如何计算POS标签的标签精度和召回率?

时间:2011-03-10 19:04:04

标签: python shell nlp machine-learning text-processing

我正在使用一些基于规则和统计的POS标记器来标记语料库(大约 5000个句子),并使用词性(POS)。以下是我的测试语料库的片段,其中每个单词由其各自的POS标签分隔为'/'。

No/RB ,/, it/PRP was/VBD n't/RB Black/NNP Monday/NNP ./.
But/CC while/IN the/DT New/NNP York/NNP Stock/NNP Exchange/NNP did/VBD n't/RB fall/VB apart/RB Friday/NNP as/IN the/DT Dow/NNP Jones/NNP Industrial/NNP Average/NNP plunged/VBD 190.58/CD points/NNS --/: most/JJS of/IN it/PRP in/IN the/DT final/JJ hour/NN --/: it/PRP barely/RB managed/VBD *-2/-NONE- to/TO stay/VB this/DT side/NN of/IN chaos/NN ./.
Some/DT ``/`` circuit/NN breakers/NNS ''/'' installed/VBN */-NONE- after/IN the/DT October/NNP 1987/CD crash/NN failed/VBD their/PRP$ first/JJ test/NN ,/, traders/NNS say/VBP 0/-NONE- *T*-1/-NONE- ,/, *-2/-NONE- unable/JJ *-3/-NONE- to/TO cool/VB the/DT selling/NN panic/NN in/IN both/DT stocks/NNS and/CC futures/NNS ./.

标记语料库后,它看起来像这样:

No/DT ,/, it/PRP was/VBD n't/RB Black/NNP Monday/NNP ./. 
But/CC while/IN the/DT New/NNP York/NNP Stock/NNP Exchange/NNP did/VBD n't/RB fall/VB apart/RB Friday/VB as/IN the/DT Dow/NNP Jones/NNP Industrial/NNP Average/JJ plunged/VBN 190.58/CD points/NNS --/: most/RBS of/IN it/PRP in/IN the/DT final/JJ hour/NN --/: it/PRP barely/RB managed/VBD *-2/-NONE- to/TO stay/VB this/DT side/NN of/IN chaos/NNS ./. 
Some/DT ``/`` circuit/NN breakers/NNS ''/'' installed/VBN */-NONE- after/IN the/DT October/NNP 1987/CD crash/NN failed/VBD their/PRP$ first/JJ test/NN ,/, traders/NNS say/VB 0/-NONE- *T*-1/-NONE- ,/, *-2/-NONE- unable/JJ *-3/-NONE- to/TO cool/VB the/DT selling/VBG panic/NN in/IN both/DT stocks/NNS and/CC futures/NNS ./. 

我需要计算标记准确度(标记方式 - 召回和精确度),因此需要在每个字标记对的标记中找到错误(如果有)。

我想到的方法是遍历这两个文本文件并将它们存储在一个列表中,然后逐个元素地比较'two'列表。

这种做法对我来说似乎很粗糙,所以希望你们能为这个问题提出更好的解决方案。

来自wikipedia页面:

  

在分类任务中,   一个类的精度是多少   真阳性(即数量)   正确标记为属于的项目   到积极的阶级)除以   标记为的元素总数   属于正面阶级(即   真正的积极和虚假的总和   积极的,这是项目不正确   标记为属于该类)。   此上下文中的召回定义为   真正积极的数量除以   按元素的总数   实际上属于积极的阶级   (即真阳性和积极的总和   假阴性,是哪些项目   没有被标记为属于   积极的,但应该是)。

1 个答案:

答案 0 :(得分:6)

请注意,由于每个单词只有一个标记,因此整体调用和精度分数对于此任务毫无意义(它们都只是等于精度度量)。但要求每个标签的召回和精确度测量是有意义的 - 例如,您可以找到DT标签的召回和精确度。

同时对所有标记执行此操作的最有效方法与您建议的方式类似,但您可以通过跳过列表制作阶段来保存一遍数据。读入每个文件的一行,逐字逐行比较两行,然后重复,直到到达文件末尾。对于每个单词比较,您可能希望检查单词是否相等,而不是假设两个文件同步。对于每种标记,您保留三个运行总计:真阳性,误报和漏报。如果当前单词的两个标记匹配,则增加标记的真正正数。如果它们不匹配,则需要增加真实标签的假阴性总数和机器错误选择的标签的误报总数。最后,您可以按照Wikipedia摘录中的公式计算每个标签的回忆和精确度分数。

我没有测试过这段代码而我的Python是一个但却生锈的,但这应该会给你一个想法。我假设文件是​​打开的,totals数据结构是字典词典:

finished = false
while not finished:
    trueLine = testFile.readline()
    if not trueLine: # end of file
        finished = true
    else:
        trueLine = trueLine.split() # tokenise by whitespace
        taggedLine = taggedFile.readline()
        if not taggedLine:
            print 'Error: files are out of sync.'
        taggedLine = taggedLine.split()
        if len(trueLine) != len(taggedLine):
            print 'Error: files are out of sync.'
        for i in range(len(trueLine)):
            truePair = trueLine[i].split('/')
            taggedPair = taggedLine[i].split('/')
            if truePair[0] != taggedPair[0]: # the words should match
                print 'Error: files are out of sync.'
            trueTag = truePair[1]
            guessedTag = taggedPair[1]
            if trueTag == guessedTag:
                totals[trueTag]['truePositives'] += 1
            else:
                totals[trueTag]['falseNegatives'] += 1
                totals[guessedTag]['falsePositives'] += 1