自然语言处理——自动标注词性
2017-09-11 14:06
597 查看
本文探讨以不同的方式给文本自动添加词性标记。
首先加载要使用的数据。
1、默认标注器
最简单的标注器是为每个标识符分配同样的标记。这似乎是一个相对普通的方法,但为标注器的性能建立了一个重要的标准。为了得到最好的效果,我们用最有可能的标记标注每个词。通过下例找出哪个标记是最有可能的。
>>>'NN'
我们现在可以创建一个将所有词都标注为NN的标注器。
不出所料,这种方法的表现相当不好。在一个典型的语料库中,它只正确标注了八分之一的标识符,如下列所示:
默认的标注器给每个单独的词分配标记,即使是之前从未遇到过的词。碰巧的是,在处理几千词的英文文本时发现,大多数新名词都是名词。这意味着,默认标注器可以帮助我们提高语言处理系统的稳定性。
2、正则表达式标注器
正则表达式标注器基于匹配模式分配标记给标识符。例如,一般情况下认为任一以ed结尾的词都是动词过去分词,任一以‘s结尾的词都是名词所有格。下例中可以用正则表达式的列表来表示这些。
# 0.20326391789486245
我们发现有大约五分之一是正确的。
3、查询标注器
很多高频词没有NN标记,我们找出100个最频繁的词,存储它们最有可能的标记,然后我们可以使用这个信息作为“查询标注器(NLTKUnigramTagger)”的模型,如下例:
此处结果与书中不同,书中结果为0.45左右,即仅仅知道100个最频繁的词的标记就能正确标注很大一部分标识符。
来看看它在未标注的输入文本是运行得怎么样:
[(u'``', None),
(u'Only', None),
(u'a', None),
(u'relative', None),
(u'handful', None),
(u'of', None),
(u'such', None),
(u'reports', u'NNS'),
(u'was', None),
(u'received', None),
(u"''", None),
(u',', None),
(u'the', None),
(u'jury', None),
(u'said', None),
(u',', None),
(u'``', None),
(u'considering', None),
(u'the', None),
(u'widespread', None),
(u'interest', None),
(u'in', None),
(u'the', None),
(u'election', None),
(u',', None),
(u'the', None),
(u'number', None),
(u'of', None),
(u'voters', None),
(u'and', None),
(u'the', None),
(u'size', None),
(u'of', None),
(u'this', None),
(u'city', None),
(u"''", None),
(u'.', None)]
可以看到很多词都被分配了'None'标签,因为它们不在100个最频繁的词中。这种情况我们想分配默认标记NN。也就是说,我们应先使用查找表,如果不能指定就使用默认标注器,这个过程叫“回退”。
最后我们把查找标注器和默认标注器结合起来之后,看它的性能如何,使用大小不同的模型:
可以看到随着模型规模的增长,最初性能增加较快,最终达到稳定水平,这时哪怕模型规模再增加,性能提升幅度也很小。
首先加载要使用的数据。
import nltk from nltk.corpus import brown brown_tagged_sents = brown.tagged_sents(categories='news') brown_sents = brown.sents(categories='news')
1、默认标注器
最简单的标注器是为每个标识符分配同样的标记。这似乎是一个相对普通的方法,但为标注器的性能建立了一个重要的标准。为了得到最好的效果,我们用最有可能的标记标注每个词。通过下例找出哪个标记是最有可能的。
tags = [tag for (word, tag) in brown.tagged_words(categories='news')] tag = nltk.FreqDist(tags).max
>>>'NN'
我们现在可以创建一个将所有词都标注为NN的标注器。
raw = 'I do not like green egg and ham, I do not like them Sam I am!' tokens = nltk.word_tokenize(raw) default_tagger = nltk.DefaultTagger('NN') default_tagger.tag(tokens)
不出所料,这种方法的表现相当不好。在一个典型的语料库中,它只正确标注了八分之一的标识符,如下列所示:
default_tagger.evaluate(brown_tagged_sents) # 0.13089484257215028
默认的标注器给每个单独的词分配标记,即使是之前从未遇到过的词。碰巧的是,在处理几千词的英文文本时发现,大多数新名词都是名词。这意味着,默认标注器可以帮助我们提高语言处理系统的稳定性。
2、正则表达式标注器
正则表达式标注器基于匹配模式分配标记给标识符。例如,一般情况下认为任一以ed结尾的词都是动词过去分词,任一以‘s结尾的词都是名词所有格。下例中可以用正则表达式的列表来表示这些。
patterns = [ (r'.*ing$', 'VBG'), # gerunds (r'.*ed$', 'VBD'), # simple past (r'.*es$', 'VBZ'), # 3rd singular present (r'.*ould$', 'MD'), # modals (r'.*\'s$', 'NN$'), # possessive nouns (r'.*s$', 'NNS'), # plural nouns (r'^-?[0-9]+(.[0-9]+)?$', 'CD'), # cardinal numbers (r'.*', 'NN') # nouns (deafult) ]这些是按顺序处理的,第一个匹配上的会被使用。现在建立一个标注器,并用它来标注句子。
regexp_tagger = nltk.RegexpTagger(patterns) regexp_tagger.tag(brown_sents[3]) regexp_tagger.evaluate(brown_tagged_sents)
# 0.20326391789486245
我们发现有大约五分之一是正确的。
3、查询标注器
很多高频词没有NN标记,我们找出100个最频繁的词,存储它们最有可能的标记,然后我们可以使用这个信息作为“查询标注器(NLTKUnigramTagger)”的模型,如下例:
fd = nltk.FreqDist(brown.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.005171350717027666 ?? in book it should be 0.45
此处结果与书中不同,书中结果为0.45左右,即仅仅知道100个最频繁的词的标记就能正确标注很大一部分标识符。
来看看它在未标注的输入文本是运行得怎么样:
sent = brown.sents(categories='news')[3] baseline_tagger.tag(sent) # many words are tagged 'None',because they do not belong to 100th most used words下面是结果:
[(u'``', None),
(u'Only', None),
(u'a', None),
(u'relative', None),
(u'handful', None),
(u'of', None),
(u'such', None),
(u'reports', u'NNS'),
(u'was', None),
(u'received', None),
(u"''", None),
(u',', None),
(u'the', None),
(u'jury', None),
(u'said', None),
(u',', None),
(u'``', None),
(u'considering', None),
(u'the', None),
(u'widespread', None),
(u'interest', None),
(u'in', None),
(u'the', None),
(u'election', None),
(u',', None),
(u'the', None),
(u'number', None),
(u'of', None),
(u'voters', None),
(u'and', None),
(u'the', None),
(u'size', None),
(u'of', None),
(u'this', None),
(u'city', None),
(u"''", None),
(u'.', None)]
可以看到很多词都被分配了'None'标签,因为它们不在100个最频繁的词中。这种情况我们想分配默认标记NN。也就是说,我们应先使用查找表,如果不能指定就使用默认标注器,这个过程叫“回退”。
baseline_tagger = nltk.UnigramTagger(model=likely_tags,backoff=nltk.DefaultTagger('NN'))
最后我们把查找标注器和默认标注器结合起来之后,看它的性能如何,使用大小不同的模型:
def performance(cfd,wordlist): lt = dict((word,cfd[word].max()) for word in wordlist) baseline_tagger = nltk.UnigramTagger(model=lt,backoff=nltk.DefaultTagger('NN')) return baseline_tagger.evaluate(brown.tagged_sents(categories='news')) def display(): import pylab words_by_freq = list(nltk.FreqDist(brown.words(categories='news'))) cfd = nltk.ConditionalFreqDist(brown.tagged_words(categories='news')) sizes = 2 ** pylab.arange(16) prefs = [performance(cfd,words_by_freq[:size]) for size in sizes] pylab.plot(sizes,prefs,'-bo') pylab.title('Lookup Tagger Performance with Varying Model Size') pylab.xlabel('Model Size') pylab.ylabel('Performace') pylab.show() display()
可以看到随着模型规模的增长,最初性能增加较快,最终达到稳定水平,这时哪怕模型规模再增加,性能提升幅度也很小。
相关文章推荐
- 自然语言处理基于java实现(2) 之 词性标注
- 十七、让机器做词性自动标注的具体方法
- NLTK中文词性自动标注
- HMM在自然语言处理中的应用一:词性标注
- 自然语言处理基础技术之分词、向量化、词性标注
- HMM在自然语言处理中的应用一:词性标注
- NLP自然语言处理 jieba中文分词,关键词提取,词性标注,并行分词,起止位置,文本挖掘,NLP WordEmbedding的概念和实现
- nlp-形式语言与自动机-ch07-自动分词、命名实体识别与词性标注
- 自然语言处理基础技术之分词、向量化、词性标注
- fudannlp - 开源中文自然语言处理工具包|中文分词|词性标注|依存句法分析|指代消解 - Google Project Hosting
- Parker - 最高效的自动标注工具
- 尝试用图像处理来实现UI设计稿的自动标注
- 词性标注(POS tagging)
- 图层的自动标注
- ICTCLAS分词系统研究(六)-- 词性标注
- nltk 词性标注详解
- Python 文本挖掘:jieba中文分词和词性标注
- MIT自然语言处理第四讲:标注(第四部分)
- 中文词性标注以及命名实体识别
- 为xcode 6.4 添加 文档自动标注 的插件VVDocumenter-Xcode