第二章 获得文本语料和词汇资源
2.2 条件频率分布
1条件和事件
频率分布计算观察到的事件,如文本中出现的词汇。条件频率分布需要给每个时间关联一个条件,所以不是处理一个词序列,我们必须处理的是一个配对序列。每对的形式是:(条件,事件) 。
2按文体计数词汇
FreqDist()以一个简单的链表作为输入,ConditionalFreqDist()以一个配对链表作为输入。
参见代码模块NltkTest68. CFDTest
说明很多标点符号是真的没有用的,数词,量词,代词,连词这些也是,没有什么sense,只会影响判断,所以自然语言处理中去除停用词确实是必要的。
3 绘制分布图和分布表
ConditionalFreqDist 为制表和绘图提供了一些有用的方法。
cfd1.plot()
cfd2.tabulate()
4使用双连词生成随机文本
随机找一个词打头然后从文本中找到他的双连词,再以这个词作为查询条件找到其双连词,这就是generate_model() 函数的工作原理了吧。
具体函数参看p70
#!/usr/python/bin
#Filename:NltkTest68,一些关于语料库使用的测试
importnltk
fromnltk.corpus import brown
fromnltk.corpus import inaugural
fromnltk.corpus import udhr
classNltkTest68:
def __init__(self):
print 'Initing...'
def CFDTest(self):
'''对应p68的小测试程序'''
## cfd = nltk.ConditionalFreqDist(\
## (genre, word)\
## for genre in brown.categories()\
## for word in brown.words(categories=genre))
genre_word = [(genre, word)\
for genre in ['news','romance']\
for word inbrown.words(categories=genre)]
print len(genre_word)
print genre_word[:4]
print genre_word[-4:]
cfd =nltk.ConditionalFreqDist(genre_word)
print cfd.conditions()
print cfd['news']
print cfd['romance']
## print list(cfd['romance'])
print cfd['romance']['could']
def PlotTest(self):
'''plot和tabulate两个画图函数的测试'''
cfd1 = nltk.ConditionalFreqDist(\
(target, fileid[:4])\
for fileid in inaugural.fileids()\
for w in inaugural.words(fileid)\
for target in ['america','citizen']\
if w.lower().startswith(target))
cfd1.plot()
languages = ['Chickasaw', 'English','German_Deutsch',\
'Greenlandic_Inuktikut','Hungarian_Magyar', 'Ibibio_Efik']
cfd2=nltk.ConditionalFreqDist(\
(lang,len(word))\
for lang in languages\
for word in udhr.words(lang +'-Latin1'))
cfd2.tabulate(conditions=['English','German_Deutsch'],\
samples=range(10),cumulative=True)
def BigramsTest(self,startWord,text):
'''可以出结果但是运行后会出现程序不响应,不知道是不是我机器的原因'''
bigrams = nltk.bigrams(text)
cfd = nltk.ConditionalFreqDist(bigrams)
print cfd[startWord]
for i in range(15):
print startWord
startWord = cfd[startWord].max()
print bigrams
nt68=NltkTest68()
#nt68.CFDTest()
#nt68.PlotTest()
#text= nltk.corpus.genesis.words('english-kjv.txt')
#nt68.BigramsTest('living',text)
2.3 更多关于 Python :代码重用
1 模块化
在一个文件中的变量和函数定义的集合被称为一个 Python 模块(module)。 相关模块集合称为一个包(package) 。 处理布朗语料库的 NLTK 代码是一个模块,处理各种不同语料库的代码的集合是一个包。NLTK 的本身是包的集合,有时被称为一个库(library)。
但凡能重用的都必须写成类或者函数,避免二次开发,简化维护过程。另外,不知道Python该采取什么风格才好,延用Java中使用的MVC应该是可以的。我觉得写程序最怕的就是混乱,逻辑不清,部署不明太麻烦了。
2.4 词典资源
1 基本定义
词典或者词典资源是一个词和/或短语以及一些相关信息的集合。一个词项包括词目(也叫词条)以及其他附加信息,例如:词性和词意定义。两个不同的词拼写相同被称为同音异义词。一种简单的词典资源是除了一个词汇列表外什么也没有。复杂的词典资源包括在词汇项内和跨词汇项的复杂的结构。
2 词汇列表语料库
NLTK 包括一些仅仅包含词汇列表的语料库。词汇语料库是 Unix 中的/usr/dict/words 文
件,被一些拼写检查程序使用。
通过NltkTest74. unusual_word()的结果可以得知,这种不规范的拼写在chat数据中比正规文本出现的要多的多,这也就是为什么社会化媒体的文本数据不好处理,大家敲东西都比较随意,再加上火星文,闪光字什么的,网络流行语什么的,简直就没法好好分析啊。这就要求在预处理过程中需要更加细致的操作了。
还有一个停用词语料库,就是那些高频词汇,如:the, to,我们有时在进一步的处理之前想要将它们从文档中过滤。停用词通常几乎没有什么词汇内容,而它们的出现会使区分文本变困难。
在执行NltkTest74. StopWordsTest()时第一次显示的结果是0,肯定是不对的,看了一下原来是忘了import from __future__ import division了,被当成整数除法了。加了以后的结果是
跟书里的0.65997695393285261不一样啊,我觉得这应该是因为语料库版本的问题,现代人估计是更追求效率在文本中使用停用词少了。
姓名很多时候是不要计入考虑的,但是有的时候在类似于命名实体分析,指代消歧的任务中却又是最重要的。所以试一下nltk的names库功能。代码见NltkTest74.NamesTest()
建议在打印词表的时候都使用切片操作,否则太多了,输出个[:20]其实也就够了,足够验证了。
我的英文名是M打头的是male占多数的地方,还是蛮正常的。
3发音的词典
不做这方面的研究,不过看到nltk收录的这么丰富还是很值得肯定的,国外的开源做的就是好啊,国内的一家家守着自己的语料和代码,怎么求都不给,代码是知识产权也就算了,语料也不公开,怎么跟你一起愉快的玩耍啊。
4词汇工具:Toolbox 和 Shoebox
一个 Toolbox 文件由一个大量条目的集合组成,其中每个条目由一个或多个字段组成。大多数字段都是可选的或重复的,这意味着这个词汇资源不能作为一个表格或电子表格来处理。
2.5 Wordnet
1 基本概念
WordNet 是面向语义的英语词典, 类似与传统辞典, 但具有更丰富的结构。 NLTK 中包括英语 WordNet,共有 155,287 个词和 117,659 个同义词集合。这个词典的优秀有目共睹但是目前的很多论文里都提到,这个词典在处理较新的文本数据时已经出现了不完备的问题,导致分析处理的准确性降低了。所以用的时候必须得考虑到这一点,评价这个缺陷对结果的影响有多少。
处理同义词、近义词和多义词是自然语言处理中非常麻烦的一件事,因为不考虑其相关性会降低对文本相似度的计算准确性,考虑的话就必须有一个完备的词表。但还是有疑问,相似的程度可以度量吗,一个词的同义词是一个多义词那么替换的影响是提高了还是降低了准确性,刚入门,一时分不清楚。
synset 或“同义词集”:意义相同的词(或“词条” )的集合。虽然定义帮助人们了解一个同义词集的本意,同义词集中的词往往对我们的程序更有用。我们可以得到指定同义词集的所有词条,查找特定的词条,得到一个词条对应的同义词集,也可以得到一个词条的“名字”。
WordNet 的同义词集对应于抽象的概念, 它们并不总是有对应的英语词汇。 这些概念在层次结构中相互联系在一起。一些概念也很一般, 如实体、状态、事件;这些被称为独一
二的根同义词集。
不去应用它,无法完全熟悉它的功能,就像有辆车,你有说明书并不代表你了解它,你得开了才知道走的怎么样,修的时候才知道动力原理怎么样。
2更多的词汇关系
上位词和下位词被称为词汇关系,因为它们是同义集之间的关系。这个关系定位上下为“是一个”层次。WordNet 网络另一个重要的漫游方式是从物品到它们的部件(部分)或到它们被包含其中的东西(整体)。
3语义相似度
#!/usr/python/bin
#Filename:NltkTest74,一些关于词典使用的测试
from__future__ import division
importnltk
fromnltk.corpus import stopwords
fromnltk.corpus import toolbox
fromnltk.corpus import wordnet as wn
classNltkTest74:
def __init__(self):
print 'Initing...'
def unusual_words(self,text):
'''书中自带的错误拼写监测程序'''
text_vocab = set(w.lower() for w intext if w.isalpha())
english_vocab = set(w.lower() for w innltk.corpus.words.words())
unusual =text_vocab.difference(english_vocab)
return sorted(unusual)
def StopWordsTest(self,text):
stopwords =nltk.corpus.stopwords.words('english')
print stopwords[:20]
content = [w for w in text if w.lower()not in stopwords]
rate=100*len(content)/len(text)
return '去掉停用词还剩%%%f的词' %rate
def NamesTest(self):
'''男生女生'''
names = nltk.corpus.names
print names.fileids()
male_names = names.words('male.txt')
female_names =names.words('female.txt')
midGender=[w for w in male_names if win female_names]
print midGender[:20]
cfd = nltk.ConditionalFreqDist(\
(fileid, name[-1])\
for fileid in names.fileids()\
for name in names.words(fileid))
cfd.plot()
def DicTest(self):
printtoolbox.entries('rotokas.dic')[:2]
def WordNetTest(self):
'''一些WordNet的测试'''
## print wn.synsets('motorcar')
## print wn.synset('car.n.01').lemma_names
## print wn.synset('car.n.01').definition
## print wn.synset('car.n.01').examples
## print wn.synset('car.n.01').lemmas
## printwn.lemma('car.n.01.automobile').synset
## printwn.lemma('car.n.01.automobile').name
## print wn.synsets('car')
## print wn.lemmas('car')
motorcar = wn.synset('car.n.01')
types_of_motorcar = motorcar.hyponyms()
types_of_motorcar[26]
motorcar.hypernyms()
paths = motorcar.hypernym_paths()
sorted([lemma.name for synset in\
types_of_motorcar for lemma\
in synset.lemmas])
print len(paths)
print [synset.name for synset inpaths[0]]
print [synset.name for synset inpaths[1]]
print motorcar.root_hypernyms()
nt74=NltkTest74()
text1=nltk.corpus.gutenberg.words('austen-sense.txt')
text2=nltk.corpus.nps_chat.words()
text3=nltk.corpus.reuters.words()
#printnt74.unusual_words(text1)
#printnt74.unusual_words(text2)
#printnt74.StopWordsTest(text3)
#nt74.NamesTest()
#nt74.DicTest()
nt74.WordNetTest()