主要思想是利用三个指标,即频数、凝固度(取对数之后就是点互信息)与自由度(边界熵)来判断一个片段是否成词,并参考了苏神的代码,详见参考部分。
前奏
读取外部文章,作为一个字符串str格式
|
|
使用正则表达式,去除不需要的标点符号
一些阈值初始设定
|
|
内部凝固度
通过list()
方法把str按单字符切分,并逐字统计
|
|
假设为2-grams模型,一段文本诸如"慕容公子真厉害"
,会被依次切分为"慕容/公子/真厉"
与"容公/子真/厉害"
,合并后进行词频统计,并剔除出现次数过小的词语(限制出现频数)。
接着,再计算一个词语的内部凝固程度(取对数后即为点互信息PMI),剔除掉低于阈值的词语。
|
|
rt形式如下:
这里补充一点,点互信息(即PMI)衡量的是两个事物之间的相关性,具体公式如下:
我们知道,若两个变量独立同分布,则有$p(x,y) = p(x)p(y)$, 但若$x$与$y$高度相关,则有$p(x,y) > p(x)p(y)$,所以PMI越大,相关性高。放入体本文的任务里,具体为"段誉"
俩字经常同时出现,内部凝固程度高,所以不应该切分成'段'/'誉'
信息熵
第一步通过(.)%s(.)
的正则方式切分出左邻字与右邻字,如"慕容公子真厉害啊"
可切分成[('慕', '容公', '子'), ('真', '厉害', '啊')]
的形式(n-grams=2)
然后把我们需要的中间那列作为索引并排序!intersect1d()
方法可以找出两个列表之间的共同元素,之后计算左(右)邻信息熵。
其中pd.Series(pp[0][s]).value_counts()
为取出交集中某个词语的全部左邻字并计数,再通过cal_s()
函数计算信息熵,只取信息熵大于一定阈值的词语(如"慕容"
),右邻信息熵同样如此,最后更新结果集rt
。
|
|
关于信息熵:熟悉决策树的同学一定不陌生,在这里可理解为词语的自由运用程度。譬如"辈子"
,大部分的情况下只会出现"上辈子"
,"一辈子"
,"几辈子"
这种情况,语境自然不丰富,其左邻信息熵相对较小,故"辈子"
无法单独成词。原文中的代码如下:
最后一步
后面只需要我们在原有的词频统计表中,取出满足我们要求的词语出来,并按频数降序排序出即可。
|
|
我们来观测下输出结果