其他
用nltk计算词语间的点互信息值PMI
写作缘由
今天淘宝来了一位客户,觉得jieba分词效果不好。比如“科技创新”被分成了“科技”和“创新”,类似的情况jieba很容易把一些词错分成更细的词。虽然jieba有全局、搜索、精准模式,但分别使用效果并没有改变。
这位仁兄提了个idea,我们先把文本分词,然后计算文本中词语间的关联程度,如果关联程度很高,那么这两个词很有可能是一个长词错分出来的。
idea很棒,我也觉得很有道理,不过搞了半天没实现。
这也是这篇文章的来源,
互信息概念
在概率论和信息论中,两个随机变量的互信息(Mutual Information,简称MI)是变量间相互依赖性的量度。不同于相关系数,互信息并不局限于实值随机变量,它更加一般且决定着联合分布 p(X,Y) 和分解的边缘分布的乘积 p(X)p(Y) 的相似程度。
互信息(Mutual Information)是度量两个事件集合之间的相关性(mutual dependence)。
互信息的实现
import jieba
from nltk.collocations import BigramAssocMeasures
from nltk.collocations import BigramCollocationFinder
def readdict(file):
"""
读取词典(自定义词典.txt或停止词词典.txt),返回词语列表
:return:词语列表
"""
stopword = []
fp = open(file)
for line in fp.readlines():
word = line.strip()
stopword.append(word)
return stopword
def wordlist(inputfile):
"""
读取txt文件,返回词语列表
:param inputfile: 此处为输入数据,txt文件
:return: 返回双连词列表
"""
#导入自定义词典(txt文件中一行一个词)
jieba.load_userdict('自定义词典.txt')
stopword = readdict(file='停止词词典.txt')
word_list = []
lines = open(inputfile).readlines()
for line in lines:
w_list = list(jieba.cut(line))
w_list = [w for w in w_list if w not in stopword]
word_list+=w_list
return word_list
def relevance(inputfile):
"""
输入文本数据,生成词语间关联度(PMI互信息)
:param inputfile: 输入文本数据的路径,含txt文件名
:param outputfile: 输出的词语间关联度csv文件,含csv文件名
"""
csvf = open(outputfile, 'w+', encoding='utf-8', newline='')
writer = csv.writer(csvf)
bigram_measures = BigramAssocMeasures()
finder = BigramCollocationFinder.from_words(wordlist(inputfile))
for w1w2,value in finder.score_ngrams(bigram_measures.pmi):
w1,w2=w1w2
print(w1,w2,value)
relevance(inputfile='三体.txt')
最近喜欢上用《三体》小说来说测试,没办法,macbook上只有这个txt文件。下面打印的效果很符合语言规律,数值越大,说明两个词在一起更符合我们的语言习惯,两词语依赖关系越强。
二百年 前 39.11559432
中心 半径 29.16239132875690
一幅 全息 20.328756906
一百 光年 18.623913285
主要 出路 19.851348097
他们 感到 15.443285478
些 变化 2.273145935
人 也 1.162009468
只是 初露端倪 10.391328756
即将 获得 9.384648291746
企图 劫持 9.1764523455
其他 成员 9.02648362846
使 其 9.0256394626
......
历史文章:
数据采集
【视频】有了selenium,小白也可以自豪的说:“去TMD的抓包、cookie”
【视频】快来get新技能--抓包+cookie,爬微博不再是梦