使用HuggingFace计算Rouge-L分数异常偏低的问题求助
问题:Rouge-L分数远低于基线结果,Rouge-1/2表现正常
我用HuggingFace相关工具计算文本摘要的Rouge分数时,Rouge-1和Rouge-2分数和基线接近,但Rouge-L分数大幅偏低。比如在elife数据集上,基线模型lead-k的Rouge分数为34.12(R-1)、6.73(R-2)、32.06(R-L),而我的计算结果是37.18、7.97、15.05,明显计算逻辑存在问题。
我的原始代码:
import evaluate import transformers import os import torch from datasets import list_datasets, load_dataset import nltk import numpy as np rouge = evaluate.load('rouge') elife = load_dataset('tomasg25/scientific_lay_summarisation', 'elife') print(elife) """ lexsum = load_dataset('allenai/multi_lexsum') print(lexsum) """ refs = [] predicts_lead3 = [] predicts_leadk = [] for text in elife['test']['summary']: refs.append(text) for text in elife['test']['article']: predicts_lead3.append(' '.join(nltk.sent_tokenize(text)[:3])) predicts_leadk.append(' '.join(text.split(' ')[:383])) result_3 = rouge.compute(predictions=predicts_lead3, references=refs) print("lead 3 results:") print(result_3) result_k = rouge.compute(predictions=predicts_leadk, references=refs) print("lead k results:") print(result_k)
问题根源
- Rouge-L计算模式不匹配:HuggingFace的
evaluate库默认计算的rougeL是对整个文档的最长公共子序列(LCS),而多数文献中的基线用的是rougeLsum——对每个句子单独计算LCS后取平均,这是分数差异的核心原因。 - lead-k截断逻辑错误:直接用
split(' ')[:383]会把句子拆成不完整的片段,而基线通常是取完整句子直到总词数接近指定值。 - 缺少统一预处理:基线一般会对文本做小写转换、标准分词等处理,原始代码未做一致预处理,导致计算偏差。
修复方案
1. 统一文本预处理
添加预处理函数,对齐基线的文本处理逻辑:
def preprocess(text): # 转小写+标准分词 text = text.lower() tokens = nltk.word_tokenize(text) return ' '.join(tokens)
2. 切换Rouge-L为sum模式
在rouge.compute()中指定rouge_types为["rouge1", "rouge2", "rougeLsum"],启用聚合计算:
result_k = rouge.compute( predictions=predicts_leadk, references=refs, rouge_types=["rouge1", "rouge2", "rougeLsum"], use_aggregator=True )
3. 修正lead-k截断逻辑
改为取完整句子,直到总词数不超过383:
for text in elife['test']['article']: sentences = nltk.sent_tokenize(text) lead_k_words = [] total_words = 0 for sent in sentences: words = nltk.word_tokenize(sent) if total_words + len(words) <= 383: lead_k_words.extend(words) total_words += len(words) else: break predicts_leadk.append(' '.join(lead_k_words))
完整修正代码
import evaluate import nltk from datasets import load_dataset # 下载nltk必要资源 nltk.download('punkt') rouge = evaluate.load('rouge') # 加载数据集 elife = load_dataset('tomasg25/scientific_lay_summarisation', 'elife') # 预处理函数 def preprocess(text): text = text.lower() tokens = nltk.word_tokenize(text) return ' '.join(tokens) refs = [] predicts_lead3 = [] predicts_leadk = [] # 处理参考摘要 for text in elife['test']['summary']: refs.append(preprocess(text)) # 处理预测结果 for text in elife['test']['article']: # lead-3:取前3个完整句子 sentences = nltk.sent_tokenize(text) lead3_text = ' '.join(sentences[:3]) predicts_lead3.append(preprocess(lead3_text)) # lead-k:取完整句子直到总词数不超过383 lead_k_words = [] total_words = 0 for sent in sentences: words = nltk.word_tokenize(sent) if total_words + len(words) <= 383: lead_k_words.extend(words) total_words += len(words) else: break predicts_leadk.append(' '.join(lead_k_words)) # 计算Rouge,指定rougeLsum模式 result_3 = rouge.compute( predictions=predicts_lead3, references=refs, rouge_types=["rouge1", "rouge2", "rougeLsum"], use_aggregator=True ) print("lead 3 results:") print(result_3) result_k = rouge.compute( predictions=predicts_leadk, references=refs, rouge_types=["rouge1", "rouge2", "rougeLsum"], use_aggregator=True ) print("lead k results:") print(result_k)
内容的提问来源于stack exchange,提问作者Yifan Wang
相关产品推荐
相关产品推荐

