摘要:機(jī)器學(xué)習(xí)處理文字、語(yǔ)音住诸、圖片驾胆、視頻等任務(wù),很重要的一點(diǎn)就是從原始信息中提取出機(jī)器可以理解的特征贱呐。一篇文章通常由大量的詞語(yǔ)組成丧诺,在轉(zhuǎn)換為向量的過(guò)程中,首先便會(huì)遇到抽取詞語(yǔ)的問(wèn)題吼句。對(duì)抽取出的詞語(yǔ)锅必,進(jìn)行向量后,然后便可以計(jì)算向量之間的相似性了惕艳。
人類的語(yǔ)言搞隐,經(jīng)過(guò)了幾千年積累,已經(jīng)形成了完整體系远搪。對(duì)人而言劣纲,識(shí)別其中的意思是比較容易的∷ⅲ可電腦卻不同癞季,要想識(shí)別其中的字詞是很困難的。
自然語(yǔ)言處理中倘潜,最簡(jiǎn)單的是判斷兩個(gè)文本的相似性绷柒。簡(jiǎn)單說(shuō),就是兩段話或者兩篇文檔涮因,判斷他們是否表達(dá)相同的意思废睦。又或者,發(fā)表了一篇論文养泡,論文審核的人會(huì)去論文庫(kù)里面搜索是否涉及抄襲嗜湃。再比如奈应,把10篇文檔按內(nèi)容描述的大意分成3個(gè)類別,即判斷文檔之間的相似性购披,把相似性高的聚在一起杖挣,這是簡(jiǎn)單的文檔聚類。
機(jī)器處理文本刚陡,最重要的是提取文本的特征惩妇。擴(kuò)展開(kāi)來(lái),機(jī)器學(xué)習(xí)的很多任務(wù)都需要提取特征橘荠,提取出來(lái)的特征好壞屿附,很大程序上決定了任務(wù)結(jié)果的好壞。機(jī)器學(xué)習(xí)處理文字哥童、語(yǔ)音挺份、圖片、視頻等任務(wù)贮懈,很重要的就是從原始信息中提取出機(jī)器可以理解的特征匀泊,這也是基于自動(dòng)特征提取的深度學(xué)習(xí)算法能火起來(lái)的主要原因。
機(jī)器只能處理數(shù)值類型的數(shù)據(jù)朵你,首先遇到的一個(gè)問(wèn)題各聘,就是將文字的描述轉(zhuǎn)換成數(shù)值類型,即后面要用到的向量抡医。只有轉(zhuǎn)換為向量后躲因,才能通過(guò)模型來(lái)進(jìn)行計(jì)算。一篇文章通常由大量的詞語(yǔ)組成忌傻,在轉(zhuǎn)換為向量的過(guò)程中大脉,首先會(huì)遇到詞語(yǔ)的抽取問(wèn)題。對(duì)抽取出的詞語(yǔ)水孩,進(jìn)行向量后镰矿,然后計(jì)算向量之間的相似性。
02 中文分詞
中文最小的基本單位為字俘种,詞由字組成秤标,詞與詞之間沒(méi)有分隔符。不同于英文宙刘,英文每個(gè)單詞之間有空格進(jìn)行分隔苍姜,因此中文處理的很多地方都會(huì)用到分詞悬包。
比如,“佛陀是徹底的覺(jué)悟者”這句話,人很容易就進(jìn)行了分詞,佛陀/是/徹底/的/覺(jué)悟者/吊输,但程序做不到饶号。因?yàn)槿说拇竽X在閱讀了大量的書箱后季蚂,已經(jīng)在潛移默化中積累了很多的詞語(yǔ),比如“佛陀”扭屁,“徹底”成詞算谈,“的”單獨(dú)成詞。
要想讓程序識(shí)別其中的詞語(yǔ)“佛陀”和“徹底”料滥,最開(kāi)始大家找了很多語(yǔ)言學(xué)家然眼,企圖讓計(jì)算機(jī)能像人一樣理解其中的意思,然后再來(lái)進(jìn)行分詞葵腹。但經(jīng)過(guò)大量的嘗試后高每,卻發(fā)現(xiàn)效果并不理想。于是基于統(tǒng)計(jì)學(xué)的方式開(kāi)始流行践宴。想法就是:只簡(jiǎn)單的喂給計(jì)算機(jī)大量的文本資料鲸匿,按一定的算法,讓其進(jìn)行統(tǒng)計(jì)阻肩,從中發(fā)現(xiàn)出哪些是可能組成詞語(yǔ)带欢,哪些是單字。而整個(gè)過(guò)程中烤惊,計(jì)算機(jī)并不需要理解其中的意思乔煞。
通常,如果不做深入的自然語(yǔ)言處理(NLP)撕氧,可以不用太關(guān)心分詞使用的具體的算法瘤缩。直接使用現(xiàn)有的庫(kù)即可。Python最有名的中文分詞庫(kù)伦泥,應(yīng)該算是Jieba(結(jié)巴)了剥啤,這個(gè)名字很形象,結(jié)巴說(shuō)話是一個(gè)詞一個(gè)詞的說(shuō)不脯,中間有停頓府怯,停頓的地方便是單詞的分隔。
結(jié)巴支持幾個(gè)模式防楷,精確模式牺丙、全模式、搜索引擎模式,各個(gè)模式有不同的適合場(chǎng)景冲簿。還支持自定義詞庫(kù)粟判,比如:“徹底覺(jué)悟的人便是覺(jué)者”這句話,正確的分詞為:徹底/覺(jué)悟/的/人/便是/覺(jué)者峦剔,其中的“覺(jué)者”档礁,就是佛。假設(shè)你喂給程序的文檔里面不包含這個(gè)詞吝沫,Jieba分詞也能通過(guò)新詞識(shí)別算法識(shí)別出來(lái)呻澜。
假設(shè)算法也沒(méi)有識(shí)別出來(lái),那么可能會(huì)把“覺(jué)者”這個(gè)詞分成“覺(jué)”和“者”惨险,這是不合情理的。這種情況下辫愉,可以用Jieba的自定義詞庫(kù)功能,將“覺(jué)者”寫入文本文件窘疮,在調(diào)用結(jié)巴之前加載這個(gè)自定義詞典即可闸衫。其它的一些網(wǎng)絡(luò)新詞匯诽嘉,如“然并卵”,或者領(lǐng)域?qū)S迷~匯骄酗,或者人名等都可以進(jìn)行自定義。
03 詞袋向量化
一段文本趋翻,究竟用一個(gè)什么樣的向量來(lái)表示盒蟆,才能完整的表達(dá)其中的含義,這是自然語(yǔ)言處理的一大核心問(wèn)題讨惩。比較簡(jiǎn)單的有詞袋模型和主題模型寒屯。計(jì)算文本相似性的,可以使用最簡(jiǎn)單的詞袋模型处面。
假定一篇文檔中包含的信息魂角,可以只由其中包含的詞語(yǔ)來(lái)描述,并且與詞語(yǔ)在文檔中的位置沒(méi)有關(guān)系,這便是詞袋模型传于,英文為bag of words,意為單詞的袋子平挑。例如系草,一篇文檔包含大量佛陀,菩薩等詞唇辨,和一篇包含大量的學(xué)校能耻,班級(jí)的文檔,只由他們包含的詞語(yǔ)便可以知道饿幅,他們描述了兩個(gè)不同的主題戒职,因此相似性很低。
抽取文檔中出現(xiàn)的所有詞匯磕秤,放入一個(gè)袋子里面蚓曼,再對(duì)袋子里的詞進(jìn)行一些處理,便可以完成向量化床绪,也即使用詞袋模型進(jìn)行向量化。對(duì)袋子進(jìn)行處理的方法中膀斋,最簡(jiǎn)單的便是統(tǒng)計(jì)袋子里面各個(gè)詞在各文檔中出現(xiàn)的頻度數(shù)仰担,下一節(jié)的CountVectorizer便專門做這個(gè)事情绩社。
與對(duì)每個(gè)詞進(jìn)行單純計(jì)數(shù)不一樣的,還有一個(gè)方法贮尉,TF-IDF朴沿,詞頻和逆文檔詞頻,這個(gè)主要用于設(shè)置文檔中一些詞語(yǔ)的權(quán)重魏铅。其原理是:文檔之間的區(qū)別坚芜,通常是由在兩個(gè)文檔中都出現(xiàn)得少的詞來(lái)區(qū)別,因此這些詞語(yǔ)權(quán)重增加路操,那些公共出現(xiàn)的詞的權(quán)重降低千贯,從而達(dá)到理有效區(qū)分文檔的目的。
向量化需要注意的是魁袜,要保證在兩個(gè)文檔在相同的向量空間里面敦第,也即使用的詞袋相同。 訓(xùn)練數(shù)據(jù)與測(cè)試數(shù)據(jù)鞠呈,必須在同一向量空間進(jìn)行向量化蚁吝,以保證兩個(gè)向量的維度一樣。這樣對(duì)于后續(xù)的相似性比較窘茁,才有意義。
04 詞頻向量化
使用scikit-learn中的CountVectorizer來(lái)進(jìn)行說(shuō)明房待,這個(gè)方法把詞袋模型中的概念基本都介紹清楚驼抹。CountVectorizer位于sklearn.feature_extraction.text中,從包名中也可以看出洼怔,這個(gè)方法用于提取文本的特征左驾。
其中的一個(gè)參數(shù)诡右,analyzer:使用字符還是單詞對(duì)文本進(jìn)行切分轻猖。在中文狀態(tài)下,假定已經(jīng)預(yù)先使用結(jié)巴分詞對(duì)文本進(jìn)行了分詞猜煮,詞之間用空格分開(kāi)败许。那么使用"word"的切分方式。"char"的方式即對(duì)單字進(jìn)行切分愕撰,在某些情況下會(huì)用到搞挣。假設(shè)下面句子音羞,則可以使用char的方式:(這5個(gè)字,是寫在茶壺外面一圈的5個(gè)字舍肠,從任何一個(gè)字開(kāi)始的5種讀法,都是可以讀通貌夕,從中體會(huì)中文表達(dá)意思的強(qiáng)大):
可以清心也
以清心也可
清心也可以
心也可以清
也可以清心
如果你需要處理2元詞,3元詞险毁,即認(rèn)為詞與詞的順序是有一定關(guān)系的们童,每個(gè)詞的出現(xiàn)會(huì)與前面1個(gè)或者2個(gè)詞有關(guān)系,那么就可以使用n-gram(n元詞)跷跪,常用的有bi-gram(2元詞)齐板, tri-gram(3元詞)。
依然以上面的5句話為例子橡羞,使用每個(gè)字為一個(gè)詞(char的方式 )卿泽,且使用2元分割滋觉,則第一句話的分割為: 可以-以清-清心-心也,第二句話的分割為:以清-清心-心也-也可第租,其它類似我纪。參數(shù)ngram_range即用來(lái)指定最小的元數(shù)和最大的元數(shù)。
回到CountVectorizer這個(gè)方法上來(lái)璧诵,Count即為計(jì)數(shù)的意思仇冯,假定要向量化上面“可以清心也”的前兩句,使用char的分割比被,ngram_range使用(2,2)等缀,即只使用2元組合,則詞袋為兩個(gè)句子中的全部詞語(yǔ)笤妙。詞袋為:“可以噪裕,以清,清心召衔,心也苍凛,也可”,共6個(gè)詞醇蝴。對(duì)照這個(gè)詞袋毒姨,第一句的向量為:1弧呐,1嵌纲, 1,1鸠蚪,1师溅,0,第二名為:0蘸鲸,1窿锉,1膝舅,1仍稀,1埂息,1。這里全為1和0崭篡,是因?yàn)槲覀兙渥雍芏塘鹕粒~都只出現(xiàn)1次或者不出現(xiàn)砸彬,實(shí)際應(yīng)用中可以大于1,這便是Count的意義蛀蜜。當(dāng)然增蹭,如果只關(guān)心詞語(yǔ)是否出現(xiàn),而不關(guān)心詞出現(xiàn)的次數(shù)霎奢,可以加一個(gè)參數(shù): binary=True饼灿,這個(gè)參數(shù)在一些實(shí)際問(wèn)題上比較有用碍彭。
上面用了分詞和分割兩個(gè)描述,分詞是專門針對(duì)中文的舞箍,而分割是針對(duì)CountVectorizer這個(gè)方法的皆疹。處理中文時(shí),將中文進(jìn)行分詞后软族,使用空格進(jìn)行分隔,上面方法可以直接處理立砸。如果詞中有自定義的詞,而自定義的詞中有特殊特號(hào)浊闪,默認(rèn)的token_pattern可能不能滿足螺戳,此時(shí)需要自定義這個(gè)正則表達(dá)式倔幼。token_pattern的默認(rèn)的正則為:(?u)\b\w\w+\b, 要求單詞最少兩個(gè)字符翩腐,以單詞的分界進(jìn)行判斷膏燃。
在Scikit-learn的源碼中,是這樣的兩條語(yǔ)句:
token_pattern =re.compile(self.token_pattern)
return lambda doc: token_pattern.findall(doc)
如果修改了正則表達(dá)式等龙,可以使用re.findall(string, pattern)來(lái)測(cè)試在分詞的基礎(chǔ)上的分割伶贰,看是否滿足需求。
05 向量相似性
將文字轉(zhuǎn)換為向量后暴备,計(jì)算向量的相似性相對(duì)而言就比較簡(jiǎn)單了们豌。根據(jù)具體的問(wèn)題望迎,選擇一種合適的相似性度量即可凌外。在選擇相似性的時(shí)候,也可以嘗試多種摄欲,然后選擇一種最合適的。
相似性度量(similarity)的方式有很多種胸墙,最常用的當(dāng)然是空間中的距離度量。剩下的還有常見(jiàn)的余弦相似性但骨,街區(qū)距離,杰卡德相似系數(shù)等等校哎。Scikit-learn中兩個(gè)主要地方描述了相似性度量箫锤,一個(gè)是近鄰方法中的sklearn.neighbors.DistanceMetric,另一個(gè)是度量相關(guān)的sklearn.metrics.pairwise.pairwise_distances谚攒。
在選擇相似性度量的時(shí)候,需要參考向量的類型野蝇,在scikit-learn中括儒,按向量的數(shù)據(jù)類型,區(qū)分三種類型:實(shí)數(shù)型乍狐、整數(shù)型固逗、真假二值型。比如杰卡德相似系數(shù)惜傲,就只適用于真假二值型的數(shù)據(jù)。
另外盗誊,如果要自己實(shí)現(xiàn)相似性的方法哈踱,通常而言,需要滿足以下四點(diǎn):
- 非負(fù)性:相似性不可以為負(fù)數(shù)吻贿;
- 相等為零:當(dāng)且僅當(dāng)兩個(gè)向量相等時(shí)哑子,相似性為0;
- 對(duì)稱性:A與B的相似性等于B與A的相似性帐要;
- 三角不等式:d(x, y) + d(y, z) >= d(x, z)弥奸,類似于三角形兩邊之和大于(等于)第三邊;
在一般性的分類赠橙、聚類中愤炸,計(jì)算相似性度量之前,還需要考慮數(shù)據(jù)的量綱凤薛,盡量在相同的值域內(nèi)诞仓。比如一個(gè)特征的取值范圍為1000到2000,另外一個(gè)特征的取值范圍為5到10活玲,那么在計(jì)算相似性距離的時(shí)候谍婉,第一個(gè)特征會(huì)明顯作為主導(dǎo),第二個(gè)特征起到的作用就非常小珍剑。此時(shí)對(duì)數(shù)據(jù)進(jìn)行歸一化處理死陆,將兩個(gè)特征的范圍都縮放到0到1或者-1到1,再進(jìn)行相似性計(jì)算别凤,就很有必要了领虹。