自然语言处理入门笔记-> 准确率评测

1,986 阅读4分钟

此文为学习何晗老师《自然语言处理入门》笔记

参考:

准确率是衡量一个系统准确程度的标准,可以理解为一系列评测指标。

混淆矩阵

在搜索引擎、分类器、中文分词场景下的准确率本质上是下图四个集合的并集运算。 下图中“纵坐标”为预测结果,“横坐标”为标准答案。 这种图表在机器学习中也称混淆矩阵(confusion matrix)

混淆矩阵性质:

  • 样本全集 = TP ∪ FP ∪ FN ∪ TN
  • 任何一个样本属于4个集合中的一个,即没有交集

精确率、召回率

在中文分词任务中,一般使用在标准数据集上词语级别的精确率、召回率与F1 计算方法

  • 精确率 (pricision,P) 指的是预测结果中正类数量占全部结果的比率。
  • 召回率 (recall, R) 指的是正类样本被找出来的比率。

精确率和召回率:一场拔河比赛

要全面评估模型的有效性,必须同时检查准确率和召回率。遗憾的是,准确率和召回率往往是此消彼长的情况。即提高准确率通常会导致降低召回率,反之亦然。

如下图显示了电子邮件分类模型做出了30项预测,分类阈值右侧的被归类为“垃圾邮件”,左侧的被归类为“非垃圾邮件”。

TP: 8 FP: 2
FN: 3 TN: 17

?P = \frac {8} {8 + 2} = 0.8? ?R = \frac {9} {8 + 3} = 0.73?

提高分类阈值后:

FP会减少,FN会增加。结果,精确率有所提高,召回率则有所降低:

TP: 7 FP: 1
FN: 4 TN: 18

?P = \frac {7} {7 + 1} = 0.88? ?R = \frac {7} {7 + 4} = 0.64?

降低分类阈值

FP增加,FN减少。结果,精确率有所降低,而召回率有所提高:

TP: 9 FP: 3
FN: 2 TN: 16

?P = \frac {9} {9 + 3} = 0.75? ?R = \frac {9} {9 + 2} = 0.82?

更合适的评测标准

在系统排名中,人们只习惯用一个指标F1值

?F1 = \frac {2 * P * R}{P+R}?

计算

标准答案构成一个集合A

分词结果所有单词构成一个集合B ?{TP}\cup{FN} = A? ?{TP}\cup{FP} = B? ?TP = A \cap B? ?P = \frac{|A \cap B|}{|B|}? ?R = \frac{|A \cap B|}{|A|}?

示例

100个病人,99个阴性,1个阳性,当预测阳性机器全部预测为阳性的时候

可见单纯的根据P或者R来评测并不客观。

OOV-R/IV-R

OOV指的是“未登录词”(Out Of Vocabulary),俗称新词,即词典未收录词汇。 如何正确切分OOV,乃至识别其语义,是整个NLP领域的难题之一。

IV指的是“登录词”(In Vocabulary)。 IV Recall Rate指的是词典中的词汇被正确召回的概率,连词典中的词汇都无法百分之百召回,说明词典分词的消歧能力不好。

OOV-R和IV-R是两个很有用的指标

计算方法

  • 标准词典dic
  • 记标准答案为A
  • 计算分词结果B
  • 统计标准答案A中,判断在词典dic中的累计IV,否则累计OOV
  • 统计在A & B (即TP)中,判断在词典dic中的累计IV_R,否则累计OOV_R ?{OOV-R} = \frac{OOV_R}{OOV}? ?{IV-R} = \frac{IV_R}{IV}?

代码(摘录自书本82页)

def prf(gold, pred, dic):
    """
    计算P R F1 OOV-R IV-R
    :param gold: 标准答案,比如“商品 和 服务”
    :param pred: 分词结果文件,比如“商品 和服 务”
    :param dic: 词典
    : return (P, R, F1, OOV-R, IV-R)
    """
    A_size, B_size, A_cap_B_size, OOV, IV, OOV_R, IV_R = 0, 0, 0, 0, 0, 0
    with open(gold) as gd, open(pred) as pd:
        for g, p in zip(gd, pd):
            # to_region 讲分词结果分为区间数组
            # 比如 “商品 和 服务” 转为 [(0, 2), (2, 3), (3, 5)]
            A, B = set(to_region(g)), set(to_region(p))
            A_size += len(A)
            B_size += len(B)
            A_cap_B_size += len(A & B)
            # \\s表示 空格,回车,换行等空白符
            text = re.sub("\\s+", "", g)
            # 计算标准答案
            for (start, end) in A:
                word = text(start: end)
                if dic.containsKey(word):
                    IV += 1
                else:
                    OOV += 1
            
            # 计算TP
            for (start, end) in A & B:
                word = text(start: end)
                if dic.containsKey(word)
                    IV_R += 1
                else:
                    OOV_R += 1
    
    P, R = A_cap_B_size / B_size * 100, A_cap_B_size / A_size * 100
    F1 = 2 * P * R / (P + R)
    IV-R, OOV-R = IV_R / IV, OOV_R / OOV
    return P, R, F1, IV-R, OOV-R