【问题标题】:Evaluating POS tagger in NLTK评估 NLTK 中的词性标注器
【发布时间】:2017-10-12 15:36:44
【问题描述】:

我想使用文本文件作为输入来评估 NLTK 中的不同 POS 标签。

例如,我将使用 Unigram 标注器。我发现了如何使用棕色语料库评估 Unigram 标签。

from nltk.corpus import brown
import nltk

brown_tagged_sents = brown.tagged_sents(categories='news')
brown_sents = brown.sents(categories='news')
# We train a UnigramTagger by specifying tagged sentence data as a parameter
# when we initialize the tagger.
unigram_tagger = nltk.UnigramTagger(brown_tagged_sents)
print(unigram_tagger.tag(brown_sents[2007]))
print(unigram_tagger.evaluate(brown_tagged_sents))

它产生如下输出。

[('Various', 'JJ'), ('of', 'IN'), ('the', 'AT'), ('apartments', 'NNS'), ('are', 'BER'), ('of', 'IN'), ('the', 'AT'), ('terrace', 'NN'), ('type', 'NN'), (',', ','), ('being', 'BEG'), ('on', 'IN'), ('the', 'AT'), ('ground', 'NN'), ('floor', 'NN'), ('so', 'QL'), ('that', 'CS'), ('entrance', 'NN'), ('is', 'BEZ'), ('direct', 'JJ'), ('.', '.')]
0.9349006503968017

以类似的方式,我想从文本文件中读取文本并评估不同 POS 标记器的准确性。

我想出了如何读取文本文件以及如何为令牌应用 pos 标签。

import nltk
from nltk.corpus import brown
from nltk.corpus import state_union

brown_tagged_sents = brown.tagged_sents(categories='news')

sample_text = state_union.raw(
    r"C:\pythonprojects\tagger_nlt\new-testing.txt")
tokens = nltk.word_tokenize(sample_text)

default_tagger = nltk.UnigramTagger(brown_tagged_sents)

default_tagger.tag(tokens)

print(default_tagger.tag(tokens))
[('Honestly', None), ('last', 'AP'), ('seven', 'CD'), ('lectures', None), ('are', 'BER'), ('good', 'JJ'), ('.', '.'), ('Lectures', None), ('are', 'BER'), ('understandable', 'JJ')

我想要的是一个类似 default_tagger.evaluate() 的分数,这样我就可以使用相同的输入文件比较 NLTK 中的不同 POS 标记器,以确定最适合给定的 POS 标记器文件。

任何帮助将不胜感激。

【问题讨论】:

  • 您的测试句子需要真实标签。您要么使用现有的标记句子集(如您在第一个示例中使用的布朗语料库),要么找一些精通英语且愿意手动标记句子的语言学家。
  • @Yash 您正在尝试做的事情与您现在正在做的事情不同。您正在传递命令 default_tagger.tag(tokens) 并标记您的原始令牌。您应该提供手动标记的数据,以便能够评估标记器。

标签: python nlp nltk linguistics pos-tagger


【解决方案1】:

这个问题本质上是关于模型评估指标的问题。在这种情况下,我们的模型是一个词性标注器,特别是UnigramTagger

量化

您想知道您的标注员在做什么“how well”。这是一个qualitative 问题,所以我们有一些通用的quantitative 指标来帮助定义“how well”的含义。基本上,我们有标准的指标来为我们提供这些信息。它们通常是accuracyprecisionrecallf1-score

评估

首先,我们需要一些用POS tags 标记的数据,然后我们可以进行测试。这通常被称为train/test 拆分,因为我们使用一些数据来训练 POS 标注器,还有一些用于测试或evaluating 它的性能。

由于 POS 标记传统上是一个supervised learning 问题,我们需要一些带有 POS 标记的句子来训练和测试。

在实践中,人们标记一堆句子,然后将它们拆分为testtrain 集合。 NLTK book解释的很好,我们来试试吧。

from nltk import UnigramTagger
from nltk.corpus import brown
# we'll use the brown corpus with universal tagset for readability
tagged_sentences = brown.tagged_sents(categories="news", tagset="universal")

# let's keep 20% of the data for testing, and 80 for training
i = int(len(tagged_sentences)*0.2)
train_sentences = tagged_sentences[i:]
test_sentences = tagged_sentences[:i]

# let's train the tagger with out train sentences
unigram_tagger = UnigramTagger(train_sentences)
# now let's evaluate with out test sentences
# default evaluation metric for nltk taggers is accuracy
accuracy = unigram_tagger.evaluate(test_sentences)

print("Accuracy:", accuracy)
Accuracy: 0.8630364649525858

现在,accuracy 是了解“how many you got right”的好指标,但还有其他指标可以为我们提供更多详细信息,例如 precisionrecallf1-score。我们可以使用sklearnclassification_report 给我们一个很好的结果概览。

tagged_test_sentences = unigram_tagger.tag_sents([[token for token,tag in sent] for sent in test_sentences])
gold = [str(tag) for sentence in test_sentences for token,tag in sentence]
pred = [str(tag) for sentence in tagged_test_sentences for token,tag in sentence]
from sklearn import metrics
print(metrics.classification_report(gold, pred))

             precision    recall  f1-score   support

          .       1.00      1.00      1.00      2107
        ADJ       0.89      0.79      0.84      1341
        ADP       0.97      0.92      0.94      2621
        ADV       0.93      0.79      0.86       573
       CONJ       1.00      1.00      1.00       453
        DET       1.00      0.99      1.00      2456
       NOUN       0.96      0.76      0.85      6265
        NUM       0.99      0.85      0.92       379
       None       0.00      0.00      0.00         0
       PRON       1.00      0.96      0.98       502
        PRT       0.69      0.96      0.80       481
       VERB       0.96      0.83      0.89      3274
          X       0.10      0.17      0.12         6

avg / total       0.96      0.86      0.91     20458

现在我们有一些想法和价值观可以用来量化我们的标注器,但我相信你在想,“That's all well and good, but how well does it perform on random sentences?

简单地说,就是其他答案中提到的,除非你有我们要测试的句子的 POS 标记数据,否则我们永远无法确定!

【讨论】:

    【解决方案2】:

    您需要自己或从其他来源读取手动标记的数据。然后按照您评估一元标记器的方式。您不需要标记手动标记的数据。假设你的新标签数据保存在一个名为yash_new_test的变量中,那么你需要做的就是执行这个命令:

     `print(unigram_tagger.evaluate(yash_new_test))`
    

    我希望这会有所帮助!

    【讨论】:

    • 我运行了你的建议,它给了我这个错误。 tagged_sents = self.tag_sents(untag(sent) for sent in gold) ValueError: too many values to unpack (expected 2)
    • 您试图以错误的方式解压字典。这与我的方法完全无关。
    猜你喜欢
    • 1970-01-01
    • 2015-02-20
    • 2015-11-13
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多