Python3自然语言处理——获得文本语料库和词汇资源
Python3自然语言处理——获得文本语料库和词汇资源
注:转载请联系博主,或关注微信公众号"引文空间",后台提出转载申请,等待回复。否则将举报抄袭!
1.获取文本语料库
古腾堡语料库
NLTK包含Project Gutenberg电子文本档案的一小部分文本。我们先要用Python解释器加载NLTK包,然后尝试获得语料库中的文件标识符:
>>> import nltk
>>> nltk.corpus.gutenberg.fileids()
['austen-emma.txt', 'austen-persuasion.txt', 'austen-sense.txt', 'bible-kjv.txt', 'blake-poems.txt', 'bryant-stories.txt', 'burgess-busterbrown.txt', 'carroll-alice.txt', 'chesterton-ball.txt', 'chesterton-brown.txt', 'chesterton-thursday.txt', 'edgeworth-parents.txt', 'melville-moby_dick.txt', 'milton-paradise.txt', 'shakespeare-caesar.txt', 'shakespeare-hamlet.txt', 'shakespeare-macbeth.txt', 'whitman-leaves.txt']
Python还提供了另一个版本的import语句,示例如下:
>>> from nltk.corpus import gutenberg
>>> gutenberg.fileids()
['austen-emma.txt', 'austen-persuasion.txt', 'austen-sense.txt', 'bible-kjv.txt', 'blake-poems.txt', 'bryant-stories.txt', 'burgess-busterbrown.txt', 'carroll-alice.txt', 'chesterton-ball.txt', 'chesterton-brown.txt', 'chesterton-thursday.txt', 'edgeworth-parents.txt', 'melville-moby_dick.txt', 'milton-paradise.txt', 'shakespeare-caesar.txt', 'shakespeare-hamlet.txt', 'shakespeare-macbeth.txt', 'whitman-leaves.txt']
网络和聊天文本
NLTK 的网络文本小集合的内容包括 Firefox 交流论坛,在纽约无意听到的对话 ,《加勒比海盗》的电影剧本,个人广告和葡萄酒的评论:
>>> from nltk.corpus import webtext
>>> for fileid in webtext.fileids():
print(fileid)
firefox.txt
grail.txt
overheard.txt
pirates.txt
singles.txt
wine.txt
还有一个即时消息聊天会话语料库,最初由美国海军研究生院为研究自动检测互联网幼童虐待癖而收集的。语料库包含超过 10,000 张帖子,以“UserNNN”形式的通用名替换掉用户名,手工编辑消除任何其他身份信息,制作而成。语料库被分成 15 个文件,每个文件包含几百个按特定日期和特定年龄的聊天室(青少年、20 岁、30 岁、40岁、再加上一个通用的成年人聊天室)收集的帖子。文件名中包含日期、聊天室和帖子数量,例如:10-19-20s_706posts.xml 包含 2006 年 10 月 19 日从 20 多岁聊天室收集的 706 个帖子。
>>> chatroom=nps_chat.posts('10-19-20s_706posts.xml')
>>> chatroom
[['now', 'im', 'left', 'with', 'this', 'gay', 'name'], [':P'], ...]
布朗语料库
布朗语料库是第一个百万词级的英语电子语料库的,由布朗大学于 1961 年创建。这个语料库包含 500 个不同来源的文本,按照文体分类,如:新闻、社论等。
>>> from nltk.corpus import brown
>>> brown.categories()
['adventure', 'belles_lettres', 'editorial', 'fiction', 'government', 'hobbies', 'humor', 'learned', 'lore', 'mystery', 'news', 'religion', 'reviews', 'romance', 'science_fiction']
路透社语料库
路透社语料库包含 10,788 个新闻文档,共计 130 万字。这些文档分成 90 个主题,按照“训练”和“测试”分为两组。因此,fileid 为“test/14826”的文档属于测试组。这样分割是为了训练和测试算法的。
>>> from nltk.corpus import reuters
>>> reuters.fileids()
(此处省略2198行)
>>> reuters.categories()
['acq', 'alum', 'barley', 'bop', 'carcass', 'castor-oil', 'cocoa', 'coconut', 'coconut-oil', 'coffee', 'copper', 'copra-cake', 'corn', 'cotton', 'cotton-oil', 'cpi', 'cpu', 'crude', 'dfl', 'dlr', 'dmk', 'earn', 'fuel', 'gas', 'gnp', 'gold', 'grain', 'groundnut', 'groundnut-oil', 'heat', 'hog', 'housing', 'income', 'instal-debt', 'interest', 'ipi', 'iron-steel', 'jet', 'jobs', 'l-cattle', 'lead', 'lei', 'lin-oil', 'livestock', 'lumber', 'meal-feed', 'money-fx', 'money-supply', 'naphtha', 'nat-gas', 'nickel', 'nkr', 'nzdlr', 'oat', 'oilseed', 'orange', 'palladium', 'palm-oil', 'palmkernel', 'pet-chem', 'platinum', 'potato', 'propane', 'rand', 'rape-oil', 'rapeseed', 'reserves', 'retail', 'rice', 'rubber', 'rye', 'ship', 'silver', 'sorghum', 'soy-meal', 'soy-oil', 'soybean', 'strategic-metal', 'sugar', 'sun-meal', 'sun-oil', 'sunseed', 'tea', 'tin', 'trade', 'veg-oil', 'wheat', 'wpi', 'yen', 'zinc']
就职演说语料库
>>> from nltk.corpus import inaugural
>>> inaugural.fileids()
['1789-Washington.txt', '1793-Washington.txt', '1797-Adams.txt', '1801-Jefferson.txt', '1805-Jefferson.txt', '1809-Madison.txt', '1813-Madison.txt', '1817-Monroe.txt', '1821-Monroe.txt', '1825-Adams.txt', '1829-Jackson.txt', '1833-Jackson.txt', '1837-VanBuren.txt', '1841-Harrison.txt', '1845-Polk.txt', '1849-Taylor.txt', '1853-Pierce.txt', '1857-Buchanan.txt', '1861-Lincoln.txt', '1865-Lincoln.txt', '1869-Grant.txt', '1873-Grant.txt', '1877-Hayes.txt', '1881-Garfield.txt', '1885-Cleveland.txt', '1889-Harrison.txt', '1893-Cleveland.txt', '1897-McKinley.txt', '1901-McKinley.txt', '1905-Roosevelt.txt', '1909-Taft.txt', '1913-Wilson.txt', '1917-Wilson.txt', '1921-Harding.txt', '1925-Coolidge.txt', '1929-Hoover.txt', '1933-Roosevelt.txt', '1937-Roosevelt.txt', '1941-Roosevelt.txt', '1945-Roosevelt.txt', '1949-Truman.txt', '1953-Eisenhower.txt', '1957-Eisenhower.txt', '1961-Kennedy.txt', '1965-Johnson.txt', '1969-Nixon.txt', '1973-Nixon.txt', '1977-Carter.txt', '1981-Reagan.txt', '1985-Reagan.txt', '1989-Bush.txt', '1993-Clinton.txt', '1997-Clinton.txt', '2001-Bush.txt', '2005-Bush.txt', '2009-Obama.txt', '2013-Obama.txt', '2017-Trump.txt']
标注文本语料库
许多文本语料库都包含语言学标注,有词性标注、命名实体、句法结构、语义角色等 。NLTK 中提供了很方便的方式来访问这些语料库中的几个,还有一个包含语料库和语料样本的数据包,用于教学和科研的话可以免费下载。有关下载信息请参阅 http://www.nltk.org/data。关于如何访问 NLTK 语料库的其它例子,请在 http://www.nltk.org/howto 查阅语料库的 HOWTO。
其他语言的语料库
NLTK 包含多国语言语料库。某些情况下你在使用这些语料库之前需要学习如何在 Python 中处理字符编码。
载入你自己的语料库
如果你有自己收集的文本文件,并且想使用前面讨论的方法访问它们,你可以很容易地在 NLTK 中的 PlaintextCorpusReader 帮助下载入它们。首先要检查你的文件在文件系统中的位置,我的文件目录如下:
C:\Users\Administrator\Desktop\examples
将变量corpus_root的值设置为这个目录。PlaintextCorpusReader 初始化函数的第二个参数可以是一个如[‘a.txt’, ‘test/b.txt’]这样的 fileids链表,或者一个匹配所有fileids的模式 ,如:’[abc]/.*.txt’,关于正则表达式我们将在以后介绍。在这个路径下,我存储了“1.txt”和“2.txt”两个文本文件。我们载入了自己的语料库后也可以通过代码访问它的内容。完整代码如下:
>>> from nltk.corpus import PlaintextCorpusReader
>>> corpus_root=r'C:\Users\Administrator\Desktop\examples'
>>> wordlist=PlaintextCorpusReader(corpus_root,'.*')
>>> wordlist.fileids()
['1.txt', '2.txt']
>>> wordlist.words('1.txt')
['There', 'was', 'an', 'old', 'man', 'who', 'lived', ...]
2.条件频率分布
当语料文本被分为几类(文体、主题、作者等)时,我们可以计算每个类别独立的频率分布。这将允许我们研究类别之间的系统性差异。条件频率分布是频率分布的集合,每个频率分布有一个不同的“条件”。这个条件通常是文本的类别。
在绘制分布图和分布表的时候,需要用到plot()和tabulate()方法。这两个方法的源代码路径仍然在上一章所说的probability.py中,代码如下:
def plot(self, *args, **kwargs):
"""
Plot the given samples from the conditional frequency distribution.
For a cumulative plot, specify cumulative=True.
(Requires Matplotlib to be installed.)
:param samples: The samples to plot
:type samples: list
:param title: The title for the graph
:type title: str
:param conditions: The conditions to plot (default is all)
:type conditions: list
"""
try:
import matplotlib.pyplot as plt #import statment fix
except ImportError:
raise ValueError(
'The plot function requires matplotlib to be installed.'
'See http://matplotlib.org/'
)
cumulative = _get_kwarg(kwargs, 'cumulative', False)
percents = _get_kwarg(kwargs, 'percents', False)
conditions = [c for c in _get_kwarg(kwargs, 'conditions', self.conditions()) if c in self] # conditions should be in self
title = _get_kwarg(kwargs, 'title', '')
samples = _get_kwarg(
kwargs, 'samples', sorted(set(v
for c in conditions
for v in self[c]))
) # this computation could be wasted
if "linewidth" not in kwargs:
kwargs["linewidth"] = 2
ax = plt.gca()
if (len(conditions) != 0):
freqs = []
for condition in conditions:
if cumulative:
# freqs should be a list of list where each sub list will be a frequency of a condition
freqs.append(list(self[condition]._cumulative_frequencies(samples)))
ylabel = "Cumulative Counts"
legend_loc = 'lower right'
if percents:
freqs[-1] = [f / freqs[len(freqs) - 1] * 100 for f in freqs]
ylabel = "Cumulative Percents"
else:
freqs.append([self[condition][sample] for sample in samples])
ylabel = "Counts"
legend_loc = 'upper right'
# percents = [f * 100 for f in freqs] only in ConditionalProbDist?
i = 0
for freq in freqs:
kwargs['label'] = conditions[i] #label for each condition
i += 1
ax.plot(freq, *args, **kwargs)
ax.legend(loc=legend_loc)
ax.grid(True, color="silver")
ax.set_xticks(range(len(samples)))
ax.set_xticklabels([text_type(s) for s in samples], rotation=90)
if title:
ax.set_title(title)
ax.set_xlabel("Samples")
ax.set_ylabel(ylabel)
plt.show()
return ax
def tabulate(self, *args, **kwargs):
"""
Tabulate the given samples from the conditional frequency distribution.
:param samples: The samples to plot
:type samples: list
:param conditions: The conditions to plot (default is all)
:type conditions: list
:param cumulative: A flag to specify whether the freqs are cumulative (default = False)
:type title: bool
"""
cumulative = _get_kwarg(kwargs, 'cumulative', False)
conditions = _get_kwarg(kwargs, 'conditions', sorted(self.conditions()))
samples = _get_kwarg(
kwargs, 'samples', sorted(set(v for c in conditions
if c in self
for v in self[c]))) # this computation could be wasted
width = max(len("%s" % s) for s in samples)
freqs = dict()
for c in conditions:
if cumulative:
freqs[c] = list(self[c]._cumulative_frequencies(samples))
else:
freqs[c] = [self[c][sample] for sample in samples]
width = max(width, max(len("%d" % f) for f in freqs[c]))
condition_size = max(len("%s" % c) for c in conditions)
print(' ' * condition_size, end=' ')
for s in samples:
print("%*s" % (width, s), end=' ')
print()
for c in conditions:
print("%*s" % (condition_size, c), end=' ')
for f in freqs[c]:
print("%*d" % (width, f), end=' ')
print()
# Mathematical operators
def __add__(self, other):
"""
Add counts from two ConditionalFreqDists.
"""
if not isinstance(other, ConditionalFreqDist):
return NotImplemented
result = ConditionalFreqDist()
for cond in self.conditions():
newfreqdist = self[cond] + other[cond]
if newfreqdist:
result[cond] = newfreqdist
for cond in other.conditions():
if cond not in self.conditions():
for elem, count in other[cond].items():
if count > 0:
result[cond][elem] = count
return result
实例1
我们用布朗语料库做一个分布表,分布表的内容是各种文体中情态动词的出现频数。
>>> import nltk
>>> from nltk.corpus import brown
>>> cfd=nltk.ConditionalFreqDist(
(genre,word)
for genre in brown.categories()
for word in brown.words(categories=genre))
>>> genres=['news','religion','hobbies','science_fiction','romance','humor']
>>> modals=['can','could','may','might','must','will']
>>> cfd.tabulate(conditions=genres,samples=modals)
can could may might must will
news 93 86 66 38 50 389
religion 82 59 78 12 54 71
hobbies 268 58 131 22 83 264
science_fiction 16 49 4 12 8 16
romance 74 193 11 51 45 43
humor 16 30 8 8 9 13
通过观察可以发现,新闻文体中最常出现的情态动词为will,而言情文体中最常见的情态动词是could。
实例2
在就职演说语料库中,让我们来看看词汇 america 和 citizen 随时间推移的使用情况。下面的代码使用 w.lower将就职演说语料库中的词汇转换成小写。然后用 startswith()检查它们是否以“目标”词汇 america 或 citizen 开始。因此,它会计算如 American’s 和 Citizens 等词。
import nltk
from nltk.corpus import inaugural
cfd=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))
cfd.plot()
实例3
在语言语料库中,udhr是超过 300 种语言的世界*宣言。这个语料库的 fileids包括有关文件所使用的字符编码,如:UTF8 或者 Latin1。让我们用条件频率分布来研究“世界*宣言”(udhr)语料库中不同语言版本中的字长差异。图是累积字长分布。
import nltk
from nltk.corpus import udhr
languages=['Chickasaw','English','German_Deutsch','Greenlandic_Inuktikut','Hungarian_Magyar','Ibibio_Efik']
cfd=nltk.ConditionalFreqDist(
(lang,len(word))
for lang in languages
for word in udhr.words(lang+'-Latin1'))
cfd.plot(cumulative=True)
在第三个实例中,我们形成的图形的纵轴仍然和书上的Cumulative Percentage不同,这一点在上一章已经介绍过,但是这回的解决方案还没有找到,如果加上percents=True,会如此报错:
Traceback (most recent call last):
File "C:\Users\Administrator\Desktop\NLP\5.py", line 9, in <module>
cfd.plot(cumulative=True,percents=True)
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38\lib\site-packages\nltk\probability.py", line 1935, in plot
freqs[-1] = [f / freqs[len(freqs) - 1] * 100 for f in freqs]
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38\lib\site-packages\nltk\probability.py", line 1935, in <listcomp>
freqs[-1] = [f / freqs[len(freqs) - 1] * 100 for f in freqs]
TypeError: unsupported operand type(s) for /: 'list' and 'list'
错误原因是:
unsupported operand type(s) for /: 'list' and 'list'
解决方案目前还不清楚,等以后清楚了我会再补充,读者也可以根据上面贴出的源码自己试一下。
实例4
有一个词汇列表是名字语料库,包括 8000 个按性别分类的名字。男性和女性的名字存储在单独的文件中。正如大家都知道的,以字母 a 结尾的名字几乎都是女性。我们可以在图 中看到这一点以及一些其它的模式,该图是由下面的代码产生的。请记住 name[-1]是 name 的最后一个字母。
import nltk
names=nltk.corpus.names
cfd=nltk.ConditionalFreqDist(
(fileid,name[-1])
for fileid in names.fileids()
for name in names.words(fileid))
cfd.plot()