我的原文:http://blog.hijerry.cn/p/45749.html
FreqDist类
官方文档:nltk.probability.FreqDist
介绍:词的概率分布类,包含一些概率学的方法。
所在文件:probability.py
,大约在63~427行
创建
定义:__init__
(self, samples=None)
import nltk
from nltk.book import *
fdist = FreqDist(gutenberg.words('chesterton-thursday.txt'))
print fdist
outputs:
<FreqDist with 6807 samples and 69213 outcomes>
上面的69213 outcomes
是指有69213
个词,而6807 samples
是指有6807
个不重复的词。
通过下述命令可以确认这一点:
len(wds)
len(set(wds))
outputs:
69213
6807
词数量
fdist.N()
outputs:
69213
### 不重复词的数量(样本数量)
fdist.B()
outputs:
6807
生成副本
fdist2 = fdist
fdist3 = fdist.copy() #make copy
fdist == fdist2
fdist == fdist3
fdist is fdist2
fdist is fdist3
outputs:
True
True
True
False
词频率
定义:freq
(sample)
sample是词,返回值∈[0, 1]
fdist.freq('the')
outputs:
0.04754887087685839
可见,the的词频是0.0475
,也就是4.75%
词频度(出现次数)
fdist['the']
outputs:
3291
词和词频的对
items = fdist.items()
print items[:5]
outputs:
[(u'yellow', 16), (u'four', 18), (u'Does', 6), (u'conjuring', 2), (u'marching', 4)]
只出现一次的词
会一次性全部返回,下面只展示前5个。
hapaxes = fdist.hapaxes()
print hapaxes[:5]
outputs:
[u'disturb', u'buttonhole', u'himselves', u'woods', u'wavered']
出现次数最多的词
fdist.max()
outputs:
u','
u是unicode的标志,说明,
出现的最多。
这明显不符合预期,因为,
不应该被算作一个词,这会干扰我们分析文本,所以在我们创建
FreqDist实例的时候,应该要把词集
进行过滤,剔除掉标点符号。
词频分布介绍
定义:pformat
(maxlen=10)
返回一个可以代表本FreqDist
类的字符串,其实就是把高频词和频度列出来了。
maxlen
表示打印多少个高频词
fdist.pformat()
outputs:
u'FreqDist({u\',\': 3488, u\'the\': 3291, u\'.\': 2717, u\'a\': 1713, u\'of\': 1710, u\'and\': 1568, u\'"\': 1336, u\'to\': 1045, u\'in\': 888, u\'I\': 885, ...})'
频率分布图
定义:plot
(*args, **kwargs)
可以指定的参数有
title
表示图像的标题cumulative
是否累计频度
如果第一参数是整数的话,它表示展示词的数量
fdist.plot(50)
这样看起来是不是别扭呢,因为曲线肯定会下降(频度越高的词越显示在左边)
所以有时候我们需要看这些高频词加起来
占了多少,所以:
fdist.plot(50, cumulative=True)
可以发现,曲线越到后面越平缓。
频率分布表
fdist.tabulate(10)
outputs:
, the . a of and
3488 3291 2717 1713 1710 1568
累计表:
fdist.tabulate(10,cumulative=True)
outputs:
, the . a of and
3488 6779 9496 11209 12919 14487
FreqDist的应用
前面已经介绍了Text
,结合本次的FreqDist
类,我们已经可以做一些基础的NLP研究了。
理解文本的主题或风格
高频词
text1
变量保存的是《白鲸记》Text
类实例,高频词
是否可以帮助我们理解呢?
打印出它前50个词的频率分布图可以发现:
fdist1 = text1.vocab()
fdist1.plot(50, cumulative=True)
相比the
、of
这类助词,whale
的频率相对靠后,而这个词恰恰是《白鲸记》中比较重要的词,可以体现出文本的主题。
低频词
既然高频率词没啥帮助,那只出现一次的词呢?
len(fdist1.hapaxes())
outputs:
9002
emmm,貌似低频词太多了,如果不看上下文,我们也很难借助低频词来理解文本主题。
细粒度的选择词
或许长词
包含的信息比较多,是否有帮助呢?
我们考虑以下哪些成都大于15的词:
samples = set(text1)
print [w for w in samples if len(w) > 15]
outputs:
[u'hermaphroditical', u'subterraneousness', u'uninterpenetratingly',
u'irresistibleness', u'responsibilities', u'comprehensiveness',
u'uncompromisedness', u'superstitiousness', u'uncomfortableness',
u'supernaturalness', u'circumnavigating', u'cannibalistically',
u'circumnavigations', u'indispensableness', u'preternaturalness',
u'apprehensiveness', u'CIRCUMNAVIGATION', u'simultaneousness',
u'undiscriminating', u'characteristically', u'Physiognomically',
u'physiognomically', u'circumnavigation', u'indiscriminately']
似乎比低频词
的数量要少很多了,可以发现的是,长词
大多也是 低频词
,所以从这个角度来说我们忽略了短高频词
和大部分低频词
,也许寻找那些长高频词
会比较有帮助。
长高频词
下面将选择出那些长度大于7,且出现的频度也大于7的词:
print [w for w in samples if len(w) > 7 and fdist1[w] > 7]
outputs:
[u'uncertain', u'bringing', u'substance', u'cannibal', u'therefore', u'violently', u'whalebone' ...]
其实得到的结果数量还是很多,但我们已经看到了whalebone
这个词,可以大致确定下来《白鲸记》的主题了,所以寻找长高频词
可以有效的帮助我们理解文本的主题。
搭配词
文中出现的搭配词能非常明确的体现文本的类型。
下面寻找搭配词:
text1.collocations()
outputs:
Sperm Whale; Moby Dick; White Whale; old man; Captain Ahab; sperm
whale; Right Whale; Captain Peleg; New Bedford; Cape Horn; cried Ahab;
years ago; lower jaw; never mind; Father Mapple; cried Stubb; chief
mate; white whale; ivory leg; one hand
可以看到第一个词就是Sperm Whale
。
计算其他东西
词长分布
也就是计算每个长度的词出现的次数
lens = [len(w) for w in text1]
fdistw = FreqDist(lens)
fdistw.keys()
outputs:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20]
可以看到text1
中的词,最短长度是1,最长长度是20
fdistw.plot()
可以发现长度大于8和之后的的词出现的频度已经很小了
fdistw.max()
outputs:
3
可以发现,最频繁出现的词长度是3。
ConditionalFreqDist类
官方文档:nltk.probability.ConditionalFreqDist
介绍:条件频率分布类
所在文件:probablity.py
,大约在1734~2003
创建
定义:__init__
(cond_samples=None):
import nltk
from nltk.book import *
from nltk.probability import ConditionalFreqDist
cond_samples = [(len(w), w) for w in text1]
cfdist = ConditionalFreqDist(cond_samples)
print cfdist
outputs:
<ConditionalFreqDist with 19 conditions>
cond_samples
参数是元组集合,元组是(条件, 词)
,上述代码的条件是词长
,下面看看效果你就懂了:
cfdist[3]
outputs:
FreqDist({u'the': 13721, u'and': 6024, u'his': 2459, u'was': 1632, u'all': 1462, u'for': 1414, u'but': 1113, u'not': 1103, u'him': 1058, u'one': 889, ...})
这列出了所有长度为3
的词,这意味着元组的第一个元素条件
被作为了cfdist
的键,而它值是一个FreqDist
对象。
查看所有条件
cfdist.conditions()
outputs:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20]
条件频率
cfdist[3].freq('but')
outputs:
0.02216116122095454
在长度为3
的条件下,but
出现的频率是0.02216
条件频率分布图
定义:plot
(*args, **kwargs)
可以指定的参数有
samples
list 要显示的样本集合title
str 标题conditions
list 要显示的条件,默认是全部
为了便于理解,下面把cfdist
换成以文本为条件:
from nltk.corpus import brown
cond_samples = [
(genre, word)
for genre in ['news', 'romance']
for word in brown.words(categories=genre)
]
cfdist = ConditionalFreqDist(cond_samples)
print cfdist
outputs:
<ConditionalFreqDist with 2 conditions>
这里我们取了两个文体:news
和 romance
,看看两者中情态动词
的频率分布吧:
cfdist.plot(samples=['would', 'will', 'could', 'can', 'might', 'may', 'should'])
哈哈,大致符合预期呢,新闻中的will
频率异常的高。
条件频率分布表
定义:tabulate
(*args, **kwargs)
可以指定的参数有
samples
list 要显示的样本集合title
str 标题conditions
list 要显示的条件,默认是全部
cfdist.tabulate(samples=['would', 'will', 'could', 'can', 'might', 'may', 'should'])
outputs:
would will could can might may should
news 244 389 86 93 38 66 59
romance 244 43 193 74 51 11 32
ConditionalFreqDist的应用
用词分析
之前对比了news
、romance
两个文体中,情态动词的频率分布,发现了news
的will词用的频率很高。
生成随机文本
如果知道了一个词如living
,也知道了living
这个词的条件频率分布,那么可以找到最有可能出现在living
后面的那个词,这样迭代的进行计算,可以获得一个随机文本。根据上述方法,可以定义一个函数用来生成随机文本:
def random_text(cfdist, word, num=15):
for i in range(num):
print word,
word = cfdist[word].max()
我们导入《创世纪》文本:
from nltk.corpus import genesis
text = genesis.words('english-kjv.txt')
为创建条件概率分布类,我们需要cond_samples
,所以我们可以构造一些双连词
,bigrams
可以从数组
生成 双连词
:
from nltk import bigrams
cond_samples = bigrams(text)
cfdist = ConditionalFreqDist(cond_samples)
random_text(cfdist, 'living')
outputs:
living creature that he said , and the land of the land of the land
可以发现。。效果不怎么好,因为后面无限循环了。。
我们试试其他词:
random_text(cfdist, 'I')
outputs:
I will not be a son , and the land of the land of the
哈哈,最后还是无限循环了,不过挺有趣的!