注:本文首发于 GiantPandaCV

EM

EM 是 exact match 的简称,所以就很好理解,em 表示预测值和答案是否完全一样。

def calc_em_score(answers, prediction):
    em = 0
    for ans in answers:
        # 删掉标点符号
        ans_ = remove_punctuation(ans)
        prediction_ = remove_punctuation(prediction)
        if ans_ == prediction_:
            # 只有在预测和答案完全一样时 em 值为1,否则为0
            em = 1
            break
    return em

参考:

F1

分别计算准确率和召回率, F1 是准确率和召回率的调和平均数。

def calc_f1_score(answers, prediction):
    f1_scores = []
    for ans in answers:
        # 分词后的答案,分词方法参见附录2
        ans_segs = mixed_segmentation(ans, rm_punc=True)
        # 分词后的预测
        prediction_segs = mixed_segmentation(prediction, rm_punc=True)
        # 计算答案和预测之间的最长公共子序列,参见附录1
        lcs, lcs_len = find_lcs(ans_segs, prediction_segs)
        if lcs_len == 0:
            f1_scores.append(0)
            continue
        # 准确率和 lcs_len/len(prediction_segs) 成正比
        precision = 1.0*lcs_len/len(prediction_segs)
        # 召回率和 lcs_len/len(ans_segs) 成正比
        recall = 1.0*lcs_len/len(ans_segs)
        # 准确率和召回率的调和平均数
        f1 = (2*precision*recall)/(precision+recall)
        f1_scores.append(f1)
    return max(f1_scores)

对于准确率和召回率增加下了解。看一个例子,如下图所示,方框代表全集,黄色圈代表正确结果集合,斜纹圈代表返回的预测结果。这样就构成了如下几个部分:

Untitled

这时再来看 F1 的计算,就更直观了:

Untitled