我的原文: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)
可以指定的参数有
sampleslist 要显示的样本集合titlestr 标题conditionslist 要显示的条件,默认是全部
为了便于理解,下面把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)
可以指定的参数有
sampleslist 要显示的样本集合titlestr 标题conditionslist 要显示的条件,默认是全部
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
哈哈,最后还是无限循环了,不过挺有趣的!
4634

被折叠的 条评论
为什么被折叠?



