用python實現新詞發現程序——基於凝固度和自由度


互聯網時代,信息產生的數量和傳遞的速度非常快,語言文字也不斷變化更新,新詞層出不窮。一個好的新詞發現程序對做NLP(自然預言處理)來說是非常重要的。

N-Gram加詞頻

最原始的新詞算法莫過於n-gram加詞頻了。簡單來說就是,從大量語料中抽取連續的字的組合片段,這些字組合片段最多包含n個字,同時統計每個字組合的頻率,按照詞頻並設置一個閾值來判斷一個字組合片段是否為詞匯。

該方法簡單處理速度快,它的缺點也很明顯,就是會把一些不是詞匯但出現頻率很高的字組合也當成詞了。

凝固度和自由度

這個算法在文章《互聯網時代的社會語言學:基於SNS的文本數據挖掘》 里有詳細的闡述。

凝固度就是一個字組合片段里面字與字之間的緊密程度。比如“琉璃”、“榴蓮”這樣的詞的凝固度就非常高,而“華為”、“組合”這樣的詞的凝固度就比較低。

自由度就是一個字組合片段能獨立自由運用的程度。比如“巧克力”里面的“巧克”的凝固度就很高,和“巧克力”一樣高,但是它自由運用的程度幾乎為零,所以“巧克”不能單獨成詞。

Python實現

根據以上闡述,算法實現的步驟如下:

1. n-gram統計字組合的頻率

如果文本量很小,可以直接用Python的dict來統計n-gram及其頻率。一段文本n-gram出來的字組合的大小大約是原始文本的(1+n)*n/2倍,字組合的數量也非常驚人。比如,“中華人民共和國”的首字n-gram是(n=5):


中華
中華人
中華人民
中華人民共

n-gram統計字組合頻率的同時還要統計字組合的左右鄰居,這個用來計算自由度。

如果文本量再大一些,Python的dict經常會碰到最好使用trie tree這樣的數據結構。雙數組Trie Tree有很多非常好的開源實現,比如,cedar、darts等等。Trie Tree使用的好處是,它天然包含了字組合的右鄰居信息,因為這個數據結構一般是前綴樹。要統計左鄰居信息時,只需要把字組合倒序放入另外一個Trie Tree即可。
使用cedar Trie Tree的時候,5-gram統計30M的文本大約使用6GB左右的內存。

如果文本量更大,這就要借助硬盤了,可以使用leveldb這樣的key-value數據庫來實現。實驗下來,trie tree統計30M的文本用幾十秒,而同樣的用leveldb統計卻要6個多小時!!!應該還有比leveldb更合適的數據庫來做這件事情,有時間再說。
當然,為了發現新詞,幾十MB的文本文本足夠了。

2. 計算字組合的凝固度;

有了上述的統計結果,計算每個字組合的凝固度就比較簡單了。
首先,把字組合切分成不同的組合對,比如’abcd’可以拆成(‘a’, ‘bcd’), (‘ab’, ‘cd’), (‘abc’, ‘d’),
然后,計算每個組合對的凝固度:D(s1, s2) = P(s1s2) / (P(s1) * P(s2))
最后,取這些組合對凝固度中最小的那個為整個字組合的凝固度。

3. 計算字組合的自由度;

分別計算它的左鄰居信息熵和右鄰居信息熵,取其中較小的為該組合的自由度。

4. 閾值的選擇

整個過程涉及到三個閾值的選擇:

  • 組合的詞頻:頻率很低的組合成詞的可能性很小
  • 組合的凝固度:凝固度越大成詞的可能性越大
  • 組合的自由度:自由度越大成詞的可能性越大

經驗值:30M文本,詞頻>200, 凝固度>10**(n-1), 自由度>1.5

小竅門:詞頻>30, 凝固度>20**(n-1)也能發現很多低頻的詞匯。

 

文章首發於我的個人博客:猿人學


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM