You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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)

问题根源

  1. Rouge-L计算模式不匹配:HuggingFace的evaluate库默认计算的rougeL是对整个文档的最长公共子序列(LCS),而多数文献中的基线用的是rougeLsum——对每个句子单独计算LCS后取平均,这是分数差异的核心原因。
  2. lead-k截断逻辑错误:直接用split(' ')[:383]会把句子拆成不完整的片段,而基线通常是取完整句子直到总词数接近指定值。
  3. 缺少统一预处理:基线一般会对文本做小写转换、标准分词等处理,原始代码未做一致预处理,导致计算偏差。

修复方案

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 18:15:27