赞
踩
每个评估指标都有其价值,但如果只从单一的评估指标出发去评估模型,往往会得出片面甚至错误的结论;只有通过一组互补的指标去评估模型,才能更好地发现并解决模型存在的问题,从而更好地解决实际业务场景中遇到的问题。
前面说到的分类中的评估标准,但是在分词中标准答案和分词结果数不一定相等,因此要做一个思维转换。对于长为 n n n 的字符串,分词结果是一系列单词。设每个单词按照其在文中的起止位置可记作区间 [ i , j ] [i,j] [i,j] ,其中 i ≤ i ≤ j ≤ n i\leq i \leq j\leq n i≤i≤j≤n 。那么:
那么:
T
P
∪
F
N
=
A
T
P
∪
F
P
=
B
A
∩
B
=
T
P
因此相应的计算公式如下:
P r e c i s i o n = ∣ A ∩ B ∣ ∣ B ∣ , R e c a l l = ∣ A ∩ B ∣ ∣ A ∣ Precision=\frac{|A\cap B|}{|B|},\;Recall=\frac{|A\cap B|}{|A|} Precision=∣B∣∣A∩B∣,Recall=∣A∣∣A∩B∣
这样说可能有点晦涩,如下图所示:
可以发现,重合部分就是正确部分;因此,对于分词结果1来说,精确率和召回率均为0,因为没有重合部分。而对于分词结果2来说都为1。下面再来看个例子:
此时的精确率为: 3 / 5 = 0.6 3/5=0.6 3/5=0.6 ,召回率为: 3 / 6 = 0.5 3/6=0.5 3/6=0.5
OOV指的是“未登录词”(Out Of Vocabulary)的简称,也就是新词,已知词典中不存在的词。出现OOV的原因一方面可能确实是因为产生了有意义的新词而词典并没有收录;另一方面可能就是因为分词器产生的错误无意义的分词结果,这当然也不会出现在字典中。
IV指的是“登陆词”(In Vocabulary),也就是已经存在字典中的词。而OOV Recall和IV Recall 分别指的就是OOV的召回率和IV的召回率。为了说明这两个召回率的具体含义,请先耐心看下面的详细例子:
词典:[‘结婚’, ‘尚未’, ‘的’, ‘和’, ‘青年’, ‘都’, ‘应该’, ‘好好考虑’, ‘自己’, ‘人生’, ‘大事’]
标准分词 A:[‘结婚’,’ 的’,’ 和’,’ 尚未’,’ 结婚 ‘,‘的’,’ 都’,’ 应该’,’ 好好’,’ 考虑’,’ 一下’,’ 人生’,’ 大事’]
标准区间 A:[1,2],[3,3],[4,4],[5,6],[7,8],[9,9],[10,10],[11,12],[13,14],[15,16],[17,18],[19,20],[21,22]
分词结果 B:[‘结婚’,’ 的’,‘和尚’,‘未结婚 ‘,‘的 ‘,‘都’,’ 应该’,’ 好好考虑’,’ 一下’,’ 人生大事’]
分词区间 B:[1,2],[3,3],[4,5],[6,7,8],[9,9],[10,10],[11,12],[13,14,15,16],[17,18],[19,20,21,22]
重复词语 A∩B:[‘结婚’,’ 的’,’ 的’,’ 都’,’ 应该’,’ 一下’]
重复区间 A∩B:[1,2], [3,3], [9,9],[10,10],[11,12],[17,18]
R
e
c
a
l
l
=
6
10
=
0.6
P
r
e
c
i
s
i
o
n
=
6
13
=
0.4615
F
1
=
2
×
0.6
×
0.4615
0.6
+
0.4615
=
0.5217
O
O
V
R
e
c
a
l
l
=
重复词区间未在词典中出现的词
标准分词中未在词典中出现的词
=
1
3
=
0.3333
I
V
R
e
c
a
l
l
=
重复词区间在词典中出现的词
标准分词中在词典中出现的词
=
5
10
=
0.5
前面三项指标同第3节中的一样,不在赘述。从上面的计算过程可以看到:
O
O
V
R
e
c
a
l
l
=
重复词区间未在词典中出现的词
标准分词中未在词典中出现的词
=
重复词区间有意义的新词
所有有意义的新词
同理,从IV 召回率的计算公式可以发现重复词区间在词典中出现的词指的就是分词得到的正确部分(即正样本);标准分词中在词典中出现的词指的就是所有正样本。因此,IV 召回率就可以来衡量词典中的词被正确找回的概率。如果IV召回率低,就说明字典分词器连词典中的词汇都无法百分之百的发现或者找回,说明其消歧能力不好。例如“商品,和服,服务”三个词都在词典中,词典分词依然可能分布对句子”商品和服务“。
import re def to_region(segmentation: str) -> list: """ 将分词结果转换为区间 :param segmentation: 商品 和 服务 :return: [(0, 2), (2, 3), (3, 5)] """ region = [] start = 0 for word in re.compile("\\s+").split(segmentation.strip()): end = start + len(word) region.append((start, end)) start = end return region def prf(gold: str, pred: str, dic) -> tuple: """ 计算P、R、F1 :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, 0 A, B = set(to_region(gold)), set(to_region(pred)) A_size += len(A) B_size += len(B) A_cap_B_size += len(A & B) text = re.sub("\\s+", "", gold) for (start, end) in A: word = text[start: end] if word in dic: IV += 1 else: OOV += 1 for (start, end) in A & B: word = text[start: end] if word in dic: IV_R += 1 else: OOV_R += 1 p, r = A_cap_B_size / B_size * 100, A_cap_B_size / A_size * 100 return p, r, 2 * p * r / (p + r), OOV_R / OOV * 100, IV_R / IV * 100 if __name__ == '__main__': dic = ['结婚', '尚未', '的', '和', '青年', '都', '应该', '好好考虑', '自己', '人生', '大事'] gold = '结婚 的 和 尚未 结婚 的 都 应该 好好 考虑 一下 人生 大事' pred = '结婚 的 和尚 未结婚 的 都 应该 好好考虑 一下 人生大事' print("Precision:%.2f Recall:%.2f F1:%.2f OOV-R:%.2f IV-R:%.2f" % prf(gold, pred, dic))
参考资料:
NLP中文分词的评估指标
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。