在这里有不同的方式来给文本自动添加词性标记。
一个词的标记,要依赖于这个词和它在句子中的上下文。
所以:我们将处理句子层次而不是词汇层次的数据。
下面的所有代码示例中都以这些代码为基础:
>>>from nltk.corpusimport brown >>>brown_tagged_sents= brown.tagged_sents(categories='news') >>>brown_sents= brown.sents(categories='news')
默认标注器
#把最有可能的标记进行标注 tags=[tag for (word,tag) in brown.tagged_words(categories=’news’)] nltk.FreqDist(tags).max() ‘NN’
#现在使用将所有词都标注成NN的标注器 >>>raw = 'I donot like greeneggs and ham,I donot like them SamI am!' >>>tokens = nltk.word_tokenize(raw) >>>default_tagger =nltk.DefaultTagger('NN') >>>default_tagger.tag(tokens) [('I', 'NN'), ('do', 'NN'), ('not', 'NN'), ('like', 'NN'), ('green', 'NN'), ('eggs', 'NN'), ('and', 'NN'), ('ham', 'NN'), (',', 'NN'), ('I', 'NN'), ('do', 'NN'), ('not', 'NN'), ('like', 'NN'), ('them', 'NN'), ('Sam', 'NN'), ('I', 'NN'), ('am', 'NN'), ('!', 'NN')]
其实,大家也有感觉,这种方式并不会很好,可以通过下面这个函数,测评一下标注的结果。
>>>default_tagger.evaluate(brown_tagged_sents)
0.13089484257215028
正则表达式标注器
>>>patterns= [ ... (r'.*ing$', 'VBG'), #gerunds ... (r'.*ed$', 'VBD'), #simple past ... (r'.*es$', 'VBZ'), #3rdsingular present ... (r'.*ould$', 'MD'), #modals ... (r'.*\'s$', 'NN$'), #possessivenouns ... (r'.*s$', 'NNS'), #plural nouns ... (r'^-?[0-9]+(.[0-9]+)?$', 'CD'), #cardinal numbers ... (r'.*', 'NN') #nouns(default) ... ] #不过要注意,正则表达式是按顺序匹配的,匹配上第一个后面的就不会在匹配 >>>regexp_tagger = nltk.RegexpTagger(patterns) >>>regexp_tagger.tag(brown_sents[3]) [('``', 'NN'), ('Only', 'NN'), ('a', 'NN'), ('relative', 'NN'), ('handful', 'NN'), ('of', 'NN'), ('such', 'NN'), ('reports', 'NNS'), ('was', 'NNS'), ('received', 'VBD'), ("''", 'NN'), (',', 'NN'), ('the', 'NN'), ('jury', 'NN'), ('said', 'NN'), (',', 'NN'), ('``', 'NN'), ('considering', 'VBG'), ('the', 'NN'), ('widespread', 'NN'), ...] #通过检测,这种方式正确率提高了 >>>regexp_tagger.evaluate(brown_tagged_sents) 0.20326391789486245
查询标注器
#找出100个最频繁的词,存储他们最有可能的标记。 #然后使用这些信息作为查询标注器的模型 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,word,cfd[word].max()) for word in most_freq_words) baseline_tagger=nltk.UnigramTagger(model=likely_tags) baseline_tagger.evaluate(brown_tagged_sents)
通过对这个标注器进行评价,可以看到评价的结果,正确率又提升了:0.45578495136941344
如果我们拿这个标注器在一些未标注的文本上进行标注,会出现一些None的标签,这是因为它们不再100个最频繁的词汇当中。
#在这样的情况下,我们可以使用 回退,当查询标注器无法工作的时候,回退到另一个标注器进行工作。 >>>baseline_tagger =nltk.UnigramTagger(model=likely_tags, ... backoff=nltk.DefaultTagger('NN'))