0x09 文字相似性,詞袋向量化

2021-07-10 09:09:12 字數 3999 閱讀 2406

01 自然語言

人類的語言,經過了幾千年積累,已經形成了完整體系。對人而言,識別其中的意思是比較容易的。可電腦卻不同,要想識別其中的字詞是很困難的。

機器只能處理數值型別的資料,首先遇到的乙個問題,就是將文字的描述轉換成數值型別,即後面要用到的向量。只有轉換為向量後,才能通過模型來進行計算。一篇文章通常由大量的詞語組成,在轉換為向量的過程中,首先會遇到詞語的抽取問題。對抽取出的詞語,進行向量後,然後計算向量之間的相似性。

02 中文分詞

中文最小的基本單位為字,詞由字組成,詞與詞之間沒有分隔符。不同於英文,英文每個單詞之間有空格進行分隔,因此中文處理的很多地方都會用到分詞。

比如,「佛陀是徹底的覺悟者」這句話,人很容易就進行了分詞,佛陀/是/徹底/的/覺悟者/,但程式做不到。因為人的大腦在閱讀了大量的書箱後,已經在潛移默化中積累了很多的詞語,比如「佛陀」,「徹底」成詞,「的」單獨成詞。

要想讓程式識別其中的詞語「佛陀」和「徹底」,最開始大家找了很多語言學家,企圖讓計算機能像人一樣理解其中的意思,然後再來進行分詞。但經過大量的嘗試後,卻發現效果並不理想。於是基於統計學的方式開始流行。想法就是:只簡單的餵給計算機大量的文字資料,按一定的演算法,讓其進行統計,從中發現出哪些是可能組成詞語,哪些是單字。而整個過程中,計算機並不需要理解其中的意思。

通常,如果不做深入的自然語言處理(nlp),可以不用太關心分詞使用的具體的演算法。直接使用現有的庫即可。python最有名的中文分詞庫,應該算是jieba(結巴)了,這個名字很形象,結巴說話是乙個詞乙個詞的說,中間有停頓,停頓的地方便是單詞的分隔。

結巴支援幾個模式,精確模式、全模式、搜尋引擎模式,各個模式有不同的適合場景。還支援自定義詞庫,比如:「徹底覺悟的人便是覺者」這句話,正確的分詞為:徹底/覺悟/的/人/便是/覺者,其中的「覺者」,就是佛。假設你餵給程式的文件裡面不包含這個詞,jieba分詞也能通過新詞識別演算法識別出來。

假設演算法也沒有識別出來,那麼可能會把「覺者」這個詞分成「覺」和「者」,這是不合情理的。這種情況下,可以用jieba的自定義詞庫功能,將「覺者」寫入文字檔案,在呼叫結巴之前載入這個自定義詞典即可。其它的一些網路新詞彙,如「然並卵」,或者領域專用詞彙,或者人名等都可以進行自定義。

03 詞袋向量化

一段文字,究竟用乙個什麼樣的向量來表示,才能完整的表達其中的含義,這是自然語言處理的一大核心問題。比較簡單的有詞袋模型和主題模型。計算文字相似性的,可以使用最簡單的詞袋模型。

假定一篇文件中包含的資訊,可以只由其中包含的詞語來描述,並且與詞語在文件中的位置沒有關係,這便是詞袋模型,英文為bag of words,意為單詞的袋子。例如,一篇文件包含大量佛陀,菩薩等詞,和一篇包含大量的學校,班級的文件,只由他們包含的詞語便可以知道,他們描述了兩個不同的主題,因此相似性很低。

抽取文件中出現的所有詞彙,放入乙個袋子裡面,再對袋子裡的詞進行一些處理,便可以完成向量化,也即使用詞袋模型進行向量化。對袋子進行處理的方法中,最簡單的便是統計袋子裡面各個詞在各文件中出現的頻度數,下一節的countvectorizer便專門做這個事情。

與對每個詞進行單純計數不一樣的,還有乙個方法,tf-idf,詞頻和逆文件詞頻,這個主要用於設定文件中一些詞語的權重。其原理是:文件之間的區別,通常是由在兩個文件中都出現得少的詞來區別,因此這些詞語權重增加,那些公共出現的詞的權重降低,從而達到理有效區分文件的目的。

向量化需要注意的是,要保證在兩個文件在相同的向量空間裡面,也即使用的詞袋相同。 訓練資料與測試資料,必須在同一向量空間進行向量化,以保證兩個向量的維度一樣。這樣對於後續的相似性比較,才有意義。

04 詞頻向量化

使用scikit-learn中的countvectorizer來進行說明,這個方法把詞袋模型中的概念基本都介紹清楚。countvectorizer位於sklearn.feature_extraction.text中,從包名中也可以看出,這個方法用於提取文字的特徵。

其中的乙個引數,analyzer:使用字元還是單詞對文字進行切分。在中文狀態下,假定已經預先使用結巴分詞對文字進行了分詞,詞之間用空格分開。那麼使用"word"的切分方式。"char"的方式即對單字進行切分,在某些情況下會用到。假設下面句子,則可以使用char的方式:(這5個字,是寫在茶壺外面一圈的5個字,從任何乙個字開始的5種讀法,都是可以讀通,從中體會中文表達意思的強大):

可以清心也

以清心也可

清心也可以

心也可以清

也可以清心

如果你需要處理2元詞,3元詞,即認為詞與詞的順序是有一定關係的,每個詞的出現會與前面1個或者2個詞有關係,那麼就可以使用n-gram(n元詞),常用的有bi-gram(2元詞), tri-gram(3元詞)。

依然以上面的5句話為例子,使用每個字為乙個詞(char的方式 ),且使用2元分割,則第一句話的分割為: 可以-以清-清心-心也,第二句話的分割為:以清-清心-心也-也可,其它類似。引數ngram_range即用來指定最小的元數和最大的元數。

回到countvectorizer這個方法上來,count即為計數的意思,假定要向量化上面「可以清心也」的前兩句,使用char的分割,ngram_range使用(2,2),即只使用2元組合,則詞袋為兩個句子中的全部詞語。詞袋為:「可以,以清,清心,心也,也可」,共6個詞。對照這個詞袋,第一句的向量為:1,1, 1,1,1,0,第二名為:0,1,1,1,1,1。這裡全為1和0,是因為我們句子很短,詞都只出現1次或者不出現,實際應用中可以大於1,這便是count的意義。當然,如果只關心詞語是否出現,而不關心詞出現的次數,可以加乙個引數: binary=true,這個引數在一些實際問題上比較有用。

上面用了分詞和分割兩個描述,分詞是專門針對中文的,而分割是針對countvectorizer這個方法的。處理中文時,將中文進行分詞後,使用空格進行分隔,上面方法可以直接處理。如果詞中有自定義的詞,而自定義的詞中有特殊特號,預設的token_pattern可能不能滿足,此時需要自定義這個正規表示式。token_pattern的預設的正則為:(?u)\b\w\w+\b, 要求單詞最少兩個字元,以單詞的分界進行判斷。

在scikit-learn的原始碼中,是這樣的兩條語句:

token_pattern =re.compile(self

.token_pattern)

return lambda doc: token_pattern.findall(doc)

如果修改了正規表示式,可以使用re.findall(string, pattern)來測試在分詞的基礎上的分割,看是否滿足需求。

05 向量相似性

將文字轉換為向量後,計算向量的相似性相對而言就比較簡單了。根據具體的問題,選擇一種合適的相似性度量即可。在選擇相似性的時候,也可以嘗試多種,然後選擇一種最合適的。

相似性度量(similarity)的方式有很多種,最常用的當然是空間中的距離度量。剩下的還有常見的余弦相似性,街區距離,傑卡德相似係數等等。scikit-learn中兩個主要地方描述了相似性度量,乙個是近鄰方法中的sklearn.neighbors.distancemetric,另乙個是度量相關的sklearn.metrics.pairwise.pairwise_distances。

另外,如果要自己實現相似性的方法,通常而言,需要滿足以下四點:

非負性:相似性不可以為負數;

相等為零:當且僅當兩個向量相等時,相似性為0;

對稱性:a與b的相似性等於b與a的相似性;

三角不等式:d(x, y) + d(y, z) >= d(x, z),類似於三角形兩邊之和大於(等於)第三邊;

在一般性的分類、聚類中,計算相似性度量之前,還需要考慮資料的量綱,盡量在相同的值域內。比如乙個特徵的取值範圍為1000到2000,另外乙個特徵的取值範圍為5到10,那麼在計算相似性距離的時候,第乙個特徵會明顯作為主導,第二個特徵起到的作用就非常小。此時對資料進行歸一化處理,將兩個特徵的範圍都縮放到0到1或者-1到1,再進行相似性計算,就很有必要了。

CSS 4 文字相關屬性

1.color文字顏色三種表示 英語單詞 但是範圍太小了,工作中用得不多 例子 color red 單詞 red紅,blue藍,green綠,yellow黃,pin rgb方式設定 比例的範圍 0 255 例子 color rgb 255,0,0 color rgb 100 0 0 都要是百分號才行...

逆向 1 彙編 0x09 JCC

0x00 常用標誌位 狀態標誌 位 標誌 含義 通途 0 cf 進製標誌 無符號數最高位進製 借位 進製 借位 1 2 pf 奇偶標誌 常用於資料傳遞,奇偶校驗 最低位元組偶數個1 1 4 af 輔助進製 bcd算術運算中使用 算術操作結果第三位進製 借位 1 6 zf 0標誌 常與cmp test...

Lucene原始碼 二 文字相似度TF IDF原理

lucene中tf idf的計算公式與普通的tf idf不一樣。學習之後,感覺lucene的計算方法更加合理,考慮得更加周全。q query,即搜尋內容,例如 github d document,即文件內容,例如 i like github 即我們的搜尋內容 github 跟文件內容 i like ...