NLTK学习(二)

转载自:NLTK学习之二:建构词性标注器

学习所用,如有侵权,立即删除。

词性标注,或POS(Part Of Speech),是一种分析句子成分的方法,通过它来识别每个词的词性。下面简要列举POS的tagset含意,详细可看nltk.help.brown_tagset()

标记 词性 示例
ADJ 形容词 new, good, high, special, big, local
ADV 动词 really, already, still, early, now
CONJ 连词 and, or, but, if, while, although
DET 限定词 the, a, some, most, every, no
EX 存在量词 there, there’s
MOD 情态动词 will, can, would, may, must, should
NN 名词 year,home,costs,time
NNP 专有名词 April,China,Washington
NUM 数词 fourth,2016, 09:30
PRON 代词 he,they,us
P 介词 on,over,with,of
TO 词to to
UH 叹词 ah,ha,oops
VB   动词
VBD 动词过去式 made,said,went
VBG 现在分词 going,lying,playing
VBN 过去分词 taken,given,gone
WH wh限定词 who,where,when,what

使用NLTK进行词性标注:

示例:

import nltk
sent = 'I am going to Wuhan University now'
tokens = nltk.word_tokenize(sent)

taged_sent = nltk.pos_tag(tokens)
print(taged_sent)

运行结果:

[('I', 'PRP'), ('am', 'VBP'), ('going', 'VBG'), ('to', 'TO'), ('Wuhan', 'NNP'), ('University', 'NNP'), ('now', 'RB')]

语料库的已标注数据

语料类提供了下列方法可以返回预标注数据。

方法 说明
tagged_words(fileids,categories) 返回标注数据,以词列表的形式
tagged_sents(fileids,categories) 返回标注数据,以句子列表形式
tagged_paras(fileids,categories) 返回标注数据,以文章列表形式

标注器:

1、默认标注器

最简单的词性标注器将所有的词都标注为名词NN,标注的正确率不是很高,没有很高的价值。

示例:

import nltk
from nltk.corpus import brown

default_tagger = nltk.DefaultTagger('NN')
sents = 'I am going to Wuhan University now.'
print(default_tagger.tag(sents))

tagged_sent = brown.tagged_sents(categories='news')
print(default_tagger.evaluate(tagged_sent))

运行结果:

[('I', 'NN'), (' ', 'NN'), ('a', 'NN'), ('m', 'NN'), (' ', 'NN'), ('g', 'NN'), ('o', 'NN'), ('i', 'NN'), ('n', 'NN'), ('g', 'NN'), (' ', 'NN'), ('t', 'NN'), ('o', 'NN'), (' ', 'NN'), ('W', 'NN'), ('u', 'NN'), ('h', 'NN'), ('a', 'NN'), ('n', 'NN'), (' ', 'NN'), ('U', 'NN'), ('n', 'NN'), ('i', 'NN'), ('v', 'NN'), ('e', 'NN'), ('r', 'NN'), ('s', 'NN'), ('i', 'NN'), ('t', 'NN'), ('y', 'NN'), (' ', 'NN'), ('n', 'NN'), ('o', 'NN'), ('w', 'NN'), ('.', 'NN')]
0.13089484257215028

从上述结果可以看出,默认标注器将所有词标注为名词NN的准确率较低,只有13.08%。

基于规则的标注器:

使用规则可以提高标注器的准确率,比如对于ing结尾则柡注为VG,ed结尾则标注为VD。可以通过正则表达式标注器实现。

示例:

import nltk
from nltk.corpus import brown

pattern = [
    (r'.*ing$', 'VBG'),
    (r'.*ed$', 'VBD'),
    (r'.*es$', 'VBZ'),
    (r'.*\'s$', 'NN$'),
    (r'.*s$', 'NNS'),
    (r'.*', 'NN'),  # 未标注的仍为NN
]
sents = 'I am going to Wuhan University.'

tagger = nltk.RegexpTagger(pattern)

print(tagger.tag(nltk.word_tokenize(sents)))

tagged_sents = brown.tagged_sents(categories='news')
print(tagger.evaluate(tagged_sents))

运行结果:

[('I', 'NN'), ('am', 'NN'), ('going', 'VBG'), ('to', 'NN'), ('Wuhan', 'NN'), ('University', 'NN'), ('.', 'NN')]
0.1875310778288283

可以看出相比于默认的词性标注器,基于规则的词性标注具有较高的准确率。

3、基于查表的标注器

统计一下部分高频词的词性,比如经常出现的100个词的词性。利用单个词的词性的统计知识来进行标注,这就是Unigram模型的思想。

示例:

import nltk
from nltk.corpus import  brown
sents = open('nothing_gonna_change_my_love_for_you.txt').read()
fdist = nltk.FreqDist(brown.words(categories='news'))
common_word = fdist.most_common(100)

cfdist = nltk.ConditionalFreqDist(brown.tagged_words(categories='news'))
table = dict((word, cfdist[word].max()) for (word, _) in common_word)

uni_tagger = nltk.UnigramTagger(model=table, backoff=nltk.DefaultTagger('NN'))
print(uni_tagger.tag(nltk.word_tokenize(sents)))
tagged_sents = brown.tagged_sents(categories='news')
print(uni_tagger.evaluate(tagged_sents))

运行结果:

[('锘縄f', 'NN'), ('I', 'PPSS'), ('had', 'HVD'), ('to', 'TO'), ('live', 'NN'), ('my', 'NN'), ('life', 'NN'), ('without', 'NN'), ('you', 'NN'), ('near', 'NN'), ('me', 'NN'), ('The', 'AT'), ('days', 'NN'), ('would', 'MD'), ('all', 'ABN'), ('be', 'BE'), ('empty', 'NN'), ('The', 'AT'), ('nights', 'NN'), ('would', 'MD'), ('seem', 'NN'), ('so', 'NN'), ('long', 'NN'), ('With', 'NN'), ('you', 'NN'), ('I', 'PPSS'), ('see', 'NN'), ('forever', 'NN'), ('oh', 'NN'), ('so', 'NN'), ('clearly', 'NN'), ('I', 'PPSS'), ('might', 'NN'), ('have', 'HV'), ('been', 'BEN'), ('in', 'IN'), ('love', 'NN'), ('before', 'IN'), ('But', 'CC'), ('it', 'PPS'), ('never', 'NN'), ('felt', 'NN'), ('this', 'DT'), ('strong', 'NN'), ('Our', 'NN'), ('dreams', 'NN'), ('are', 'BER'), ('young', 'NN'), ('And', 'NN'), ('we', 'PPSS'), ('both', 'NN'), ('know', 'NN'), ('they', 'PPSS'), ("'ll", 'NN'), ('take', 'NN'), ('us', 'NN'), ('where', 'NN'), ('we', 'PPSS'), ('want', 'NN'), ('to', 'TO'), ('go', 'NN'), ('Hold', 'NN'), ('me', 'NN'), ('now', 'NN'), ('Touch', 'NN'), ('me', 'NN'), ('now', 'NN'), ('I', 'PPSS'), ('do', 'NN'), ("n't", 'NN'), ('want', 'NN'), ('to', 'TO'), ('live', 'NN'), ('without', 'NN'), ('you', 'NN'), ('Nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('You', 'NN'), ('ought', 'NN'), ('to', 'TO'), ('[', 'NN'), ('2', 'NN'), (']', 'NN'), ('know', 'NN'), ('by', 'IN'), ('now', 'NN'), ('how', 'NN'), ('much', 'NN'), ('I', 'PPSS'), ('love', 'NN'), ('you', 'NN'), ('One', 'NN'), ('thing', 'NN'), ('you', 'NN'), ('can', 'MD'), ('be', 'BE'), ('sure', 'NN'), ('of', 'IN'), ('I', 'PPSS'), ("'ll", 'NN'), ('never', 'NN'), ('ask', 'NN'), ('for', 'IN'), ('more', 'AP'), ('than', 'IN'), ('your', 'NN'), ('love', 'NN'), ('Nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('You', 'NN'), ('ought', 'NN'), ('to', 'TO'), ('know', 'NN'), ('by', 'IN'), ('now', 'NN'), ('how', 'NN'), ('much', 'NN'), ('I', 'PPSS'), ('love', 'NN'), ('you', 'NN'), ('The', 'AT'), ('world', 'NN'), ('may', 'NN'), ('change', 'NN'), ('my', 'NN'), ('whole', 'NN'), ('life', 'NN'), ('through', 'NN'), ('But', 'CC'), ('nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('If', 'NN'), ('the', 'AT'), ('road', 'NN'), ('ahead', 'NN'), ('[', 'NN'), ('3', 'NN'), (']', 'NN'), ('is', 'BEZ'), ('not', '*'), ('so', 'NN'), ('easy', 'NN'), (',', ','), ('Our', 'NN'), ('love', 'NN'), ('will', 'MD'), ('lead', 'NN'), ('the', 'AT'), ('way', 'NN'), ('for', 'IN'), ('us', 'NN'), ('Just', 'NN'), ('like', 'NN'), ('a', 'AT'), ('guiding', 'NN'), ('star', 'NN'), ('I', 'PPSS'), ("'ll", 'NN'), ('be', 'BE'), ('there', 'EX'), ('for', 'IN'), ('you', 'NN'), ('if', 'NN'), ('you', 'NN'), ('should', 'NN'), ('need', 'NN'), ('me', 'NN'), ('You', 'NN'), ('do', 'NN'), ("n't", 'NN'), ('have', 'HV'), ('to', 'TO'), ('change', 'NN'), ('a', 'AT'), ('thing', 'NN'), ('I', 'PPSS'), ('love', 'NN'), ('you', 'NN'), ('just', 'NN'), ('the', 'AT'), ('way', 'NN'), ('you', 'NN'), ('are', 'BER'), ('So', 'NN'), ('come', 'NN'), ('with', 'IN'), ('me', 'NN'), ('and', 'CC'), ('share', 'NN'), ('the', 'AT'), ('view', 'NN'), ('I', 'PPSS'), ("'ll", 'NN'), ('help', 'NN'), ('you', 'NN'), ('see', 'NN'), ('forever', 'NN'), ('too', 'NN'), ('Hold', 'NN'), ('me', 'NN'), ('now', 'NN'), ('Touch', 'NN'), ('me', 'NN'), ('now', 'NN'), ('I', 'PPSS'), ('do', 'NN'), ("n't", 'NN'), ('want', 'NN'), ('to', 'TO'), ('live', 'NN'), ('without', 'NN'), ('you', 'NN'), ('Nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('You', 'NN'), ('ought', 'NN'), ('to', 'TO'), ('know', 'NN'), ('by', 'IN'), ('now', 'NN'), ('how', 'NN'), ('much', 'NN'), ('I', 'PPSS'), ('love', 'NN'), ('you', 'NN'), ('One', 'NN'), ('thing', 'NN'), ('you', 'NN'), ('can', 'MD'), ('be', 'BE'), ('sure', 'NN'), ('of', 'IN'), ('I', 'PPSS'), ("'ll", 'NN'), ('never', 'NN'), ('ask', 'NN'), ('for', 'IN'), ('more', 'AP'), ('than', 'IN'), ('your', 'NN'), ('love', 'NN'), ('Nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('You', 'NN'), ('ought', 'NN'), ('to', 'TO'), ('know', 'NN'), ('by', 'IN'), ('now', 'NN'), ('how', 'NN'), ('much', 'NN'), ('I', 'PPSS'), ('love', 'NN'), ('you', 'NN'), ('The', 'AT'), ('world', 'NN'), ('may', 'NN'), ('change', 'NN'), ('my', 'NN'), ('whole', 'NN'), ('life', 'NN'), ('through', 'NN'), ('But', 'CC'), ('nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('Nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('You', 'NN'), ('ought', 'NN'), ('to', 'TO'), ('know', 'NN'), ('by', 'IN'), ('now', 'NN'), ('how', 'NN'), ('much', 'NN'), ('I', 'PPSS'), ('love', 'NN'), ('you', 'NN'), ('The', 'AT'), ('world', 'NN'), ('may', 'NN'), ('change', 'NN'), ('my', 'NN'), ('whole', 'NN'), ('life', 'NN'), ('through', 'NN'), ('But', 'CC'), ('nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('Nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('You', 'NN'), ('ought', 'NN'), ('to', 'TO'), ('know', 'NN'), ('by', 'IN'), ('now', 'NN'), ('how', 'NN'), ('much', 'NN'), ('I', 'PPSS'), ('love', 'NN'), ('you', 'NN'), ('One', 'NN'), ('thing', 'NN'), ('you', 'NN'), ('can', 'MD'), ('be', 'BE'), ('sure', 'NN'), ('of', 'IN'), ('I', 'PPSS'), ("'ll", 'NN'), ('never', 'NN'), ('ask', 'NN'), ('for', 'IN'), ('more', 'AP'), ('than', 'IN'), ('your', 'NN'), ('love', 'NN'), ('Nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('You', 'NN'), ('ought', 'NN'), ('to', 'TO'), ('know', 'NN'), ('by', 'IN'), ('now', 'NN'), ('how', 'NN'), ('much', 'NN'), ('I', 'PPSS'), ('love', 'NN'), ('you', 'NN'), ('The', 'AT'), ('world', 'NN'), ('may', 'NN'), ('change', 'NN'), ('my', 'NN'), ('whole', 'NN'), ('life', 'NN'), ('through', 'NN'), ('But', 'CC'), ('nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('Nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('You', 'NN'), ('ought', 'NN'), ('to', 'TO'), ('know', 'NN'), ('by', 'IN'), ('now', 'NN'), ('how', 'NN'), ('much', 'NN'), ('I', 'PPSS'), ('love', 'NN'), ('you', 'NN'), ('One', 'NN'), ('thing', 'NN'), ('you', 'NN'), ('can', 'MD'), ('be', 'BE'), ('sure', 'NN'), ('of', 'IN'), ('I', 'PPSS'), ("'ll", 'NN'), ('never', 'NN'), ('ask', 'NN'), ('for', 'IN'), ('more', 'AP'), ('than', 'IN'), ('your', 'NN'), ('love', 'NN'), ('Nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN'), ('You', 'NN'), ('ought', 'NN'), ('to', 'TO'), ('know', 'NN'), ('by', 'IN'), ('now', 'NN'), ('how', 'NN'), ('much', 'NN'), ('I', 'PPSS'), ('love', 'NN'), ('you', 'NN'), ('The', 'AT'), ('world', 'NN'), ('may', 'NN'), ('change', 'NN'), ('my', 'NN'), ('whole', 'NN'), ('life', 'NN'), ('through', 'NN'), ('But', 'CC'), ('nothing', 'NN'), ("'s", 'NN'), ('gon', 'NN'), ('na', 'NN'), ('change', 'NN'), ('my', 'NN'), ('love', 'NN'), ('for', 'IN'), ('you', 'NN')]
0.5817769556656125

只利用前100个词的历史统计数据便能获得58%的正确率,加大这个词的数量更可以继续提升标注的正确率,当为8000时可以达到90%的正确率。这里我们对不在这100个词的其他词统一回退到默认标注器。

训练N-gram标注器:

一般N-gram标注器:

Unigram标注器是1-Gram。考虑更多的上下文,便有了2-gram、3-gram,这里统称为N-gram。注意,考虑更长的上下文并不能带来准确度的提升。 
除了向N-gram标注器提供词表模型,另外一种构建标注器的方法是训练。N-gram标注器的构建函数如下:__init__(train=None, model=None, backoff=None),可以将标注好的语料作为训练数据,用于构建一个标注器。

示例:

import nltk
from nltk.corpus import brown

brown_tagged_sents = brown.tagged_sents(categories='news')
train_num = int(len(brown_tagged_sents) * 0.9)
x_train = brown_tagged_sents[0: train_num]
x_test = brown_tagged_sents[train_num:]
tagger = nltk.UnigramTagger(train=x_train)
print(tagger.evaluate(x_test))

运行结果:

0.8121200039868434

对于UnigramTagger,采用90%的数据进行训练,再余下的10%数据上测试的准确率是81%。

组合标注器

利用backoff参数,将多个组合标注器组合起来,以提高识别精确率。

示例:

import nltk
from nltk.corpus import brown

pattern = [
    (r'.*ing$','VBG'),
    (r'.*ed$','VBD'),
    (r'.*es$','VBZ'),
    (r'.*\'s$','NN$'),
    (r'.*s$','NNS'),
    (r'.*', 'NN')  #未匹配的仍标注为NN
]

brown_tagged_sents = brown.tagged_sents(categories='news')
train_num = int(len(brown_tagged_sents) * 0.9)

x_train = brown_tagged_sents[0: train_num]
x_test = brown_tagged_sents[train_num:]
t0 = nltk.RegexpTagger(pattern)
t1 = nltk.UnigramTagger(x_train, backoff=t0)
t2 = nltk.BigramTagger(x_train, backoff=t1)
print(t2.evaluate(x_test))

运行结果:

0.8627529153792485

可以看出,不需要任何的语言学知识,只需要借助统计数据便可以使得词性标注做的足够好。 
对于中文,只要有标注语料,也可以按照上面的过程训练N-gram标注器。

nltk.tag.BrillTagger实现了基于转换的标注,在基础标注器的结果上,对输出进行基于规则的修正,实现更高的准确度。

中文标注器的训练

示例:

import nltk
import json

lines = open('199801.txt', 'rb').readlines()
all_tagged_sents = []

for line in lines:
    line = line.decode('utf-8')
    sent = line.split()
    tagged_sent = []
    for item in sent:
        pair = nltk.str2tuple(item)
        tagged_sent.append(pair)

    if len(tagged_sent) > 0:
        all_tagged_sents.append(tagged_sent)

train_size = int(len(all_tagged_sents) * 0.8)
x_train = all_tagged_sents[: train_size]
x_test = all_tagged_sents[train_size:]
tagger = nltk.UnigramTagger(train=x_train, backoff=nltk.DefaultTagger('n'))

tokens = nltk.word_tokenize(u'我 认为 不丹 的 被动 卷入 不 构成 此次 对峙 的 主要 因素。')
tagged = tagger.tag(tokens)
print(json.dumps(tagged, ensure_ascii=False))
print(tagger.evaluate(x_test))

运行结果:

[["我", "R"], ["认为", "V"], ["不丹", "n"], ["的", "U"], ["被动", "A"], ["卷入", "V"], ["不", "D"], ["构成", "V"], ["此次", "R"], ["对峙", "V"], ["的", "U"], ["主要", "B"], ["因素。", "n"]]
0.8714095491725319
 

猜你喜欢

转载自blog.csdn.net/github_39611196/article/details/82732648