在NLTK中评估词性标注器

3
我希望您能用文本文件作为输入来评估NLTK中不同的POS标签。
例如,我将使用Unigram标记器作为示例。我已经发现如何使用brown语料库评估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() 这样的分数,这样我就可以使用相同的输入文件比较不同的POS标注器,并确定适合给定文件的最合适的POS标注器。
非常感谢您的帮助。

1
你需要为测试句子准备真实标签。你可以使用现有的已标记句子集(比如你在第一个例子中使用的布朗语料库),或者找到一些对英语有很好了解的语言学家来手动标记你的句子。 - lenz
@Yash,你现在所做的与你尝试做的不同。你正在传递命令“default_tagger.tag(tokens)”,它会标记你的原始标记。为了能够评估标注器,你应该提供手动标记的数据。 - Mohammed
2个回答

9
这个问题实际上是关于模型评估指标的问题。在这种情况下,我们的模型是一个POS标记器,具体是UnigramTagger

量化

您想知道您的标记器表现如何。这是一个定性问题,因此我们有一些通用的定量指标来帮助定义“表现如何”的含义。基本上,我们有标准指标来提供这些信息。它们通常是准确度、精确度、召回率和F1分数。

评估

首先,我们需要一些带有POS标记的数据,然后我们可以进行测试。这通常被称为“训练/测试”拆分,因为我们使用一些数据来训练POS标记器,使用一些数据来测试或评估其性能。
由于POS标记通常是一个监督学习问题,我们需要一些带有POS标记的句子来进行训练和测试。

实际上,人们会对一堆句子进行标注,然后将它们拆分成测试训练集。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

现在,“准确率”是了解“你答对了多少”的一个可以接受的指标,但还有其他指标可以给我们更多细节,例如“精确度”,“召回率”和“f1-score”。我们可以使用“sklearn”的“classification_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

现在我们有一些想法和价值观可以用来量化我们的标记器,但我相信你会想,“这都很好,但它在随机句子上表现如何?”简单地说,除非您拥有自己的POS标记数据来测试我们想要测试的句子,否则我们永远不会确定!

0

你需要手动阅读已标记的数据,可以是自己标记或来自其他来源。然后按照你评估unigram标注器的方式进行操作。你不需要对手动标记的数据进行标记。假设你的新标记数据保存在变量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) - Yash
你正在错误地尝试解包一个字典。这与我的方法完全无关。 - Mohammed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接