词性标注

来源:互联网 发布:编程兼职网站有哪些 编辑:程序博客网 时间:2024/04/30 20:50

标注是典型的NLP流水线中继分词之后的第二个步骤

在NLP流程中,对工具的性能评估是NLP的一个中心主题,一个模块输出中的任何错误在下游模块都被无限放大了!

词性标注(part-of-speech tagging, POS tagging)

给文本中的词自动分配词性的过程称为词性标注、POS标注或标注。

词性标注是NLP中一个重要的、早期的序列分类任务:利用局部上下文语境中的词和标记,对序列中任意一点的分类决策。


词性标注器(part-of-speech tagger, POS tagger)

import nltktext = nltk.word_tokenize("...")nltk.pos_tag(text)

自动标记

默认标注器

为每个标识符分配同样的标记。找出最多的那个标记

>>> tags = [tag for (word,tag) in brown.tagged_words(categories='news')]>>> nltk.FreqDist(tags).max()u'NN'>>> raw = '....'>>> tokens = nltk.word_tokenize(raw)>>> default_tagger = nltk.DefaultTagger('NN')>>> default_tagger.tag(tokens)
>>> default_tagger.evaluate(brown_tagged_sents)0.13089484257215028

正则表达式标注器

patterns = [            (r'.*ing$', 'VBG'),            (r'.*ed$', 'VBD'),            (r'.*es$', 'VBZ'),            (r'.*ould$', 'MD'),            (r'.*\'s$', 'NN$'),            (r'.*s$', 'NNS'),            (r'^-?[0-9]+(.[0-9]+)?$', 'CD'),            (r'.*', 'NN')]
regexp_tagger = nltk.RegexpTagger(patterns)regexp_tagger.tag(brown_sents[3])regexp_tagger.evaluate(brown_tagged_sents)0.20326391789486245

查询标记器

找出100个最频繁的词,存储它们最有可能的标记。然后利用这个信息作为查找标注器。

fd = nltk.FreqDist(bown.words(categories='news'))cfd = nltk.ConditionalFreqDist(brown.tagged_words(categories='news'))most_freq_words = fd.keys()[:100]likely_tags = dict((word,cfd[word].max()) for word in most_freq_words)baseline_tagger = nltk.UnigramTagger(model=likely_tags)baseline_tagger.evaluate(brown_tagged_sents)0.4557849513691344

对于不在前100个最频繁的词,分配默认标记‘NN’。也就是说先使用查找表,如果不在里面就使用默认标记器。——这个过程叫做回退,通过制定一个标注器作为另一个标注器的参数。

baseline_tagger = nltk.UnigramTagger(model=likely_tags,                                    backoff=nltk.DefaultTagger('NN'))

N-gram标注

一元标注器(Unigram Tagging)

简单的统计算法,对每个标识符分配最有可能的标记。类似查找标注器。

In [1]: import nltkIn [2]: from nltk.corpus import brownIn [3]: brown_tagged_sents = brown.tagged_sents(categories='news')In [4]: brown_sents = brown.sents(categories='news')In [5]: unigram_tagger = nltk.UnigramTagger(brown_tagged_sents)In [6]: unigram_tagger.tag(brown_sents[2007])Out[6]:[(u'Various', u'JJ'), (u'of', u'IN'), (u'the', u'AT'), (u'apartments', u'NNS'), (u'are', u'BER'), (u'of', u'IN'), (u'the', u'AT'), (u'terrace', u'NN'), (u'type', u'NN'), (u',', u','), (u'being', u'BEG'), (u'on', u'IN'), (u'the', u'AT'), (u'ground', u'NN'), (u'floor', u'NN'), (u'so', u'QL'), (u'that', u'CS'), (u'entrance', u'NN'), (u'is', u'BEZ'), (u'direct', u'JJ'), (u'.', u'.')]In [7]: unigram_tagger.evaluate(brown_tagged_sents)Out[7]: 0.9349006503968017

分离训练和测试数据

In [11]: size = int(len(brown_tagged_sents) * 0.9)In [12]: train_sents = brown_tagged_sents[:size]In [13]: test_sents = brown_tagged_sents[size:]In [14]: unigram_tagger = nltk.UnigramTagger(train_sents)In [15]: unigram_tagger.evaluate(test_sents)Out[15]: 0.8120203329014253

N-gram标注器

N-gram标注器可以定义较大数值的n,但是当n大于3时,常常会面临数据稀疏问题。即使使用大量的训练数据,看到的也只是上下文的一小部分。

unigram标注器的一般化,它的上下文是当前词和它前面n-1个标识符的词性标记,n-gram标注器将挑选在给定上下文中最有可能的标记

注意!:bigram标注器能够标注训练中它看到过的句子中的所有词,但对一个没见过的句子却不行。只要遇到一个新词,就无法给他分配标记。

>>> bigram_tagger.evaluate(test_sents)0.10276088906608193

当n越大,上下文的奇异性就会增加,要标注的数据中包含训练数据中不存在的上下文的几率也增大。这被称为数据稀疏问题。


组合标注器

  • 尝试使用bigram标注器标注标识符
  • 如果bigram标注器无法找到标记,尝试unigram标注器
  • 如果unigram标注器也无法找到标记,使用默认标注器

回退标注器

回退是一个组合模型的方法:当一个较专业的模型(如bigram标注器)不能为给定内容分配标记时,可以回退到一个较一般的模型(如unigram标注器)

t0 = nltk.DefaultTagger('NN')t1 = nltk.UnigramTagger(train_sents, backoff=t0)t2 = nltk.BigramTagger(train_sents, backoff=t1)t2.evaluate(test_sents)0.84491179108940495

基于转换的标注

Brill标注

猜想每个词的标记,然后返回和修复错误的。编制一个转换修正规则链表。

首先使用unigram标注器标注,然后运用规则修正错误。

例如规则:

(a)当前面的词是TO时,替换NN为VB;
(b)当下一个标记是NNS时,替换TO为IN.

以上规则根据以下形式的模板产生:“在上下文C中,替换T1为T12”

规则是语言学可以解释的。

参考《Natural Language Processing with Python》

0 0
原创粉丝点击