NLTK,Natural Language Toolkit是一个Python模块,提供了多种语料库(Corpora)和词典(Lexicon)资源,比如WordNet等,以及一系列基本的自然语言处理工具集,包括:分句,标记解析(Tokenization),词干提取(Stemming),词性标注(POS Tagging)和句法分析(Syntactic Parsing)等,是对英文文本数据进行处理的常用工具。
NLTK的安装为:
pip install nltk
为了使用NLTK提供的语料库和词典资源,首先需要下载。进入Python控制台,执行命令:
import nltk
nltk.download()
此时会弹出一个对话框,允许用户选择需要的下载资源,可以选择"All",然后单击"Download"。同时,也可以选择数据存储的目录,默认为C:\Users\Lab\AppData\Roming\nltk_data
。
在进行自然语言处理时,有一些词对于表达语言的含义并不重要,如英文中的冠词"a"和"the",介词"of"和"to"等。因此,在对语言进行更深入的处理之前可以将它们删除,从而加快处理的速度,减小模型的规模。这些词又被称为停用词(stop words)。NLTK提供了多种语言的停用词词表,可以通过下面指令引入停用词词表:
from nltk.corpus import stopwords
查看某种语言的停用词词表(比如英语):
stopwords.words('english')
"""
['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', "you're", "you've", "you'll", "you'd", 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', "she's", 'her', 'hers', 'herself', 'it', "it's", 'its', 'itself', 'they', 'them', 'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', "that'll", 'these', 'those', 'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 's', 't', 'can', 'will', 'just', 'don', "don't", 'should', "should've", 'now', 'd', 'll', 'm', 'o', 're', 've', 'y', 'ain', 'aren', "aren't", 'couldn', "couldn't", 'didn', "didn't", 'doesn', "doesn't", 'hadn', "hadn't", 'hasn', "hasn't", 'haven', "haven't", 'isn', "isn't", 'ma', 'mightn', "mightn't", 'mustn', "mustn't", 'needn', "needn't", 'shan', "shan't", 'shouldn', "shouldn't", 'wasn', "wasn't", 'weren', "weren't", 'won', "won't", 'wouldn', "wouldn't"]
"""
NLTK提供了多种语料库(文本数据集),如图书,电影评论和聊天记录等,它们可以被分为两类,即未标注语料库(又称为生语料库,生文本,Raw text)和人工标注语料库(Annotated corpus)。下面基于其中的典型语料库加以介绍。
未标注语料库
可以使用两种方式访问之前下载的语料库,第一种是直接访问语料库的原始文本文件(目录为下载数据时选择的存储目录);另一种是调用NLTK提供的相应功能。例如,通过以下方式,可以获得Gutenberg语料库(默认目录为nltk_data/corpora/gutenberg
),这是一小部分电子书里的内容。
from nltk.corpus import gutenberg
gutenberg.raw("austen-emma.txt")
人工标注语料库
人工标注的关于某项任务的结果。如在句子极性语料库(sentence_polarity)中,包含了10662条来自电影领域的用户评论句子以及相应的极性信息(褒义或者贬义)。通过以下命令,可以获得该语料库,其中,褒贬各有5331句(经过了小写转换,简单的标记解析Tokenization,等预处理后)。
from nltk.corpus import sentence_polarity
sentence_polarity提供了基本的数据访问方法:
sentence_polarity.categories()
返回褒贬类别列表,即['neg','pos']
;sentence_polarity.words()
返回语料库中全部单词的列表,如果调用时提供类别参数categories="pos" or "neg"
,则会返回相应类别的全部单词列表;sentence_polarity.sents()
返回语料库中全部句子的列表,调用时同样可以提供类别参数。可以使用以上方法的组合,构造出一个大列表,其中每个元素为一个句子的单词列表及其对应的褒贬类别构成的元组:
dataset=[(sentence,category)
for category in sentence_polarity.categories()
for sentence in sentence_polarity.sents(categories=category)]
"""
[
(['without', 'resorting', 'to', 'camp', 'or', 'parody', ',', 'haynes', '(', 'like', 'sirk', ',', 'but', 'differently', ')', 'has', 'transformed', 'the', 'rhetoric', 'of', 'hollywood', 'melodrama', 'into', 'something', 'provocative', ',', 'rich', ',', 'and', 'strange', '.'], 'pos'),
...
(['provides', 'a', 'porthole', 'into', 'that', 'noble', ',', 'trembling', 'incoherence', 'that', 'defines', 'us', 'all', '.'], 'pos')
]
"""
WordNet
WordNet是普林斯顿大学构建的英文语义词典(也成为辞典,Thesaurus),其主要特点是定义了同义词集合(Synset),每个同义词集合由具有相同意义的词义组成。此外,WordNet为每一个同义词集合提供了简短的释义(Gloss),同时,不同同义词集合之间还具有一定的语义关系。下面为WordNet的简单示例:
from nltk.corpus import wordnet
syns=wordnet.synsets("bank") # 返回"bank"的全部18个词义的synset
print(syns[0].name()) # 返回"bank"第一个词义的名称,其中"n"表示名词
# bank.n.01
print(syns[0].definition()) # 返回"bank"第1个词义的定义,即"河岸"的定义
# sloping land (especially the slope beside a body of water)
print(syns[1].definition()) # 返回"bank"第2个词义的定义,即"银行"的定义
# a financial institution that accepts deposits and channels the money into lending activities
print(syns[0].examples()) # 返回"bank"第1个词义的使用示例
# ['they pulled the canoe up on the bank', 'he sat on the bank of the river and watched the currents']
print(syns[0].hypernyms()) # 返回"bank"第1个词义的上位同义词集合, "slope"为"斜坡"
# [Synset('slope.n.01')]
dog=wordnet.synset('dog.n.01')
cat=wordnet.synset('cat.n.01')
print(dog.wup_similarity(cat)) # 计算两个同义词集合之间的Wu-Palmer相似度
# 0.8571428571428571
SentiWordNet
SentiWordNet是基于WordNet标注的词语(更准确地说是同义词集合)情感倾向性词典,它为WordNet中每个同义词集合人工标注了情感值,依次是褒义和贬义。通过该词典,可以实现一个简单的情感分析系统。下面是SentiWordNet的简单示例:
from nltk.corpus import sentiwordnet
# 'good.a.01'为good在形容词adj下的第1号语义
print(sentiwordnet.senti_synset('good.a.01'))
#
NLTK提供了多种常用的自然语言处理基础工具,比如分句,标记解析和词性标注等。
通常一个句子能够表达完整的语义信息,因此在进行更深入的自然语言处理之前,往往需要将较长的文档切分成若干句子,这一过程被称为分句。一般来讲,一个句子的结尾具有明显的标志,比如句号,问号和感叹号等,因此可以使用简单的规则进行分句。然而,往往存在大量的例外情况,如在英文中,句号除了可以作为句尾标志,还可以作为单词的一部分(如"Mr.")。NLTK提供的分句功能可以较好地解决此问题。下面为分句的示例:
from nltk.corpus import gutenberg
from nltk.tokenize import sent_tokenize
text=gutenberg.raw("austen-emma.txt")
sentences=sent_tokenize(text) # 对Emma小说全文进行分句
print(sentences[100]) # 显示其中的一个句子
"""
注意know--后面的字符\n为换行字符
Mr. Knightley loves to find fault with me, you know--\nin a joke--it is all a joke.
"""
一个句子是由若干标记(Token)按顺序构成的,其中标记既可以是一个词,也可以是标点符号等,这些标记是自然语言处理最基本的输入单元。将句子分割为标记的过程叫做标记解析(Tokenization)。英文中的单词之间通常使用空格进行分割,不过标点符号通常和前面的单词连在一起,因此标记解析的一项主要工作是将标点符号和前面的单词进行拆分。和分句一样,也无法使用简单的规则进行标记解析,以"."为例,它既可以作为句号,也可以作为标记的一部分,比如"Mr."不能简单被分成两个标记。同样,NLTK提供了标记解析的功能,称为标记解析器(Tokenizer)。下面为该功能的示例:
from nltk.tokenize import word_tokenize
print(word_tokenize(sentences[100]))
"""
['Mr.', 'Knightley', 'loves', 'to', 'find', 'fault', 'with', 'me', ',', 'you', 'know', '--', 'in', 'a', 'joke', '--', 'it', 'is', 'all', 'a', 'joke', '.']
"""
词性是词语所承担的语法功能类别,比如名词,动词和形容词等,因此词性也可以被称为词类。很多词语往往具有多种词性,比如"fire",既可以作为名词:火焰,也可以作为动词:开火。词性标注就是根据词语所处的上下文,确定其具体的词性。比如在"They sat by the fire."中,"fire"是名词,在"They fire a gun."中,"fire"是动词。NLTK提供了词性标注器(POS Tagger),下面为该功能的示例:
from nltk import pos_tag
print(pos_tag(word_tokenize("They sat by the fire.")))
# [('They', 'PRP'), ('sat', 'VBP'), ('by', 'IN'), ('the', 'DT'), ('fire', 'NN'), ('.', '.')]
词性标注采用宾州树库(Penn Treebank)的标注标准,NLTK提供了关于词性标注含义的查询功能:
print(nltk.help.upenn_tagset("NN"))
NLTK还有其他处理工具,包括命名实体识别,组块分析(Chunking)和句法分析等。
NLTK主要用于英文(印欧语系)处理,而以中文为代表的汉藏语系与英文不同,一个显著的区别在于词语之间不存在明显的分隔符,句子一般是由一串连续的字符构成。因此在处理中文时,需要使用更有针对性的分析工具。
语言技术平台(Language Technology Platform,LTP)是由哈尔滨工业大学历时多年研发的一整套高效,高精度的中文自然语言处理开源基础平台。该平台集词法分析(分词,词性标注和命名实体识别),句法分析(依存句法分析)和语义分析(语义角色标注和语义依存分析)等多项自然语言处理技术于一体。从LTP4.0开始,加入了预训练模型以及多任务学习机制,能够以较小的模型获得高精度表现。
LTP的安装为:
pip install ltp
中文分词需要考虑识别句子中的词语信息,因此难度很大,但LTP已经解决了这个问题:
from ltp import LTP
ltp=LTP() # 默认加载Small模型,首次使用时会自动下载并加载模型
# 对句子分词,结果使用segment访问,hidden用于访问每个词的隐含词向量,用于后续分析步骤
segment,hidden=ltp.seg(["南京长江大桥。"])
print(segment)
# [['南京市','长江','大桥','。']]
除了分词,LTP还提供了中文分句,词性标注,命名实体识别,依存句法分析和语义角色标注等功能。比如使用LTP分句以及词性标注示例如下:
# 分句
sentences=ltp.sent_split(["南京市长江大桥。","汤姆生病了。他去了医院。"])
print(sentences)
# ['南京市长江大桥。','汤姆生病了。','他去了医院。']
segment,hidden=ltp.seg(sentences)
print(segment)
"""
[
['南京市','长江','大桥','。'],
['汤姆','生病','了','。'],
['他','去','了','医院','。']
]
"""
# 词性标注
pos_tags=ltp.pos(hidden)
print(pos_tags)
"""
[
['ns','ns','n','wp'],
['nh','v','u','wp'],
['r','v','u','n','wp']
]
"""