资讯详情

资讯详情

ROUGE评估指标详解:从原理到工程实践

1. ROUGE是什么为什么文本生成离不开它做自然语言生成NLG的人几乎天天要和评价指标打交道。无论是做摘要生成、对话回复、翻译还是标题创作跑完模型后的第一件事就是拿生成结果和参考答案做对比。而在这一堆指标里ROUGE 是我个人用得最多、也最“皮实”的一个。ROUGE 的全称是 Recall-Oriented Understudy for Gisting Evaluation中文一般翻译成“面向召回率的摘要评估替身”。听名字就知道这玩意儿最早就是为摘要评估设计的核心思路特别直白看你生成的内容里有多少词或短语和参考摘要对得上。对得越多得分越高。它的最大优势是无需训练、即插即用。你不需要像学 BERTScore 那样引入一个语义模型也不需要像算 Perplexity 那样让模型跑一次前向传播。只要把两段文本拿来做个词级别的匹配结果就出来了。也正因为计算成本极低ROUGE 成了学术界和工业界事实上的“标配”从 ACL 论文到 Kaggle 竞赛从搜索引擎的摘要评测到客服机器人的话术优化到处都能看到它的身影。但这里我得先泼一盆冷水ROUGE 的“对比”停留在字面层面它衡量的是 n-gram 重叠度而不是语义相似度。换句话说如果你的生成结果用词完全不同、但意思一模一样ROUGE 分数反而会很低。这就是为什么我后面要花大篇幅讲它的原理和变体——只有搞清楚它到底在算什么你才能判断一个分数到底可不可信也才能在调模型和选指标的时候做出更合理的决策。这篇文章我会从 ROUGE 的核心设计逻辑讲起再把 ROUGE-N、ROUGE-L、ROUGE-S 这几个主流变体逐个拆开配上可以直接跑的 Python 代码示例最后聊一聊我在实际项目中踩过的坑和总结出来的排查技巧。希望能帮你不仅会用 ROUGE还能用得明白、用得不吃亏。2. ROUGE 的核心设计逻辑与 BLEU 的恩怨纠葛2.1 从召回率出发的设计哲学要理解 ROUGE必须先理解一个概念召回率Recall。稍微回顾一下信息检索里的定义召回率 检索到的相关文档数 / 系统中所有相关文档总数。它衡量的是“该找的有没有找全”。ROUGE 的设计者把这套逻辑搬到了文本生成里。假设参考摘要里有 100 个词你的生成结果里有 80 个词和参考摘要重合那么 ROUGE 的召回率就是 80%。这个数字直观地告诉你参考摘要里的信息你到底覆盖了多少。那为什么设计者这么执着于召回率而不直接看准确率Precision呢因为摘要生成这个任务有一个特殊性同一个意思可以有无数种不同的表达方式。你写“小明去超市买了苹果”参考摘要写的是“小明购入了水果”字面上一毛钱关系都没有但在语义上确实有关联。如果只看准确率即你生成的内容里有多少是正确的那面对“怎么表达都对”的情况根本没法公平打分。ROUGE 策略性地选择了召回率作为核心等于在说只要你把参考摘要里的关键内容覆盖到了我就认为你干得不错。这在早期的摘要评估里非常合理因为参考摘要本身就是人工提炼的“标准答案”覆盖了全部重要信息。你的生成结果能覆盖得越多说明摘要质量越高。2.2 ROUGE 与 BLEU 的互补关系聊 ROUGE 不可能绕过 BLEU。这两个指标经常被拿来对比但实际上它们是互补的。BLEUBilingual Evaluation Understudy最早是为机器翻译设计的核心是 n-gram 的准确率外加一个“简短惩罚”来防止生成过短的句子。用大白话说BLEU 关心的是“你说出来的话里有多少是对的”而 ROUGE 关心的是“该说的话你是不是都说到了”。举个很典型的例子。假设参考翻译是“The cat sat on the mat”模型 A 生成“The cat sat”模型 B 生成“A dog stood on the floor”。BLEU 会给 A 更高的分数因为 A 说出来的每个词都能在参考里找到但 ROUGE 会给 A 相对合理的分数但不高因为 A 漏掉了“on the mat”这部分信息。反过来如果模型 C 生成“The cat sat on the mat quickly”它多说了“quickly”BLEU 可能因为 n-gram 不怎么匹配而扣分但 ROUGE 只看召回率的话反而会拿到很高的分数。所以在实际使用中我更倾向于把 BLEU 和 ROUGE 一起报告。BLEU 告诉你生成文本的“精确度”如何ROUGE 告诉你“信息覆盖率”如何。两者一横一纵能把生成质量的不同侧面勾勒出来。2.3 文本生成评估的“标准答案依赖症”无论是 ROUGE 还是 BLEU都有一个共同的致命前提你必须有一份或多份参考标准答案。没有参考这些指标就完全失效。这一点在做开放域生成任务时要格外小心。比如闲聊机器人你去问它“今天天气怎么样”答案可能有一百种合法表达你给参考答案的时候很难穷举所有可能性。这时候 ROUGE 分数往往会偏低而且这种“低分”不一定代表生成质量差可能只是你的参考答案覆盖不够全。我用过一个取巧的办法在构建测试集的时候尽量给每一条样本收集三份以上的人工参考。多参考不仅能让 ROUGE 分数更稳定也能部分弥补它只看字面重叠的缺陷。ROUGE 官方实现里是支持多参考的计算时会取所有参考里的最高分数作为最终值这一点后面讲公式的时候会再提。3. ROUGE 家族核心变体从 n-gram 到最长公共子序列3.1 ROUGE-N最基础的 n-gram 重叠统计ROUGE-N 是 ROUGE 家族里最朴素、也最好理解的一个变体。它的计算方式就是统计生成文本和参考文本之间的 n-gram 重叠数量然后除以参考文本的 n-gram 总数。以 ROUGE-1 为例1-gram 就是单个词。参考摘要“猫坐在垫子上”分词后得到“猫 / 坐在 / 垫子 / 上”四个词生成摘要“猫趴在垫子上面”分词后得到“猫 / 趴在 / 垫子 / 上面”。两者共有的 1-gram 有“猫”和“垫子”共 2 个。参考摘要总共有 4 个 1-gram所以 ROUGE-1 召回率是 2 / 4 0.5。ROUGE-2 以此类推看的是相邻两个词的组合。上面这个例子里参考摘要的 2-gram 有“猫坐在”“坐在垫子”“垫子上”三个生成摘要的 2-gram 有“猫趴在”“趴在垫子”“垫子上面”。两者没有任何一个 2-gram 完全一致所以 ROUGE-2 就是 0。这个例子很好地说明了 ROUGE-N 的一个特性N 越大对语序和用词的要求越严格。在实际工作中我用得最多的是 ROUGE-1 和 ROUGE-2。ROUGE-1 能粗略反映信息点覆盖情况ROUGE-2 可以反映短语级别的流畅度。ROUGE-3 及以上就不太常用了因为三四个词的连续短语完全匹配的概率太低分数很容易趋近于零区分度很差。3.2 ROUGE-L最长公共子序列的巧妙之处ROUGE-L 是我个人非常喜欢的一个变体它用了动态规划里的最长公共子序列Longest Common SubsequenceLCS来做匹配。这里要特别强调一下是子序列不是子串。子序列允许跳词匹配也就是说两个词不需要在原文里紧挨着只要先后顺序一致就行。举个例子。参考文本是“我今天去超市买了苹果”生成文本是“我去了超市并且买了苹果”。连续的 2-gram 匹配几乎没有但如果按子序列来看“我 / 去 / 超市 / 买 / 苹果”这五个词是可以在两个文本里按顺序对应上的所以 LCS 长度是 5。ROUGE-L 的公式稍微复杂一点它会分别计算基于召回率的 LCS 分数和基于精确率的 LCS 分数然后取一个加权调和平均也就是 F 值。这里的权重系数 β 通常取一个很大的数让召回率占主导地位以符合 ROUGE 家族一贯的定位。ROUGE-L 的价值在于它天然对词序敏感但不像 ROUGE-2 那么苛刻。它既能捕捉到短语级别的信息流动又允许中间插入一些额外的词。对于生成式摘要这种需要重新组织语言的场景ROUGE-L 往往比 ROUGE-2 更能反映真实质量。3.3 ROUGE-W 和 ROUGE-S更精细的匹配策略ROUGE-W 是 ROUGE-L 的加权版本它的核心思想是给“连续匹配”的片段加权。在普通的 LCS 计算里一个长度 5 的连续匹配和一个由 5 个离散词组成的跳跃匹配得到的分数是一样的。但直觉告诉我们连续匹配的片段更能反映原文的语序和结构信息含量更高。ROUGE-W 通过对连续匹配长度施加平方级别的加权让这类匹配能拿到更高的分数。ROUGE-S 则走的是另一条路它允许跳过若干词来匹配二元组也就是 skip-bigram。比如参考文本有“A B C”三个词ROUGE-S 会生成三个 skip-bigramAB、AC、BC。只要生成文本里出现任意一个这样的词对不要求相邻就算一次匹配。这个设计弥补了 ROUGE-1 不考量词序、ROUGE-2 又过分严苛的中间空白地带。ROUGE-SU 是在 ROUGE-S 的基础上再加上了 unigram 匹配以便处理那些对子匹配不上但单词匹配得上的情况。在实际项目里ROUGE-W 用得相对少因为它的加权系数需要人工调节而且在多数场景下和 ROUGE-L 的差异并不显著。ROUGE-S 偶尔会在句子级生成任务中用到比如对话回复的评估。如果你刚开始接触 ROUGE我建议先吃透 ROUGE-1、ROUGE-2 和 ROUGE-L 这三个足够覆盖九成以上的评估需求。4. 从原理到代码手写实现与现成库的使用4.1 手写一个极简版 ROUGE彻底弄懂内部逻辑说实话ROUGE 的公式看着唬人但代码实现起来并不复杂。我自己第一次手写的时候大概只用了几十行 Python 就搞定了最核心的 ROUGE-N 和 ROUGE-L。这里分享一个精简版本目的是帮你理解计算过程生产环境直接调用现成库就行。from collections import Counter def tokenize(text): # 这里做了一个最小化的分词转小写 按非字母数字符号切分 # 中文场景建议改用 jieba 或直接按字切分后面会细讲 return text.lower().split() def rouge_n(reference, candidate, n2): ref_tokens tokenize(reference) cand_tokens tokenize(candidate) # 生成参考文本的 n-gram 集合 ref_ngrams Counter( tuple(ref_tokens[i:in]) for i in range(len(ref_tokens)-n1) ) cand_ngrams Counter( tuple(cand_tokens[i:in]) for i in range(len(cand_tokens)-n1) ) # 统计匹配的 n-gram 数量 overlap sum((ref_ngrams cand_ngrams).values()) total sum(ref_ngrams.values()) recall overlap / total if total 0 else 0.0 precision overlap / sum(cand_ngrams.values()) if cand_ngrams else 0.0 f1 2 * precision * recall / (precision recall) if (precision recall) 0 else 0.0 return {recall: recall, precision: precision, f1: f1} # 示例 ref the cat sat on the mat cand the cat sat print(rouge_n(ref, cand, n1)) print(rouge_n(ref, cand, n2))这段代码里Counter的求交集运算符会取两个计数器中相同 key 的最小计数正好对应了 n-gram 匹配里的“取最小值”逻辑。我在初学的时候经常在这里犯迷糊以为用集合的intersection就行但那样会丢掉重复 n-gram 的计数信息。下面是 ROUGE-L 的极简实现用的是标准的动态规划求 LCS 长度def lcs_length(a, b): m, n len(a), len(b) dp [[0] * (n 1) for _ in range(m 1)] for i in range(1, m 1): for j in range(1, n 1): if a[i-1] b[j-1]: dp[i][j] dp[i-1][j-1] 1 else: dp[i][j] max(dp[i-1][j], dp[i][j-1]) return dp[m][n] def rouge_l(reference, candidate): ref_tokens tokenize(reference) cand_tokens tokenize(candidate) lcs lcs_length(ref_tokens, cand_tokens) recall lcs / len(ref_tokens) if ref_tokens else 0.0 precision lcs / len(cand_tokens) if cand_tokens else 0.0 beta 1.2 # 论文里常用的值让召回率权重更高 f1 (1 beta**2) * precision * recall / (beta**2 * precision recall) if (beta**2 * precision recall) 0 else 0.0 return {recall: recall, precision: precision, f1: f1} ref the cat sat on the mat cand the cat sat under a mat print(rouge_l(ref, cand))这个实现的时间复杂度是 O(mn)在文本长度较短的评估场景里完全够用。如果文本特别长可以考虑用 Hunt-Szymanski 算法优化但实际上评测集里的单条文本通常不超过几百个词暴力动态规划不会成为性能瓶颈。4.2 生产环境首选rouge-score 与 HuggingFace Evaluate手写代码是理解原理的好方法但到了真正的实验阶段我强烈建议用现成的库。目前 Python 生态里最主流的是rouge-score它是 Google Research 出的也是很多论文里默认的评测工具。安装很简单pip install rouge-score基本用法如下from rouge_score import rouge_scorer scorer rouge_scorer.RougeScorer( [rouge1, rouge2, rougeL], use_stemmerTrue ) scores scorer.score( the cat sat on the mat, the cat sat ) for key in scores: print(key, scores[key])use_stemmerTrue这个参数值得单独说一下。它会把英文单词还原成词根形式比如“running”和“ran”会被视为同一个词进行匹配。这能部分缓解词形变化对评估的影响让分数更贴近语义层面的匹配。代价是稍微损失一些对用词精确度的敏感度。如果做的任务是机器翻译这类对用词要求较高的场景建议关掉 stemmer如果是摘要生成这种更看重信息覆盖的场景开着效果更好。如果你本身已经在用 HuggingFace 的生态也可以直接用evaluate库import evaluate rouge evaluate.load(rouge) results rouge.compute( predictions[the cat sat on the mat], references[the cat sat] ) print(results)这个库的好处是接口统一而且内部封装了rouge-score结果和 Google 的官方实现基本一致。它还支持一次性传入多个参考使用起来非常方便。4.3 多参考分数的聚合策略前面提到过ROUGE 支持多参考。在多参考场景下标准做法是对每个参考分别计算分数然后取最大值。这个逻辑非常直观只要你的生成结果能匹配上任何一份参考就说明它在某种程度上是可接受的。from rouge_score import rouge_scorer scorer rouge_scorer.RougeScorer([rougeL], use_stemmerTrue) candidate the cat sat on the mat references [ a cat is sitting on a mat, the cat sat on the mat ] scores [scorer.score(ref, candidate)[rougeL].fmeasure for ref in references] print(max(scores))这里有个细节需要注意scorer.score的第一个参数是参考第二个参数是生成结果。千万别传反了否则你算出来的实际上是“反向”的匹配分数虽然数值上看起来差不多但在文本长度差异较大的情况下会产生明显偏差。我身边不止一个同事在这个参数顺序上踩过坑。5. 实战中的关键决策分词、语言适配与场景选型5.1 中文场景的 ROUGE 计算按字还是按词这一节可以说是全文最“接地气”的部分了。ROUGE 最早是为英文设计的英文天然以空格分词所以split()一下就能用。但到了中文事情就没有那么简单了。我在项目里试过两种中文处理方式各有优劣。第一种是按字切分。把“猫坐在垫子上”切成“猫 / 坐 / 在 / 垫 / 子 / 上”。这样做的好处是简单粗暴、没有任何歧义而且对未登录词的适应性极强。缺点是忽略了词边界会让一些本来不该匹配的片段“误匹配”上。比如“人民日报”和“人民日报”按字切分的话会有大量重合按词切分则完全不同。第二种是按词切分用 jieba、pkuseg 这类分词工具先分词再做 ROUGE 计算。这种方式更贴近中文的语言习惯尤其是在短语级别的匹配上更准确。但分词器本身会引入误差有些专有名词切不对反而影响分数。我的建议是做粗颗粒度对比的时候用按字切分稳定性更好不受分词器影响论文里也更容易复现做细颗粒度调优的时候用按词切分因为词级别的重叠更能反映语义单元的对齐程度。顺带提醒一下很多开源库的“中文支持”并没有你想的那么完善。rouge-score本身不做分词它只负责匹配所以你在调用之前需要自己对中文文本先做处理。标准化流程一般是分词或按字切分→ 去标点 → 转小写中文不需要→ 送入 ROUGE 计算。5.2 文本预处理对分数的影响到底有多大文本预处理对 ROUGE 分数的影响远远超出很多人的想象。我做过一个实验同样的生成结果和参考文本仅仅因为标点符号处理方式不同ROUGE-L 的 F1 值能从 0.52 波动到 0.61。这 0.09 的差距在论文的表格里可能就决定了你是“显著优于 baseline”还是“没区别”。核心的问题在于标点符号要不要参与 n-gram 匹配rouge-score的默认实现里标点符号是被当成 token 的一部分处理的。英文里“hello,”和“hello”会被视为不同的 token括号、引号也会影响匹配。这在大部分场景下没问题因为参考和生成通常都遵循类似的标点风格。但如果你做的是语音识别ASR后的文本生成评估识别结果里经常没有标点这时候直接用rouge-score算出来的分数会低得离谱。我常用的预处理策略是先将文本统一转小写然后剥离所有标点符号保留中英文空格作为分词边界最后再送入 ROUGE 计算。这样得到的分数更关注词汇和信息层面的匹配不受格式干扰。还有一个很容易被忽略的实践细节数字格式的统一。参考文本里写“2024年”生成文本里写“2024 年”多了一个空格在按空格切分的情况下会导致“2024”和“年”的连接方式不同ROUGE-2 的分数会受到影响。类似的情况还包括日期格式Jan. 1 vs January 1、金额格式$100 vs 100 dollars等。如果你做的领域里这些情况很常见建议在预处理阶段做一层简单的标准化映射。5.3 不同 NLG 任务怎么选 ROUGE 变体不是所有任务都适合用同一套 ROUGE 配置。我在不同项目里的经验是这样做新闻摘要生成重点看 ROUGE-1 和 ROUGE-L。新闻摘要讲究信息覆盖和关键信息的保留ROUGE-1 能衡量“关键实体和话题词有没有被提到”ROUGE-L 能衡量“句子的主干结构是不是保留了”。做对话回复生成ROUGE-L 比 ROUGE-1 更可靠。对话回复经常会出现大量口语化的语气词和填充词ROUGE-1 很容易被这些词的偶然重叠干扰。ROUGE-L 基于子序列匹配对这种场景更鲁棒。做标题生成ROUGE-1 和 ROUGE-2 都有参考价值。标题通常很短信息高度浓缩ROUGE-1 能粗看核心关键词的覆盖ROUGE-2 能看出短语级别的表达是否和参考标题重合。做机器翻译除非特别需要不然我一般不推荐用 ROUGE。翻译更看重的是“说对了没有”而不是“信息覆盖全不全”BLEU 在这类任务里表现更好。你可以同时报两个指标但要知道哪个是主力、哪个是辅助。5.4 ROUGE 与人工评估、语义指标的关系我见过不少新手拿到 ROUGE 分数就开始盲目优化结果分数涨了实际生成质量反而下降了。原因很简单ROUGE 只衡量字面重叠它会被一些“投机取巧”的行为骗到。举个例子。在做摘要生成时模型发现把参考摘要里的关键词全部原样搬到生成结果里能显著提高 ROUGE 分数。于是它学会了“复制集锦”——把文档里最像摘要关键词的句子原封不动地抽出来拼在一起。这种结果在 ROUGE 上表现确实很好但读起来句子之间毫无逻辑连接根本不能算一篇合格的摘要。这就是为什么我在实际项目中从不只看 ROUGE 一个指标。通常的搭配是ROUGE 看信息覆盖 BERTScore 看语义相似 人工抽样看可读性。BERTScore 是另一类基于预训练模型的评价指标它能捕捉到“用词不同但意思相近”的情况正好弥补 ROUGE 在这方面的盲区。还有一点要特别注意ROUGE 分数只能在“同一组实验的横向对比”中有意义。你说你的模型 ROUGE-L 是 0.45我说我的模型 ROUGE-L 是 0.42如果我们在不同的测试集、不同的分词方式、不同的预处理流程下算出来的那这个对比是没有意义的。论文里报告 ROUGE 分数时一定要注明测试集、分词方式、是否使用 stemmer、是否多参考等条件否则读者根本没法复现。6. 高频踩坑记录与排查速查表6.1 参数顺序传反分数虚高的假象这是一个非常隐蔽的坑。rouge_scorer.score(reference, candidate)参考在前面生成结果在后面。有的人图省事写成score(candidate, reference)跑出来的数字看着也没毛病但语义已经完全变了。为什么说它隐蔽因为在大部分情况下两个方向算出来的分数差值不会特别夸张特别是当参考和生成文本长度接近时。可一旦你的生成结果特别长——比如模型倾向于输出很啰嗦的答案——反向计算会让分数出现明显虚高。我从一个项目里抓到过这个问题反向计算时 ROUGE-1 的 F1 比正向高了 0.08而这 0.08 刚好把模型从“不显著”推到了“显著”的位置上。排查方法很简单随便拿一条样本手算一遍对比库输出的结果方向对不对一目了然。6.2 重复生成内容拉高 ROUGE 分数ROUGE 的召回率定义决定了它对“废话连篇”的文本是相对宽容的。假设参考摘要里有一个关键词“苹果”你的生成结果前半段把“苹果”说了一遍后半段又重复说了一遍ROUGE 的召回率只会统计你“有没有覆盖”不会因为你重复了就惩罚你。这个问题在长文本生成任务里尤其严重。模型生成 500 字参考摘要只有 100 字只要这 500 字里反复提及参考中的关键实体ROUGE-1 的召回率就会很高尽管整段文本的可读性和信息密度极差。我在项目里的应对办法是同时计算 F1 值而不仅仅看召回率。F1 值综合了精确率和召回率如果生成文本冗余精确率就会下降F1 自然会被拉低。另外如果你有明确的长度限制需求可以在评估时对超长结果做截断处理或者直接用长度惩罚项来修正。6.3 分词器和 Stemmer 导致的中英文匹配错位如果你在同一个项目里既评估中文数据又评估英文数据最容易遇到的一个问题是分词方式不一致导致的不可比性。中文按字切分得到的结果和英文按词 stemmer 得到的结果数值范围完全不同。你不能拿中文的 ROUGE-1 0.45 和英文的 ROUGE-1 0.45 说“两者一样好”这没有意义。还有一个相对小众但很实际的坑多语言混排文本。比如商品标题“Apple iPhone 15 128GB 蓝色”中英文混在一起。英文部分按空格切分没问题但中文部分会被整体当成一个 token导致中文字符完全不参与匹配。处理这种数据时我通常先做语言检测把中英文分离中文部分按字切分英文部分按词切分再合并送入 ROUGE 计算。6.4 常见问题速查表现象可能原因排查与建议分数比自己预期低很多标点符号进了 token或大小写未归一化预处理阶段剥离标点、统一小写再评估中文任务分数普遍偏低没有对中文做分词/按字处理整个句子被当成一个 token使用 jieba 分词或按字符切分两版模型分数差异极小但人工感觉差异大ROUGE 对近义词替换不敏感语义改动不体现在字面重叠上增加 BERTScore 或人工抽样评估分数虚高接近 1.0生成结果疑似复制参考文本或存在严重的数据泄露检查测试集与训练集是否有重叠同一条样本多次计算分数不同可能在用随机性分词器或存在未固定随机种子的预处理固定分词器的随机种子确认预处理流程确定性6.5 分数波动的稳定性验证方法评估指标的可信度取决于它自身的稳定性。我建议你在跑完一轮实验后花十分钟做一个简单的稳定性验证把测试集随机分成五份分别计算模型在每一份上的 ROUGE 分数看看方差大不大。如果某一折的分数明显偏离其他四折说明你的测试集里可能存在分布不均匀的情况这时候报告整体均值会掩盖真实表现。更进一步可以使用置信区间来报告结果。用 Bootstrap 重采样法对测试集做有放回的抽样重复 1000 次每次计算一个 ROUGE 分数最后取 95% 分位数作为置信区间。这样别人看你的论文时能在一定程度上感知到分数的可靠性。这也是目前一些顶会论文里比较推荐的做法。7. 我对 ROUGE 使用习惯的几点总结我在实际项目中兜兜转转最后沉淀下来的 ROUGE 使用习惯可以浓缩成三句话用 ROUGE-L 兜底用 ROUGE-1 看覆盖用 ROUGE-2 辅助诊断。ROUGE-L 作为最稳健的子序列匹配指标几乎适用于所有文本生成场景ROUGE-1 在信息覆盖类任务里是最直观的信号ROUGE-2 则是一个敏感的“照妖镜”它一旦偏低通常说明模型在短语级别的表达能力出了问题。另外我想特别提醒一点做实验的时候所有的生成结果和参考文本都应该在评估前统一固定下来尽量不要在得到分数之后再去反推预处理方式。我在早期吃过这个亏——因为某种预处理让分数更好看就不自觉地选了它这实际上是在玩弄指标而不是在评估模型。正确的做法是先定好评估方案再跑实验最后老老实实接受分数。最后再分享一个我一直在用的小技巧在提交论文或项目报告之前我习惯随机抽取二三十条生成结果把 ROUGE 分数高的、中等的、低的各挑几条出来人工看一眼。ROUGE 分数高的样本是否真的读起来通顺分数低的样本是不是其实质量不错、只是用词不同这个人工抽检过程往往比看一整张指标表格更能帮你发现模型的真实问题。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →