互聯網時代,信息產生的數量和傳遞的速度很是快,語言文字也不斷變化更新,新詞層出不窮。一個好的新詞發現程序對作NLP(天然預言處理)來講是很是重要的。算法
最原始的新詞算法莫過於n-gram加詞頻了。簡單來講就是,從大量語料中抽取連續的字的組合片斷,這些字組合片斷最多包含n個字,同時統計每一個字組合的頻率,按照詞頻並設置一個閾值來判斷一個字組合片斷是否爲詞彙。數據庫
該方法簡單處理速度快,它的缺點也很明顯,就是會把一些不是詞彙但出現頻率很高的字組合也當成詞了。數組
這個算法在文章《互聯網時代的社會語言學:基於SNS的文本數據挖掘》 裏有詳細的闡述。數據結構
凝固度就是一個字組合片斷裏面字與字之間的緊密程度。好比「琉璃」、「榴蓮」這樣的詞的凝固度就很是高,而「華爲」、「組合」這樣的詞的凝固度就比較低。python爬蟲
自由度就是一個字組合片斷能獨立自由運用的程度。好比「巧克力」裏面的「巧克」的凝固度就很高,和「巧克力」同樣高,可是它自由運用的程度幾乎爲零,因此「巧克」不能單獨成詞。學習
根據以上闡述,算法實現的步驟以下:網站
若是文本量很小,能夠直接用Python的dict來統計n-gram及其頻率。一段文本n-gram出來的字組合的大小大約是原始文本的(1+n)*n/2倍,字組合的數量也很是驚人。好比,「中華人民共和國」的首字n-gram是(n=5):spa
中
中華
中華人
中華人民
中華人民共blog
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的文本文本足夠了。
有了上述的統計結果,計算每一個字組合的凝固度就比較簡單了。
首先,把字組合切分紅不一樣的組合對,好比’abcd’能夠拆成(‘a’, ‘bcd’), (‘ab’, ‘cd’), (‘abc’, ‘d’),
而後,計算每一個組合對的凝固度:D(s1, s2) = P(s1s2) / (P(s1) * P(s2))
最後,取這些組合對凝固度中最小的那個爲整個字組合的凝固度。
分別計算它的左鄰居信息熵和右鄰居信息熵,取其中較小的爲該組合的自由度。
整個過程涉及到三個閾值的選擇:
經驗值:30M文本,詞頻>200, 凝固度>10**(n-1), 自由度>1.5
小竅門:詞頻>30, 凝固度>20**(n-1)也能發現不少低頻的詞彙。