用python实现新词发现程序——基于凝固度和自由度

互联网时代,信息产生的数量和传递的速度很是快,语言文字也不断变化更新,新词层出不穷。一个好的新词发现程序对作NLP(天然预言处理)来讲是很是重要的。算法

N-Gram加词频

最原始的新词算法莫过于n-gram加词频了。简单来讲就是,从大量语料中抽取连续的字的组合片断,这些字组合片断最多包含n个字,同时统计每一个字组合的频率,按照词频并设置一个阈值来判断一个字组合片断是否为词汇。数据库

该方法简单处理速度快,它的缺点也很明显,就是会把一些不是词汇但出现频率很高的字组合也当成词了。数组

凝固度和自由度

这个算法在文章《互联网时代的社会语言学:基于SNS的文本数据挖掘》 里有详细的阐述。数据结构

凝固度就是一个字组合片断里面字与字之间的紧密程度。好比“琉璃”、“榴莲”这样的词的凝固度就很是高,而“华为”、“组合”这样的词的凝固度就比较低。spa

自由度就是一个字组合片断能独立自由运用的程度。好比“巧克力”里面的“巧克”的凝固度就很高,和“巧克力”同样高,可是它自由运用的程度几乎为零,因此“巧克”不能单独成词。内存

Python实现

根据以上阐述,算法实现的步骤以下:get

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)也能发现不少低频的词汇。

 

文章首发于个人我的博客:猿人学

相关文章
相关标签/搜索