当前位置: 首页 > news >正文

DeepSeek BLEU和ROUGE(Recall)的计算

以下是 BLEU Score (Bilingual ​Evaluation ​Understudy)和 ROUGE Score(​Recall-Oriented ​Understudy for ​Gisting ​Evaluation) 的原生Python实现(不依赖第三方库),通过分步计算逻辑和示例详细说明。


一、BLEU Score 实现

核心逻辑
  1. n-gram匹配:计算候选文本和参考文本的n-gram匹配数(截断到参考文本中最大出现次数)。
  2. 精确度计算:各n-gram的匹配数除以候选文本n-gram总数。
  3. 几何平均:对1-gram到4-gram的精确度取几何平均。
  4. 长度惩罚:候选文本过短时施加惩罚。
代码实现
import math

def get_ngrams(text, n):
    """生成n-gram列表"""
    return [tuple(text[i:i+n]) for i in range(len(text)-n+1)]

def bleu_score(candidate, reference, max_n=4):
    """计算BLEU分数(单参考文本简化版)"""
    candidate = candidate.split()
    reference = reference.split()
    
    # 长度惩罚
    c_len = len(candidate)
    r_len = len(reference)
    bp = 1.0 if c_len > r_len else math.exp(1 - r_len / c_len) if c_len !=0 else 0.0

    # 计算各n-gram的精确度
    precisions = []
    for n in range(1, max_n+1):
        # 生成候选和参考的n-gram
        cand_ngrams = get_ngrams(candidate, n)
        ref_ngrams = get_ngrams(reference, n)
        
        # 统计匹配数(截断到参考中的最大出现次数)
        match_count = 0
        ref_counts = {}
        for gram in ref_ngrams:
            ref_counts[gram] = ref_counts.get(gram, 0) + 1
        
        for gram in cand_ngrams:
            if ref_counts.get(gram, 0) > 0:
                match_count += 1
                ref_counts[gram] -= 1  # 避免重复匹配
        
        # 计算精确度
        if len(cand_ngrams) == 0:
            p_n = 0.0
        else:
            p_n = match_count / len(cand_ngrams)
        precisions.append(p_n)
    
    # 几何平均(避免零值)
    geom_mean = math.exp(sum(math.log(p + 1e-10) for p in precisions) / max_n)
    bleu = bp * geom_mean
    return bleu
示例
reference = "the cat is on the mat"
candidate1 = "the the the the the"  # 低质量候选
candidate2 = "the cat is on the mat"  # 完美匹配

print(bleu_score(candidate1, reference))  # 输出接近0.0
print(bleu_score(candidate2, reference))  # 输出1.0(完美匹配)

二、ROUGE Score 实现(以ROUGE-N和ROUGE-L为例)

1. ROUGE-N(基于n-gram的召回率)
def rouge_n(candidate, reference, n=1):
    """计算ROUGE-N分数(召回率)"""
    cand_ngrams = get_ngrams(candidate.split(), n)
    ref_ngrams = get_ngrams(reference.split(), n)
    
    # 统计匹配数
    ref_gram_counts = {}
    for gram in ref_ngrams:
        ref_gram_counts[gram] = ref_gram_counts.get(gram, 0) + 1
    
    match_count = 0
    for gram in cand_ngrams:
        if ref_gram_counts.get(gram, 0) > 0:
            match_count += 1
            ref_gram_counts[gram] -= 1  # 避免重复匹配
    
    # 召回率 = 匹配数 / 参考文本中的n-gram总数
    rouge = match_count / len(ref_ngrams) if len(ref_ngrams) > 0 else 0.0
    return rouge
2. ROUGE-L(基于最长公共子序列,LCS)
def lcs_length(x, y):
    """计算最长公共子序列长度"""
    m, n = len(x), len(y)
    dp = [[0]*(n+1) for _ in range(m+1)]
    for i in range(1, m+1):
        for j in range(1, n+1):
            if x[i-1] == y[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(candidate, reference):
    """计算ROUGE-L分数(F1值)"""
    cand_tokens = candidate.split()
    ref_tokens = reference.split()
    lcs = lcs_length(cand_tokens, ref_tokens)
    
    # 精确率 = LCS长度 / 候选文本长度
    precision = lcs / len(cand_tokens) if len(cand_tokens) > 0 else 0.0
    # 召回率 = LCS长度 / 参考文本长度
    recall = lcs / len(ref_tokens) if len(ref_tokens) > 0 else 0.0
    # F1值
    f1 = 2 * precision * recall / (precision + recall + 1e-10)
    return f1
示例
reference = "the cat is on the mat"
candidate = "the cat sits"  # 部分匹配

# ROUGE-1
print(rouge_n(candidate, reference, n=1))  # 输出 2/6 ≈ 0.333

# ROUGE-L
print(rouge_l(candidate, reference))      # LCS长度=2("the cat")
# 精确率=2/3≈0.666,召回率=2/6≈0.333 → F1≈0.444

三、对比说明

指标核心公式示例输出(候选文本:the cat sits
BLEU几何平均+长度惩罚接近0.0(因4-gram不匹配)
ROUGE-1匹配1-gram数 / 参考1-gram数2/6 ≈ 0.333
ROUGE-LLCS的F1值0.444(精确率0.666,召回率0.333)

四、关键点总结

  1. BLEU:强调生成文本的精确度和长度匹配。
  2. ROUGE-N:关注参考文本的内容覆盖度(召回率)。
  3. ROUGE-L:通过最长公共子序列衡量语义连贯性。

通过原生Python实现,可以更深入理解这些指标的计算逻辑,适用于定制化需求或教学场景。

相关文章:

  • torch.cat和torch.stack的区别
  • 应急响应靶机-Linux(1)
  • 数据结构*包装类泛型
  • C语言进阶之指针
  • CMD命令行笔记
  • 数据库实验:分组查询与聚集函数的使用
  • Vue3状态管理深度实战:Pinia架构设计与企业级应用
  • C#核心学习(十六)面向对象--关联知识点(2)string和Stringbuilder
  • 案例驱动的 IT 团队管理:创新与突破之路: 第四章 危机应对:从风险预见到创新破局-4.1.3重构过程中的团队士气管理
  • 202524 | 分布式事务
  • 《基于 RNN 的股票预测模型代码优化:从重塑到直接可视化》
  • 设计模式——抽象工厂模式总结
  • AcWing 6093. 不互质子序列
  • ubuntu 安装samba
  • 奇葩问题:PGPOOL自动容灾切换,主备不生效原因
  • 部署YUM仓库
  • 卡码网55:右旋字符串
  • 【android bluetooth 框架分析 02】【Module详解 3】【HciHal 模块介绍】
  • 【tRPC-go】message、context相关源码设计思路
  • vue 入门:生命周期
  • 腾讯重构混元大模型研发体系:成立大语言和多模态模型部,提升AI长期技术作战能力
  • 总书记考察的上海“模速空间”,是一个怎样的空间?
  • 今年一季度全国社会物流总额达91万亿元,工业品比重超八成
  • 葡萄牙、西班牙突发大范围停电,交通和通信服务受到严重影响
  • 流浪猫给车主造成困扰,长春一小区拟投药应对?律师:此举欠妥
  • 古籍新书·2025年春季|中国土司制度史料集成