中文文本纠错(Chinese Spell Checking, CSC)任务各个论文的评价指标

本文说明

本文汇总了中文文本纠错(Chinese Spell Checking)任务在各个开源项目中的评价指标,他们虽然写法不同,但大部分本质是相同的,但也有少部分论文的评价指标存在问题或其他论文不一致,本文对他们的指标代码进行了分析,并说明了其中的问题。

评价指标总结(结论)

中文文本纠错通常使用精准率(Precision)、召回率(Recall)和F1-Score作为评价指标,有如下四种:

  • Character-level Detection Metrics:少数论文使用了。意思是:按字为维度统计,能检测出错字的情况;就目前来看,大部分论文的该指标统计方式相同。
  • Character-level Correction Metrics:少数论文使用了。意思是:按字为维度统计,能正确纠正字的情况;目前找到有三篇论文使用了该指标,但多多少少都存在问题。(如果大家找到哪个开源项目使用了该指标,欢迎在评论区提醒,我会补充进来)
  • Sentence-level Detection Metrics:大部分论文使用了。意思是:按句子为维度统计,能检测出句子存在错字的情况。大部分论文对该指标统计方式相同。
  • Sentence-level Correction Metrics::几乎所有论文都使用了。意思是:按句子为维度,能完全正确修改句子的情况。大部分论文对该指标统计方式相同。

下面我将会使用混淆矩阵的方式给出这四种指标的定义,会用到的术语如下:①该纠:表示该句子(汉字)中存在错字。②不该纠:表示该句子(汉字)中不存在错字;③纠了:表示模型对该句子(汉字)进行了改错。④未纠:表示模型未对该句子(汉字)做任何修改

顺手写一下指标公式:

  • 准确率(Accuracy): (TP+TN) / (TP+FP+TN+FN)
  • 精准率(Precision): TP / (TP + FP)
  • 召回率(Recall): TP / (TP+FN)
  • F1-Score: (2 * Precision * Recall) / (Precsion + Recall)

Character-level Detection Metrics

实际值 / 预测值PN
P(TP) 该纠的字,纠了,纠没纠对不管(FN) 该纠的字,没纠
N(FP) 不该纠的字,纠了(TN) 不该纠的字,未纠

Character-level Correction Metrics

实际值 / 预测值PN
P(TP) 该纠的字,纠了也纠对了。(FN) 该纠的字,没纠或没纠对
N(FP) 不该纠的字,纠了。(TN) 不该纠的字,没纠

目前我看到只有PLOME和Confusionset-guided Pointer Networks这两篇论文的开源项目用了这个指标,但它们好像都有点问题。具体可以看下面对论文指标的详细解析。

Sentence-level Detection Metrics


SIGHAN 官方指标:

实际值 / 预测值PN
P(TP) 该纠,且该纠的字,都纠了,纠没纠对不管;不该纠的字,都没纠(FN) 该纠,但未纠或把不该纠的字纠了
N(FP) 不该纠,但纠了(TN) 不该纠,未纠

论文常用指标

实际值 / 预测值PN
P(TP) 该纠,且该纠的字,都纠了,纠没纠对不管;不该纠的字,都没纠(FN) 该纠,但未纠或把不该纠的字纠了
N(FP) “不该纠,但纠了” 或 “纠了,但把不该纠的字纠了”(TN) 不该纠,未纠

为什么官方和“论文常用指标”不一样,请参考“Sentence-level Correction Metrics(重点)”这节

Sentence-level Correction Metrics(重点)


SIGHAN官方工具的评价方式

实际值 / 预测值PN
P(TP) 该纠,且纠对了(FN)该纠,未纠或纠错了
N(FP) 不该纠,但纠了(TN) 不该纠,未纠

目前论文常用的评价方式

实际值 / 预测值PN
P(TP) 该纠,且纠对了(FN)该纠,未纠或纠错了
N(FP) “不该纠,但纠了” 或 “纠了,但没纠对(原句子是否有错不管)”(TN) 不该纠,未纠

在Sentence-level Correction Metrics上,现有的论文与SIGHAN的指标方式并不一样。现有的论文实验方式伪代码通常是这样:

true_positive = 0 # “原句子有错,且纠对了”的数量
target_postive = 0 # “原句子有错”的数量 
pred_positive = 0 # “对原句子进行了纠错(原句子是否有错不管)”的数量

for src, target, pred in (...):
	if src != target and target == pred:
		# 原句子有错,且纠对了
		true_positive += 1
	
	if src != target:
		# 原句子有错
		target_postive += 1
	
	if src != pred:
		# 对原句子进行了纠错(原句子是否有错不管)
		pred_positive += 1

precision = true_positive / pred_positive
recall = true_positive / target_postive

这种实现思路看似毫无问题:①精准率为“对于纠错的那部分句子中,纠对了的句子的比例” ②召回率为“对于该纠的那部分句子,纠对了的句子的比例”

然而,若通过混淆矩阵来看的话,似乎就发现了问题,部分样本重复出现在了“False Positive”中,导致精准率偏低

例如,对于如下样本:

  • src:我喜欢唱跳rap
  • tgt:我喜欢唱跳rap
  • pred: 我喜欢唱跳rap

对于该样本,其同时满足 “target_postive” 和 “pred_positive”,也就是该样本同时出现在了“精准率”和“召回率”的分母中。


因此,可以得出以下结论:

  1. 现有的SIGHAN官方的指标在精准率上要高于“论文常用指标”
  2. 现有的SIGHAN官方的指标在召回率上与“论文常用指标”相等
  3. 如果你看到某个论文的精准率特别高,那就说明它使用的是官方的指标,因此它与现有论文在F1上的比较是不公平的

各开源项目使用的评价指标

SIGHAN(官方)

Sentence-level Detection Metrics:

实际值 / 预测值PN
P(TP) 该纠,且该纠的字,都纠了,纠没纠对不管;不该纠的字,都没纠(FN) 该纠,但未纠或把不该纠的字纠了
N(FP) 不该纠,但纠了(TN) 不该纠,未纠

Sentence-level Correction Metrics:

实际值 / 预测值PN
P(TP) 该纠,且纠对了(FN)该纠,未纠或纠错了
N(FP) 不该纠,但纠了(TN) 不该纠,未纠

SIGHAN官方提供的工具是Java的,反编译后的部分代码如下:

while(...) {
	String id = (String)var20.next();
	// gct为真实值,rct为预测值。
	// 数据格式为:(位置, 字)
	// 例如:[(1, 鸡), (5, 美)],表示1位置字应该改成鸡,5位置字应该改成美
    Map<Integer, String> gctMap = (Map)gtMap.get(id);
    Map<Integer, String> rctMap = (Map)rtMap.get(id);
    if (gctMap.size() == 0) {  // 不该纠(句子没错)
        if (rctMap.size() == 0) { // 不该纠,没纠
            dtnSet.add(id);  // detect TN
            itnSet.add(id);  // correct TN (这里的i是Identification)
        } else {  // 不该纠,但纠了
            dfpSet.add(id);  // detect FP
            ifpSet.add(id);  // correct FP
        }
    } else if (rctMap.size() == 0) {  // 该纠,但没纠
        dfnSet.add(id); // detect FN
        ifnSet.add(id); // correct FN
    } else if (gctMap.keySet().containsAll(rctMap.keySet()) 
			   && gctMap.size() == rctMap.size()) { // 该纠,纠了,纠的位置也对。
        if (gctMap.values().containsAll(rctMap.values())) { // 该纠,纠对了
            dtpSet.add(id); // detect TP
            itpSet.add(id); // correct TP
        } else { // 该纠,且该纠的字,都纠了,但是有些字没纠对。
            dtpSet.add(id); // detect TP
            ifnSet.add(id); // correct FN
        }
    } else { // 该纠,纠了,但纠了不该纠的字。
        dfnSet.add(id); // detect FN
        ifnSet.add(id); // correct FN
    }
}

double fp = (double)dfpSet.size() / (double)(dfpSet.size() + dtnSet.size());
double daccuracy = ((double)dtpSet.size() + (double)dtnSet.size()) / (double)rtList.size();
double dprecision = (double)dtpSet.size() / (double)(dtpSet.size() + dfpSet.size());
double drecall = (double)dtpSet.size() / (double)(dtpSet.size() + dfnSet.size());
double df1Score = 2.0D * dprecision * drecall / (dprecision + drecall);
double iaccuracy = ((double)itpSet.size() + (double)itnSet.size()) / (double)rtList.size();
double iprecision = (double)itpSet.size() / (double)(itpSet.size() + ifpSet.size());
double irecall = (double)itpSet.size() / (double)(itpSet.size() + ifnSet.size());
double if1Score = 2.0D * iprecision * irecall / (iprecision + irecall);

Confusionset-guided Pointer Networks


论文地址:https://aclanthology.org/P19-1578.pdf


Character-level Detection Metrics:

实际值 / 预测值PN
P(TP) 该纠的字,纠了,纠没纠对不管(FN) 该纠的字,没纠
N(FP) 不该纠的字,纠了(TN) 不该纠的字,未纠
for ... in ...:
    gold_index = ... # 错字的位置。例如: [1, 3, 5]表示该句话1,3,5位置是错字
    predict_index = ... # 预测错字的位置。例如: [3, 5, 7]表示模型对3,5,7位置的字进行了纠错
    for i in predict_index:
        if i in gold_index:
            TP += 1  # 该纠的字,纠了,纠没纠对不管
        else:
            FP += 1  # 不该纠的字,纠了
    for i in gold_index:
        if i in predict_index:
            continue
        else:
            FN += 1	 # 该纠的字,但没纠

detection_precision = TP / (TP + FP) if (TP+FP) > 0 else 0
detection_recall = TP / (TP + FN) if (TP+FN) > 0 else 0
detection_f1 = 2 * (detection_precision * detection_recall) / (detection_precision + detection_recall) if (detection_precision + detection_recall) > 0 else 0

Character-level Correction Metrics:

作者与正常的Character-level Correction Metrics不一样,他只考虑了“该纠的字,纠了”这样的场景,其他场景不在该指标的考虑范围内。因此,本次不对该指标进行讨论。

for i in range(len(all_predict_true_index)):
    # we only detect those correctly detected location, which is a different from the common metrics since
    # we wanna to see the precision improve by using the confusionset
    if len(all_predict_true_index[i]) > 0:
        predict_words = []
        for j in all_predict_true_index[i]:
            predict_words.append(results[i][2][j])
            if results[i][1][j] == results[i][2][j]:
                TP += 1
            else:
                FP += 1
        for j in all_gold_index[i]:
            if results[i][1][j]  in predict_words:
                continue
            else:
                FN += 1

correction_precision = TP / (TP + FP) if (TP+FP) > 0 else 0
correction_recall = TP / (TP + FN) if (TP+FN) > 0 else 0
correction_f1 = 2 * (correction_precision * correction_recall) / (correction_precision + correction_recall) if (correction_precision + correction_recall) > 0 else 0

PLOME


Character-level Detection Metrics:

实际值 / 预测值PN
P(TP) 该纠的字,纠了,纠没纠对不管(FN) 该纠的字,没纠
N(FP) 不该纠的字,纠了(TN) 不该纠的字,未纠

Character-level Correction Metrics:

实际值 / 预测值PN
P(TP) 该纠的字,纠了也纠对了。(FN) 该纠的字,没纠
N(FP) 该纠的字,纠了,但没纠对。(TN) 不该纠的字,没纠

Character-level Correction Metrics这个指标应该有问题,这个FP应该不对。对于“不该纠的字,但纠了”这种场景没有被统计进去。例如:ori=‘张’, god=‘张’, prd=‘李’,这种场景没有被统计到Character-level Correction指标中。

for ... in ...:
     ori_txt = ... # 原字
     god_txt = ... # 正确字
     prd_txt = ... # 预测字
     
     # 不该纠的字,没纠。即TN
     if ori_txt == god_txt and ori_txt == prd_txt:
         continue
     if ori != god: # 该纠
         total_gold_err += 1 # 相当于(TP+FN)
     if prd != ori: # 纠了
         total_pred_err += 1 # 相当于(TP+FP)
     if (ori != god) and (prd != ori):  # 该纠,且纠了
         check_right_pred_err += 1  # 该纠,且纠了,不管对没对
         if god == prd: # 该纠,且纠对了
             right_pred_err += 1

# Detect P, R, F1
p = 1. * check_right_pred_err / (total_pred_err + 0.001)
r = 1. * check_right_pred_err / (total_gold_err + 0.001)
f = 2 * p * r / (p + r +  1e-13)

# Correct P, R, F1
pc = 1. * right_pred_err / (check_right_pred_err + 0.001) # TP/(TP+FP)
rc = 1. * right_pred_err / (total_gold_err + 0.001)	# TP/(TP+FN)
fc = 2 * pc * rc / (pc + rc + 1e-13) 

Sentence-level Detection Metrics:

实际值 / 预测值PN
P(TP) 该纠,且该纠的字,都纠了,纠没纠对不管;不该纠的字,都没纠(FN) 该纠,但未纠或把不该纠的字纠了
N(FP) 不该纠,但纠了 或 “纠了,但把不该纠的字纠了”(TN) 不该纠,未纠

Sentence-level Correction Metrics

实际值 / 预测值PN
P(TP) 该纠,且纠对了(FN)该纠,未纠或纠错了
N(FP) 不该纠,但纠了 或 “纠了,但没纠对(原句子是否有错不管)”(TN) 不该纠,未纠
for ... in ...:
	# errs存的是错字位置,例如:[1, 5],表示1和5位置上有错字
    gold_errs = ... # Label
    pred_errs = ... # 预测结果
	# tags存的是错字位置即改正后的字。例如:[(1, 鸡), (5, 美)],表示1位置字应该改成鸡,5位置字应该改成美
    god_tags = ... # Label
	pred_tags = .. # 预测结果
    # 该纠
    if len(gold_errs) > 0:
        total_gold_err += 1  # 相当于TP+FN
    
    # 纠了
    if len(pred_errs) > 0:
        total_pred_err += 1 # 相当于TP+FP
        if gold_errs == pred_errs: # 该纠的字都纠了,不该纠的字都没纠,纠没纠对不管
            check_right_pred_err += 1
        if god_tags == prd_tags: # 该纠,纠对了
            right_pred_err += 1

# Sentence-level Detection Metrics
p = 1. * check_right_pred_err / total_pred_err
r = 1. * check_right_pred_err / total_gold_err
f = 2 * p * r / (p + r + 1e-13)

# Sentence-level Correction Metrics
p = 1. * right_pred_err / total_pred_err
r = 1. * right_pred_err / total_gold_err
f = 2 * p * r / (p + r + 1e-13)

ReaLiSe

ReaLiSe字段说明:

  • targ/pred:存的是错字位置即改正后的字。例如:[(1, 鸡), (5, 美)],表示1位置字应该改成鸡,5位置字应该改成美

Sentence-level Detection Metrics:

实际值 / 预测值PN
P(TP) 该纠,且该纠的字,都纠了,纠没纠对不管;不该纠的字,都没纠(FN) 该纠,但未纠或把不该纠的字纠了
N(FP) 不该纠,但纠了 或 “纠了,但把不该纠的字纠了”(TN) 不该纠,未纠
for ... in ...:
	# 该纠的句子(句子有错字)
    if targ != []:
        targ_p += 1	# 相当于TP+FN
    # 纠了的句子(句子有没有错字不知道,模型认为有)
    if pred != []:
        pred_p += 1	# 相当于TP+FP
    # 不该纠,没纠;或 该纠,且该纠的字,都纠了,纠没纠对不管;不该纠的字,都没纠
    if len(pred) == len(targ) and all(p[0] == t[0] for p, t in zip(pred, targ)):
        hit += 1
    # 该纠,且该纠的字,都纠了,纠没纠对不管;不该纠的字,都没纠
    if pred != [] and len(pred) == len(targ) and all(p[0] == t[0] for p, t in zip(pred, targ)):
        tp += 1
     
acc = hit / len(targs)
p = tp / pred_p
r = tp / targ_p
f1 = 2 * p * r / (p + r) if p + r > 0 else 0.0

Sentence-level Correction Metrics:

实际值 / 预测值PN
P(TP) 该纠,且纠对了(FN)该纠,未纠或纠错了
N(FP) 不该纠,但纠了 或 “纠了,但没纠对(原句子是否有错不管)”(TN) 不该纠,未纠
for ... in ...:
	# 该纠的句子(句子有错字)
    if targ != []:
        targ_p += 1	# 相当于TP+FN
    # 纠了的句子(句子有没有错字不知道,模型认为有)
    if pred != []:
        pred_p += 1	# 相当于TP+FP
    # 不该纠,没纠;或 该纠,纠对了
    if pred == targ:
        hit += 1
    # 该纠,纠对了
    if pred != [] and pred == targ:
        tp += 1

acc = hit / len(targs)
p = tp / pred_p
r = tp / targ_p
f1 = 2 * p * r / (p + r) if p + r > 0 else 0.0

SpellGCN

SpellGCN字段说明:

  • detect_token:存的是错字所在的位置。例如: [1,5,7]表示1,5,7三个位置上的字存在错误。如果没有错字,则为[0]
  • correct_zip/correct_tokens:存的是错字位置即改正后的字。例如:[(1, 鸡), (5, 美)],表示1位置字应该改成鸡,5位置字应该改成美

Character-level Detection Metrics:

实际值 / 预测值PN
P(TP) 该纠的字,纠了,纠没纠对不管(FN) 该纠的字,没纠
N(FP) 不该纠的字,纠了(TN) 不该纠的字,未纠
for ... in ...:
	# 该纠的句子(句子中存在错字)
	if detect_actual_tokens[0]!=0:
		# 该纠的字,纠了,纠没纠对不管。
		# 例如:label为(1, 3, 5), pred为(3, 5, 7),则TP+=2,因为对两个该纠的字纠了
        detect_TP += len(set(max_detect_pred_tokens) & set(detect_actual_tokens)) 
        # 该纠的字,没纠
        # 例如:label为(1, 3, 5), pred为(3, 5, 7),FN+=1,因为1位置该纠但没纠
        detect_FN += len(set(detect_actual_tokens) - set(max_detect_pred_tokens))
    
    # 不该纠的字,但纠了
    # 例如:label为(1, 3, 5), pred为(3, 5, 7),FP+=1,因为7位置不该纠,但纠了
    detect_FP += len(set(max_detect_pred_tokens) - set(detect_actual_tokens)) 
    
detect_precision = detect_TP * 1.0 / (detect_TP + detect_FP)
detect_recall = detect_TP * 1.0 / (detect_TP + detect_FN)
detect_F1 = 2. * detect_precision * detect_recall/ ((detect_precision + detect_recall) + 1e-8)

Character-level Correction Metrics

实际值 / 预测值PN
P(TP) 该纠的字,纠了也纠对了。(FN) 纠了,但没纠对的字。(包括这个字本身有错和没错两种情况)
N(FP) 该纠的字,没纠对或没纠。(TN) 不该纠的字,没纠

这个指标好像有问题,因为“该纠,但没纠对的字”会被FN和FP重复计算。详情可以参考下面代码中的注释

for ... in ...:
	"""
	该纠的字,纠了也纠对了。
    例如:label为[(1, '鸡'), (3, '你'), (5, '太')], 
         pred为[(1, '坤'), (3, '你'), (5, '太'), (7, '美')]
         则TP+=2。  因为“你,太”两个字该纠且纠对了
	"""
	correct_TP += len(set(correct_pred_tokens) & set(zip(detect_actual_tokens,correct_actual_tokens))) 
	"""
	纠了,但没纠对的字。(包括这个字本身有错和没错两种情况)
    例如:label为[(1, '鸡'), (3, '你'), (5, '太')], 
         pred为[(1, '坤'), (3, '你'), (5, '太'), (7, '美')]
         则FP+=2。  因为'坤'字纠了,但没纠对。'美'字纠了,但7位置本身没错,所以也没纠对
	"""
    correct_FP += len(set(correct_pred_tokens) - set(zip(detect_actual_tokens,correct_actual_tokens)))
    """
	该纠的字,但没纠对或没纠。
    例如:label为[(1, '鸡'), (3, '你'), (5, '太'), (9, '美')], 
         pred为[(1, '坤'), (3, '你'), (5, '太')]
         则FN+=2。 因为'鸡'字没纠对,'美'字该纠但没纠
    这里这个指标好像出现了问题,对于'坤'字的错误预测,在FP和FN被重复计算了。
	"""
    correct_FN += len(set(zip(detect_actual_tokens,correct_actual_tokens)) - set(correct_pred_tokens)) 

correct_precision = correct_TP * 1.0 / (correct_TP + correct_FP)
correct_recall = correct_TP * 1.0 / (correct_TP + correct_FN)
correct_F1 = 2. * correct_precision * correct_recall/ ((correct_precision + correct_recall) + 1e-8)

Sentence-level Detection Metrics:

实际值 / 预测值PN
P(TP) 该纠,且该纠的字,都纠了,纠没纠对不管;不该纠的字,都没纠(FN) 该纠,但未纠或把不该纠的字纠了
N(FP) 不该纠,但纠了 或 “纠了,但把不该纠的字纠了”(TN) 不该纠,未纠
for ... in ...:
	# 不管该不该纠,反正纠了
	if detect_pred_tokens[0] !=  0:
        sent_P += 1	# 相当于TP+FP
    # 该纠的
    if detect_actual_tokens[0] != 0:
        sent_N += 1  # 相当于(TP+FN)
        if sorted(detect_actual_tokens) == sorted(detect_pred_tokens): 
		    detect_sent_TP += 1

detect_sent_precision = detect_sent_TP * 1.0 / (sent_P)
detect_sent_recall = detect_sent_TP * 1.0 / (sent_N)
detect_sent_F1 = 2. * detect_sent_precision * detect_sent_recall/ ((detect_sent_precision + detect_sent_recall) + 1e-8)

Sentence-level Correction Metrics

实际值 / 预测值PN
P(TP) 该纠,且纠对了(FN)该纠,未纠或纠错了
N(FP) 不该纠,但纠了 或 “纠了,但没纠对(原句子是否有错不管)”(TN) 不该纠,未纠

代码如下:

for ... in ...:
	# 不管该不该纠,反正纠了
	if detect_pred_tokens[0] !=  0:	# 表示预测句子中存在错字
        sent_P += 1	 # 相当于TP+FP
        # 该纠的,且纠对了(因为纠了,且纠对了,说明句子该纠)
        if sorted(correct_pred_zip) == sorted(correct_actual_zip):
          correct_sent_TP += 1
    # 该纠的
    if detect_actual_tokens[0] != 0:
        sent_N += 1	# 相当于(TP+FN)
	
correct_sent_precision = correct_sent_TP * 1.0 / (sent_P)
correct_sent_recall = correct_sent_TP * 1.0 / (sent_N)
correct_sent_F1 = 2. * correct_sent_precision * correct_sent_recall/ ((correct_sent_precision + correct_sent_recall) + 1e-8)

PyCorrector


Sentence-level Correction Metrics

实际值 / 预测值PN
P(TP) 该纠,且纠对了(FN)该纠,未纠或纠错了
N(FP) 不该纠,但纠了(TN) 不该纠,未纠

代码如下:

for ... in ...:
	# 负样本,不该纠的
	if src == tgt:
	    # 预测也为负
	    if tgt == tgt_pred:
	        TN += 1
	    # 预测为正
	    # 不该纠的,但是纠了,为FP
	    else:
	        FP += 1
	# 正样本,该纠错的
	else:
	    # 预测也为正
	    # 该纠错的句子,且纠对了,为TP
	    if tgt == tgt_pred:
	        TP += 1
	    # 预测为负
	    # 该纠的,没纠或者纠错了,为FN
	    else:
	        FN += 1
	
	total_num += 1
acc = (TP + TN) / total_num
precision = TP / (TP + FP) if TP > 0 else 0.0
recall = TP / (TP + FN) if TP > 0 else 0.0
f1 = 2 * precision * recall / (precision + recall) if precision + recall != 0 else 0

SCOPE

Sentence-level Correction Metrics

实际值 / 预测值PN
P(TP) 该纠,且纠对了(FN)该纠,未纠或纠错了
N(FP) 不该纠,但纠了 或 “纠了,但没纠对(原句子是否有错不管)”(TN) 不该纠,未纠

代码如下:

def sent_metric_correct(preds, targs):
    assert len(preds) == len(targs)
    # tp: true positive
    # targ_p: target positive
    # pred_p: prediction positive
    # hit: 预测正确的数量
    tp, targ_p, pred_p, hit = 0, 0, 0, 0
    for pred_item, targ_item in zip(preds, targs):
        assert pred_item[0] == targ_item[0]
        pred, targ = sorted(pred_item[1:]), sorted(targ_item[1:])
        if targ != []: # 如果target包含错字,则target positive加1
            targ_p += 1
        if pred != []: # 如果predition包含错字,则prediction positive加1
            pred_p += 1
        if pred == targ: # 如果target和预测结果一致,则hit+1。(不管原句是否存在错误)
            hit += 1
        if pred != [] and pred == targ: # 如果target和预测结果一致,且原句有错误,则true positive加1
            tp += 1

    acc = hit / len(targs)
    p = tp / pred_p
    r = tp / targ_p
    f1 = 2 * p * r / (p + r) if p + r > 0 else 0.0
	...

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iioSnail

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值