Jupyter Notebook使用Python做PMI点互信息计算

2021-8-25 08:58| 发布者: Fuller| 查看: 4305| 评论: 0

摘要: Python自然语言处理库NLTK下的Collocations模块,提供了PMI计算的方法。Collocations中有两个类BigramCollocationFinder和TrigramCollocationFinder分别可以识别2词短语和3词短语 ...

1,本Notebook背景介绍

此前介绍了一篇论文范例《基于科技政策文本的程度词典构建研究》,是针对科技政策文本的量化分析,该研究作者尝试利用PMI算法进行词语扩展,使用同义词词林筛选词语。最后结合 TextRank算法进行实验验证。经过信度和效度检验,构建的程度词典有效,得出了结合程度词典的政策文本分析细粒度优于使用单一的文本挖掘算法的结论。

那么这个PMI点互信息计算能不能在python中实现?

笔者查了一下相关资料,Python自然语言处理库NLTK下的Collocations模块,提供了PMI计算的方法。Collocations中有两个类BigramCollocationFinder和TrigramCollocationFinder分别可以识别2词短语和3词短语。

1.1,NLTK-Collocations介绍

首先可以参看NLTK官网对collocations模块的介绍,也可以参考知乎文章:NLTK-Collocations,还可以看这个NLTK官方网页上的多种情形的示例代码

NLTK-Collocations模块用于识别固定搭配,说白了就是2个词紧挨着或者3个词紧挨着。通过统计语料库中出现挨着的情形的频率,根据测量打分参数,找到符合频率要求的挨着的词,就把他们识别成一个短语。

Collocations识别搭配时,主要计算的是单个词语频率,以及词语与其上下文词语之间的共现频率。其次是对于候选搭配的合理性打分函数。其中一个是点互信息,点互信息就是衡量ngrams中的词语之间的关联性。

Collocations中有两个类BigramCollocationFinder和TrigramCollocationFinder分别可以识别2词短语和3词短语。

1.2,构造识别器

以BigramCollocationFinder为例,TrigramCollocationFinder的用法几乎一摸一样。函数原型如下:

Class nltk.collocations.BigramCollocationFinder(word_fd, bigram_fd, window_size=2)

这个构造函数用来实例化搭配识别器,更常用的是用from_words这个静态方法构建识别器,具体参数含义可以参考上面列出来的文章,其实对于新手有些难理解。干脆就直接拷贝示例代码拿来用就行了,等摸熟了再进一步理解这些参数。

常用的构造识别器的方法:

from_words(words, window_size=2)

从给定的词语序列words中,抽取连续的2grams(window_size=2)并统计频次。如果window_size>2,则会同时会抽取非连续的2grams并统计频次。

1.3,打分排序

nbest(self, score_fn, n)

此函数按照打分函数score_fn进行打分,并按照分数由高到低排列,返回topn个最优的搭配。

可以作为score_fn的方法有:

1. BigramAssocMeasures类中的方法pmi,是用互信息打分。

2. BigramAssocMeasures类中的方法bigram_measures.likelihood_ratio,显然是似然估计值打分。

今天这个Notebook,基于简单的科技新闻文本测试数据,我们就使用NLTK-Collocations模块进行PMI点互信息进行实验。

2,测试数据

我们摘取这样一段新闻:

国家发改委表示,目前来看,两轮储备投放基本实现了预期目标,社会各界普遍反映,储备投放体现了国家确保大宗商品市场供应和价格稳定的决心信心,引导了价格预期,缓解了部分行业企业的原材料成本压力。下一步,我们还将持续关注大宗商品价格走势情况,统筹利用好国内国外两种资源,综合采取多种措施,包括加大增产增供、适时储备投放、加强进出口调节、加大市场监管力度等,切实做好大宗商品保供稳价工作。

为简化测试,对新闻文本片段做处理后,以数组的形式存储,这个可以手工准备好,仅为了实验,实际应用的时候,应该用程序自动生成词数组,参看科技政策文本分词后在Jupyter Notebook中用TextRank做关键词提取

['国家发改委','表示','目前','两轮','储备投放','基本','实现','预期','目标','社会','各界','普遍','反映','储备投放','体现','国家','确保','大宗','商品','市场','供应','价格','稳定','决心','信心','引导','价格','预期','缓解','部分','行业','企业','原材料','成本','压力','','持续','关注','大宗商品','价格','走势','情况','统筹','利用','国内','国外','两种','资源','综合','采取','多种','措施','加大','增产','增供','适时','储备投放','加强','进出口','调节','加大','市场','监管','力度','切实','大宗商品','保供','稳价','工作']

原新闻见:发改委:加强市场调节,防止生猪和猪肉价格大起大落

3,第三方库

完整的安装nltk库及所有语料库的方法,见:如何在Jupyter Notebook中安装和使用NLTK

运行本Notebook,可以只安装nltk库,不用安装nltk-data,上文讲的方法主要是应对安装nltk-data遇到的问题。如果没有安装nltk,那么需要打开一个COMMAND窗口进行安装:

pip install nltk

4,本notebook所做的测试

基于测试数据,在Jupyter Notebook中使用Python做PMI点互信息计算。

代码参考了PMI点互信息计算

5,引入nltk库下的几个子模块

NLTK,全称Natural Language Toolkit,自然语言处理工具包,是NLP研究领域常用的一个Python库,由宾夕法尼亚大学的Steven Bird和Edward Loper在Python的基础上开发的一个模块,至今已有超过十万行的代码。这是一个开源项目,包含数据集、Python模块、教程等。

# coding:utf-8    

from nltk.corpus import stopwords

from nltk.tokenize import word_tokenize

from nltk.collocations import BigramAssocMeasures, BigramCollocationFinder

6,把测试数据赋值给变量words

为简化测试,我们把一段新闻内容文本做了处理,直接赋值给变量words,用于后续的PMI计算

words = ['国家发改委','表示','目前','两轮','储备投放','基本','实现','预期','目标','社会','各界','普遍','反映','储备投放','体现','国家','确保','大宗','商品','市场','供应','价格','稳定','决心','信心','引导','价格','预期','缓解','部分','行业','企业','原材料','成本','压力','','持续','关注','大宗商品','价格','走势','情况','统筹','利用','国内','国外','两种','资源','综合','采取','多种','措施','加大','增产','增供','适时','储备投放','加强','进出口','调节','加大','市场','监管','力度','切实','大宗商品','保供','稳价','工作']

7,输出显示words变量内容

print(words)

​数据结果是:

['国家发改委', '表示', '目前', '两轮', '储备投放', '基本', '实现', '预期', '目标', '社会', '各界', '普遍', '反映', '储备投放', '体现', '国家', '确保', '大宗', '商品', '市场', '供应', '价格', '稳定', '决心', '信心', '引导', '价格', '预期', '缓解', '部分', '行业', '企业', '原材料', '成本', '压力', '', '持续', '关注', '大宗商品', '价格', '走势', '情况', '统筹', '利用', '国内', '国外', '两种', '资源', '综合', '采取', '多种', '措施', '加大', '增产', '增供', '适时', '储备投放', '加强', '进出口', '调节', '加大', '市场', '监管', '力度', '切实', '大宗商品', '保供', '稳价', '工作']


8,计算PMI值并显示

bigram_measures = BigramAssocMeasures()

finder = BigramCollocationFinder.from_words(words)

print('word1  , word2,  PMI值')

for row in finder.score_ngrams(bigram_measures.pmi):

    data = (*row[0],row[1])

    if len(data[0]) > 0 and  len(data[1]) > 0:

        print(data)

​输出结果是:

word1  , word2,  PMI值

('两种', '资源', 6.10852445677817)

('企业', '原材料', 6.10852445677817)

('体现', '国家', 6.10852445677817)

('保供', '稳价', 6.10852445677817)

('信心', '引导', 6.10852445677817)

('决心', '信心', 6.10852445677817)

('利用', '国内', 6.10852445677817)

('力度', '切实', 6.10852445677817)

('加强', '进出口', 6.10852445677817)

('原材料', '成本', 6.10852445677817)

('各界', '普遍', 6.10852445677817)

('国内', '国外', 6.10852445677817)

('国外', '两种', 6.10852445677817)

('国家', '确保', 6.10852445677817)

('国家发改委', '表示', 6.10852445677817)

('基本', '实现', 6.10852445677817)

('增产', '增供', 6.10852445677817)

('增供', '适时', 6.10852445677817)

('多种', '措施', 6.10852445677817)

('大宗', '商品', 6.10852445677817)

('情况', '统筹', 6.10852445677817)

('成本', '压力', 6.10852445677817)

('持续', '关注', 6.10852445677817)

('普遍', '反映', 6.10852445677817)

('监管', '力度', 6.10852445677817)

('目前', '两轮', 6.10852445677817)

('目标', '社会', 6.10852445677817)

('确保', '大宗', 6.10852445677817)

('社会', '各界', 6.10852445677817)

('稳价', '工作', 6.10852445677817)

('稳定', '决心', 6.10852445677817)

('统筹', '利用', 6.10852445677817)

('综合', '采取', 6.10852445677817)

('缓解', '部分', 6.10852445677817)

('行业', '企业', 6.10852445677817)

('表示', '目前', 6.10852445677817)

('资源', '综合', 6.10852445677817)

('走势', '情况', 6.10852445677817)

('进出口', '调节', 6.10852445677817)

('部分', '行业', 6.10852445677817)

('采取', '多种', 6.10852445677817)

('关注', '大宗商品', 5.10852445677817)

('切实', '大宗商品', 5.10852445677817)

('加大', '增产', 5.10852445677817)

('商品', '市场', 5.10852445677817)

('大宗商品', '保供', 5.10852445677817)

('实现', '预期', 5.10852445677817)

('市场', '供应', 5.10852445677817)

('市场', '监管', 5.10852445677817)

('措施', '加大', 5.10852445677817)

('调节', '加大', 5.10852445677817)

('预期', '目标', 5.10852445677817)

('预期', '缓解', 5.10852445677817)

('两轮', '储备投放', 4.523561956057014)

('价格', '稳定', 4.523561956057014)

('价格', '走势', 4.523561956057014)

('供应', '价格', 4.523561956057014)

('储备投放', '体现', 4.523561956057014)

('储备投放', '加强', 4.523561956057014)

('储备投放', '基本', 4.523561956057014)

('反映', '储备投放', 4.523561956057014)

('引导', '价格', 4.523561956057014)

('适时', '储备投放', 4.523561956057014)

('加大', '市场', 4.10852445677817)

('价格', '预期', 3.523561956057014)

('大宗商品', '价格', 3.523561956057014)


9,输出结果解读

1. pmi计算结果是从大到小输出的。pmi越大,两个词语挨在一起的概率就越大。

2. 由于测试数据的量比较小,那么可能的结果失真就会被放大。比如,“储备投放”和“体现”,以及和“加强”,“基本”,他们实际上没有连成词组的意义,只是从频率上来说,他们一起出现的很多,这个错误是因为我们测试的语料太少了,频率不能反映实际的情况。

有兴趣的同学可以基于更大的文本去做实验,进行结果分析。

10,下载notebook

下载notebook源代码请进:使用Python做PMI点互信息计算


鲜花

握手

雷人

路过

鸡蛋

最新评论

GMT+8, 2024-12-19 00:44