查看全课大纲(第 86 / 93 节)
  1. 1.计算机视觉概述
  2. 2.计算机视觉应用场景
  3. 3.困难与挑战
  4. 4.开源库介绍
  5. 5.图像显示与存储
  6. 6.CLAHE
  7. 7.腐蚀膨胀与开闭运算
  8. 8.滤波与边缘填充
  9. 9.各种滤波
  10. 10.图像金字塔
  11. 11.傅里叶变换
  12. 12.短时傅里叶变换与小波变换
  13. 13.颜色特征与颜色直方图
  14. 14.几何特征_边缘
  15. 15.几何特征-角点与斑点
  16. 16.局部特征-SIFT特征描述子
  17. 17.局部特征-SURF特征描述子
  18. 18.局部特征-ORB特征描述子
  19. 19.其他特征描述子
  20. 20.传统图像分割技术
  21. 21.GraphCut
  22. 22.GrabCut
  23. 23.人脸检测的传统方法
  24. 24.行人检测的传统方法HOG+SVM
  25. 25.行人检测DPM
  26. 26.人工神经网络的架构
  27. 27.目标函数与梯度下降
  28. 28.误差反向传播
  29. 29.可手算的神经网络
  30. 30.改进目标函数与克服梯度消散
  31. 31.神经网络之传统神经网络与深度网络的差异
  32. 32.各种梯度下降算法
  33. 33.如何选择合适的梯度下降算法
  34. 34.避免过适应
  35. 35.CNN的架构
  36. 36.CNN的误差反向传播_卷积层
  37. 37.CNN的误差反向传播_池化层
  38. 38.分类所用的数据集
  39. 39.Alexnet详解
  40. 40.VGG详解
  41. 41.GoogLeNet_v1
  42. 42.BatchNormalization
  43. 43.GoogLeNet_v3v4
  44. 44.ResNet
  45. 45.ResNeXt
  46. 46.CNN设计准则
  47. 47.图像检索与推土机距离
  48. 48.基于颜色相似性
  49. 49.基于形状相似性
  50. 50.基于纹理相似性
  51. 51.基于局部特征相似性
  52. 52.DL的二值哈希编码
  53. 53.高维空间中检索KDTree
  54. 54.高维空间中检索LSH
  55. 55.目标识别任务综述
  56. 56.RCNN
  57. 57.SPP-Net
  58. 58.Fast R-CNN
  59. 59.Faster R-CNN
  60. 60.R-CNN系列模型回顾
  61. 61.R-FCN的设计思路
  62. 62.R-FCN的实现
  63. 63.YOLOv1
  64. 64.YOLOv2_9000
  65. 65.YOLOv3
  66. 66.图像分割应用场景与数据集
  67. 67.上采样的实现方式
  68. 68.FCN网络架构的由来
  69. 69.FCN构建细节
  70. 70.DeepLabv1
  71. 71.CRF
  72. 72.DeepLabv2
  73. 73.DeepLabv3
  74. 74.特定的医学影像分割任务
  75. 75.U-Net
  76. 76.3D U-Net
  77. 77.V-Net
  78. 78.DenseNet
  79. 79.病理切片分析任务及数据集
  80. 80.病理切片分析
  81. 81.图说任务及其传统处理方法
  82. 82.深度语言模型与RNN
  83. 83.LSTM及其变种
  84. 84.NIC模型
  85. 85.SAT模型
  86. 86.图说的性能指标
  87. 87.判别模型与生成模型
  88. 88.KL散度与JS散度
  89. 89.VAE
  90. 90.GAN的基本原理
  91. 91.DCGAN与CGAN
  92. 92.Wasserstein GAN
  93. 93.SRGAN

图说的性能指标

小象实战讲义 · 基于深度学习的计算机视觉

图像描述(图说)模型能够为图片生成自然语言描述,但如何客观地评价这些描述的质量呢?本节课,我们将系统学习图像描述领域常用的几种自动化评价指标,理解它们的设计思想、计算方式以及各自的优缺点,从而能够为模型性能评估选择合适的指标。

需要先说明一个背景:图说任务兴起较晚,因此它并没有从零设计评价体系,而是借用了机器翻译(以及自动摘要)领域已有的指标——BLEU最早,可视为机器翻译评测的行业标准;ROUGE与BLEU几乎是同一框架,只是把精确率换成了召回率;METEOR则另辟蹊径,走的是词对齐、加权F值与碎化惩罚的路子,还引入了同义词和词干匹配,与BLEU的n-gram精确率框架并不相同;只有CIDEr是真正为图像描述设计的。

💡 核心导读

  • BLEU:最早的评价指标,源自机器翻译,基于n-gram精确率,衡量用词准确性和句子流畅性。
  • ROUGE:最初为自动摘要设计、后被借用到机器翻译与图说,基于召回率,关注参考描述中的词是否被模型“召回”。
  • METEOR:与人类评价最接近,引入同义词匹配和“chunk”概念,综合评价准确率、召回率和流畅度。
  • CIDEr:专为图像描述设计,将句子视为TF-IDF向量,通过余弦相似度打分,能区分不同词的重要性。
  • 主观指标与数据集:了解流畅度、相关性、助盲性等主观评价维度,以及MS COCO等主流数据集的特点。

BLEU:基于n-gram精确率的评价指标

BLEU(Bilingual Evaluation Understudy)最早是机器翻译领域的评价标准,在该领域几乎可以算作行业标准,后来被借用到图像描述任务中。它通过比较模型生成的描述(候选描述)与人工标注的参考描述之间的n-gram重叠程度来打分。

核心思想:计算候选描述中出现的n-gram有多少出现在参考描述中,其百分比作为精确率(Precision)。

这里的n-gram是指连续的n个词(对于英文)或字(对于中文)构成的序列。例如,对于句子“机器翻译评测”,其中文n-gram是这样切分的:

  • 1-gram(unigram):[“机”, “器”, “翻”, “译”, “评”, “测”]
  • 2-gram(bigram):[“机器”, “器翻”, “翻译”, “译评”, “评测”]
  • 3-gram(trigram):[“机器翻”, “器翻译”, “翻译评”, “译评测”]

注意“器翻”“译评”并不是词,但作为n-gram依然是合法的序列片段——n-gram只看位置是否连续,不要求语义成词。对英文则按空格分词,如“the cat is on the mat”。

BLEU通常计算n从1到4的n-gram精确率,然后进行几何平均。不同n的精确率代表不同层面的质量:

  • unigram精确率:衡量单词翻译或使用的准确性。
  • 更高阶n-gram精确率:衡量句子的流畅性。因为连续多个词都匹配上,说明语序和搭配更合理。

还有一点需要注意:参考描述通常不止一句。图说数据集一般给每张图片配3到5句人工描述,BLEU会对每句参考分别统计匹配次数(同一n-gram在候选中出现多次时,匹配数取它在各参考中的最大出现次数),从而避免候选靠重复某个词刷分。

为了更公平地评价,BLEU还引入了两项改进:

  1. 截断计数(clipping):同一 n-gram 的匹配次数取 min⁡(候选中的出现次数, max⁡参考参考中的出现次数)\min(\text{候选中的出现次数},\ \max_{\text{参考}}\text{参考中的出现次数}),避免候选靠重复某个词刷分。需要说明的是,BLEU 本身不做停用词处理,它对所有 n-gram 等权——这正是它后来被 METEOR、CIDEr 等方法改进的主要缺点之一。
  2. 惩罚过短句子:引入“简洁惩罚”(Brevity Penalty, BP),避免模型通过生成极短的句子(如只包含一个正确词)来获得高分。

BLEU的优点是粒度为n-gram,考虑了更长的匹配信息。但其主要缺点是对所有匹配上的n-gram同等对待,没有考虑词性——名词、动词是句子的主要成分,而冠词、介词、连词只起连贯作用,后者的权重本应更低;后续的 METEOR(引入同义词与词干匹配)、CIDEr(TF-IDF 加权)等方法才真正缓解了这个问题。

import numpy as np
from collections import Counter

def simple_bleu(candidate, references, n=4, weights=None):
    """
    一个极度简化的BLEU计算演示,仅用于说明思想。
    实际BLEU计算包含平滑、BP惩罚等复杂处理。
    candidate: 候选句子,字符串,如 "a cat sits on the mat"
    references: 参考句子列表,如 ["a cat is on the mat", "there is a cat on the mat"]
    n: 最高n-gram阶数
    weights: 各阶n-gram的权重,默认等权 (0.25, 0.25, 0.25, 0.25)
    """
    if weights is None:
        weights = [1.0/n] * n

    candidate_tokens = candidate.split()
    refs_tokens = [ref.split() for ref in references]

    # 计算各阶n-gram的修正精确率
    p_n_scores = []
    for i in range(1, n+1):
        candidate_ngrams = list(zip(*[candidate_tokens[j:] for j in range(i)]))
        candidate_counts = Counter(candidate_ngrams)

        # 计算每个n-gram在参考句子中的最大出现次数
        max_ref_counts = Counter()
        for ref_tokens in refs_tokens:
            ref_ngrams = list(zip(*[ref_tokens[j:] for j in range(i)]))
            ref_counts = Counter(ref_ngrams)
            for ngram in candidate_counts:
                max_ref_counts[ngram] = max(max_ref_counts[ngram], ref_counts.get(ngram, 0))

        # 计算匹配次数(修正的计数)
        match_count = 0
        total_count = sum(candidate_counts.values())
        for ngram, count in candidate_counts.items():
            match_count += min(count, max_ref_counts.get(ngram, 0))

        # 避免除零
        precision_i = match_count / total_count if total_count > 0 else 0
        p_n_scores.append(precision_i)

    # 几何平均各阶精确率
    log_bleu = 0
    for w, p in zip(weights, p_n_scores):
        if p > 0:
            log_bleu += w * np.log(p)
    bleu_score = np.exp(log_bleu)

    # 简洁惩罚 (BP)
    c = len(candidate_tokens)
    # 找到最接近候选长度的参考长度
    ref_lens = [len(ref_tokens) for ref_tokens in refs_tokens]
    r = min(ref_lens, key=lambda x: abs(x - c))
    if c > r:
        bp = 1
    else:
        bp = np.exp(1 - r / c) if c > 0 else 0

    final_score = bp * bleu_score
    return final_score, p_n_scores, bp

# 示例
candidate = "the cat is on the mat"
references = ["a cat is on the mat", "there is a cat on the mat"]
score, p_n, bp = simple_bleu(candidate, references, n=2)
print(f"候选句子: {candidate}")
print(f"参考句子: {references}")
print(f"1-gram精确率: {p_n[0]:.4f}")
print(f"2-gram精确率: {p_n[1]:.4f}")
print(f"简洁惩罚(BP): {bp:.4f}")
print(f"简化BLEU分数: {score:.4f}")
候选句子: the cat is on the mat
参考句子: ['a cat is on the mat', 'there is a cat on the mat']
1-gram精确率: 0.8333
2-gram精确率: 0.8000
简洁惩罚(BP): 1.0000
简化BLEU分数: 0.8165

注意1-gram精确率为什么不是1:候选里的“the”出现了两次,而两句参考中各只出现一次,按最大出现次数截断后只能记1次匹配,于是6个unigram命中5个,得0.8333——这正是“交集计数”在起作用。2-gram精确率降到0.8,是因为候选的开头“the cat”在两句参考里都不存在(参考分别是“a cat…”和“…is a cat…”),5个bigram只有4个能对上——阶数越高,越能暴露语序和搭配上的差异,这也是BLEU用高阶n-gram衡量流畅性的原因。

ROUGE:基于召回率的评价指标

ROUGE(Recall-Oriented Understudy for Gisting Evaluation)最初是为自动摘要评估设计的(Gisting即“摘要”),后来与BLEU一样被借用到机器翻译和图像描述任务中。它的设计思路与BLEU非常相似,但核心关注点是召回率(Recall)——名字里的“Recall-Oriented”已经说明了这一点。它计算参考描述中出现的n-gram有多少被候选描述“召回”(即覆盖)。

为什么在神经网络翻译时代更关注召回率?在早期的统计机器翻译(SMT)中,模型生成的句子往往单词是对的,但语序混乱、不通顺。而神经网络机器翻译(NMT)生成能力很强,句子通常很通顺,但有时会“胡编”一些原文没有的词。因此,检查参考描述中的关键信息是否都被模型“说到了”就变得很重要,这正是召回率所衡量的。

ROUGE有几种常见变体:

  • ROUGE-N:计算n-gram的召回率。例如,ROUGE-1就是unigram召回率。
  • ROUGE-L:基于最长公共子序列(LCS)。它不要求匹配的单元连续,更能反映句子的结构相似性。
  • ROUGE-W:对ROUGE-L的改进,为LCS中的连续匹配赋予更高的权重。
  • ROUGE-S:使用skip-gram,允许在匹配时跳过几个词,更能捕捉非连续但语义相关的搭配。
from collections import Counter

def get_ngrams(tokens, n):
    """返回词列表的全部n-gram(以元组表示)。"""
    return [tuple(tokens[i:i + n]) for i in range(len(tokens) - n + 1)]

def ngram_precision(candidate, reference, n=1):
    """n-gram精确率(BLEU侧重点):候选的n-gram有多少被参考覆盖。"""
    cand = Counter(get_ngrams(candidate, n))
    ref = Counter(get_ngrams(reference, n))
    if not cand:
        return 0.0
    match = sum(min(cnt, ref.get(ng, 0)) for ng, cnt in cand.items())
    return match / sum(cand.values())

def rouge_n(candidate, reference, n=1):
    """ROUGE-N召回率:参考的n-gram有多少被候选覆盖。"""
    cand = Counter(get_ngrams(candidate, n))
    ref = Counter(get_ngrams(reference, n))
    if not ref:
        return 0.0
    match = sum(min(cnt, cand.get(ng, 0)) for ng, cnt in ref.items())
    return match / sum(ref.values())

# 示例:同一个较短的候选描述,用精确率与召回率分别看
candidate = ["a", "cat", "sits"]                                  # 候选:只说了一小部分
reference = ["a", "cat", "is", "sitting", "on", "the", "mat"]      # 参考:信息更完整

print(f"候选描述: {candidate}")
print(f"参考描述: {reference}")
for n in (1, 2):
    print(f"{n}-gram 精确率 (BLEU侧重点): {ngram_precision(candidate, reference, n):.4f}")
    print(f"{n}-gram 召回率 (ROUGE侧重点): {rouge_n(candidate, reference, n):.4f}")
候选描述: ['a', 'cat', 'sits']
参考描述: ['a', 'cat', 'is', 'sitting', 'on', 'the', 'mat']
1-gram 精确率 (BLEU侧重点): 0.6667
1-gram 召回率 (ROUGE侧重点): 0.2857
2-gram 精确率 (BLEU侧重点): 0.5000
2-gram 召回率 (ROUGE侧重点): 0.1667

结果很典型:候选只说了“a cat sits”,其中 sits 与参考里的 sitting 无法精确匹配(BLEU/ROUGE 只认字面完全相同的 n-gram),只有 a 和 cat 命中,所以 1-gram 精确率 = 2/3 ≈ 0.6667;参考里的“is”“sitting”“on”“the”“mat”全被漏掉,召回率只有0.2857。这种“词形不同就直接判为不匹配”的漏配,正是后文 METEOR 要用词干匹配解决的问题。阶数升到2-gram后,候选只剩“a cat”这一组能对上,两项分数同时下降——所以精确率回答“说的是不是对的”,召回率回答“该说的是不是都说到了”,两者必须配合看。

METEOR:与人类评价最接近的指标

METEOR(Metric for Evaluation of Translation with Explicit ORdering)旨在与人类主观评价更一致。它在BLEU/ROUGE的基础上做了重要改进:

  1. 同义词和词干匹配:不仅要求完全相同的词匹配,还利用WordNet等词汇知识库,将同义词(如参考写“计算机”、模型写“电脑”)和同一词干的不同词形(如“running”与“run”、“dogs”与“dog”)视为匹配。这解决了“词对但形式不同”被误判的问题。
  2. 综合准确率与召回率:METEOR同时计算unigram级别的准确率(P)和召回率(R),然后计算它们的调和平均数(F值)。这比只关注单一指标更全面。
  3. 惩罚碎片化匹配:引入“chunk”概念。一个chunk是候选描述和参考描述中能够对齐的、且前后顺序一致的连续一段词。METEOR惩罚那些虽然每个词都对上了,但顺序完全打乱、导致chunk很小很碎的情况。例如:
    • 参考:A B C D
    • 候选:B A D C
    • 4个unigram全部匹配,但对齐后只能切成4个长度为1的chunk(每个词各自成段),匹配词数 m=4、chunk数 c=4。按惩罚公式 0.5 × (c/m)³ = 0.5,最终分数只剩 F 值的一半。这鼓励模型生成语序更自然、更流畅的句子。

METEOR的计算公式比BLEU复杂,并且包含一些需要人为设定的参数(例如更看重流畅性还是更看重译文准确性,由人预先规定)。此外它依赖WordNet等外部词汇资源,实现与移植都比BLEU/ROUGE麻烦。

METEOR 评分计算流程(概念性伪代码):
1. 对齐(Alignment):
   - 对候选和参考句子进行词干化。
   - 建立词与词之间的映射关系,优先级:完全匹配 > 词干匹配 > 同义词匹配。
2. 计算基础分数:
   - Precision (P) = 匹配的unigram数 / 候选句子unigram总数
   - Recall (R) = 匹配的unigram数 / 参考句子unigram总数
   - Fmean = (10 * P * R) / (R + 9 * P)  # 一种加权调和平均,更偏重召回率
3. 惩罚碎片化:
   - 将对齐的词划分成尽可能少的连续片段(chunks)。
   - 设chunk数为`c`,匹配词数为`m`。
   - 惩罚因子 Penalty = 0.5 * (c / m)^3  # chunk越多(越碎),惩罚越大
4. 最终分数:
   - METEOR = Fmean * (1 - Penalty)

CIDEr:专为图像描述设计的指标

CIDEr(Consensus-based Image Description Evaluation)是第一个真正为图像描述任务设计的评价指标。它借鉴了信息检索中的TF-IDF和向量空间模型(VSM)思想。

核心思想:将每个句子(描述)表示成一个TF-IDF向量,然后计算候选描述向量与一组参考描述向量之间的余弦相似度。

具体步骤:

  1. 构建词表:使用n-gram(通常n=1到4)作为“词项”(term)。
  2. 计算TF-IDF权重:
    • TF(词频):某个n-gram在当前句子中出现的频率。频率越高,可能越重要。
    • IDF(逆文档频率):log(总图片数 / 包含该n-gram的图片数)。如果一个n-gram在很多图片的描述中都出现(如“a”, “the”, “is”),那么它对区分图片内容的作用就小,IDF值低,权重被抑制。反之,像“skateboard”、“umbrella”这类特定物体相关的n-gram,IDF值高,权重更大。
    • TF-IDF = TF * IDF:这样既考虑了句子内的重要性,又考虑了在整个数据集中区分不同图片内容的能力。
  3. 向量化与打分:将每个句子表示为其所有n-gram的TF-IDF值构成的向量。候选描述的分数是其向量与所有参考描述向量的平均余弦相似度。

CIDEr的动机正是为了解决BLEU的缺点——对不同重要性的词一视同仁。通过TF-IDF,CIDEr能够自动给名词、动词等实义词更高的权重,给停用词很低的权重,从而与人类判断更一致。在 CIDEr 原文(Vedantam et al., CVPR 2015)的对比实验中,CIDEr 与人类判断的相关性优于 METEOR、BLEU、ROUGE(METEOR 次之);后续的 SPICE 在部分语义维度上进一步超过 CIDEr。

import math
from collections import Counter
import numpy as np

def compute_cider_demo(sentences, all_docs_ngrams):
    """
    一个极度简化的CIDEr计算演示,仅用于说明TF-IDF向量和余弦相似度的思想。
    sentences: 当前图片的多个参考描述(列表),以及一个候选描述(放在最后)。
    all_docs_ngrams: 所有图片的n-gram集合列表,用于模拟IDF计算。
    """
    # 1. 为每个句子提取1-gram(真实CIDEr会取1到4-gram,这里只做1-gram演示)
    n = 1
    def extract_ngrams(tokens):
        return [tuple(tokens[i:i + n]) for i in range(len(tokens) - n + 1)]

    all_ngrams_in_this_image = []
    vector_ngrams = []  # 记录每个句子的n-gram列表
    for sent in sentences:
        tokens = sent.split()
        ngrams = extract_ngrams(tokens)
        all_ngrams_in_this_image.extend(ngrams)
        vector_ngrams.append(ngrams)

    # 2. 构建词表(排序保证每次运行顺序一致,输出可复现)
    vocab = sorted(set(all_ngrams_in_this_image))
    vocab_index = {ngram: idx for idx, ngram in enumerate(vocab)}

    # 3. 计算IDF(需要“所有图片”的统计信息,这里用传入的all_docs_ngrams模拟)
    N = len(all_docs_ngrams)  # “总图片数”
    idf = np.zeros(len(vocab))
    for idx, ngram in enumerate(vocab):
        # 统计有多少张“图片”的参考描述里出现过这个ngram
        doc_count = sum(1 for doc_ngrams in all_docs_ngrams if ngram in doc_ngrams)
        # 平滑处理,避免除零
        idf[idx] = math.log((N + 1) / (doc_count + 1)) + 1

    # 4. 计算每个句子的TF-IDF向量
    vecs = []
    for ngrams in vector_ngrams:
        tf = np.zeros(len(vocab))
        counter = Counter(ngrams)
        total_terms = len(ngrams)
        for ngram, count in counter.items():
            tf[vocab_index[ngram]] = count / total_terms if total_terms > 0 else 0
        tfidf = tf * idf
        # L2归一化,方便计算余弦相似度
        norm = np.linalg.norm(tfidf)
        if norm > 0:
            tfidf = tfidf / norm
        vecs.append(tfidf)

    # 5. 计算候选描述与所有参考描述的平均余弦相似度
    cand_vec = vecs[-1]
    ref_vecs = vecs[:-1]
    similarities = [np.dot(cand_vec, ref_vec) for ref_vec in ref_vecs]
    avg_similarity = np.mean(similarities) if similarities else 0

    return avg_similarity, vocab, idf

# ---------- 模拟数据 ----------
# 假设有三张图片,每张图片的参考描述用1-gram集合表示。
all_docs_ngrams = [
    {('a',), ('cat',), ('sits',), ('on',), ('the',), ('mat',)},                      # 图片1
    {('a',), ('dog',), ('runs',), ('in',), ('the',), ('park',)},                     # 图片2
    {('a',), ('bird',), ('flies',), ('in',), ('the',), ('blue',), ('sky',),
     ('is',), ('flying',)},                                                         # 图片3
]

# 当前图片(图片3)的参考描述和候选描述
refs_for_image3 = ["a bird flies in the blue sky", "a blue bird is flying"]
candidate_for_image3 = "a bird in the sky"  # 候选描述,漏了“blue”和“flies”
sentences_to_score = refs_for_image3 + [candidate_for_image3]

# 计算
score, vocab, idf = compute_cider_demo(sentences_to_score, all_docs_ngrams)
print("词表 (vocab):", [ng[0] for ng in vocab])
print("\nIDF 值(值越高,词越‘特别’):")
for ng, val in zip(vocab, idf):
    print(f"  {ng[0]}: {val:.3f}")
print(f"\n候选描述与参考描述的平均余弦相似度 (CIDEr思想): {score:.4f}")
词表 (vocab): ['a', 'bird', 'blue', 'flies', 'flying', 'in', 'is', 'sky', 'the']

IDF 值(值越高,词越‘特别’):
  a: 1.000
  bird: 1.693
  blue: 1.693
  flies: 1.693
  flying: 1.693
  in: 1.288
  is: 1.693
  sky: 1.693
  the: 1.000

候选描述与参考描述的平均余弦相似度 (CIDEr思想): 0.5727

从IDF一栏能直接看出机制:a和the在三张图片的描述里都出现,IDF被压到1.000;介词in出现在两张图片中,IDF为1.288;bird、blue、flies、sky等只出现在图片3,IDF最高(1.693)。候选描述漏掉了参考中的blue和flies——它虽然提到了同为高IDF的bird和sky,却没能说清“蓝色的鸟”,而“蓝色”恰恰是这张图区别于其他图片的关键信息,因此平均余弦相似度只有0.5727。

主观评价指标与常用数据集

除了上述客观的自动化指标,图像描述任务还有重要的主观评价维度,通常由人工进行评判:

  1. 流畅度:生成的描述是否语法正确、读起来自然通顺。
  2. 相关性:描述是否包含了图像中重要的物体、属性、动作和关系,是否与图像内容紧密相关。
  3. 助盲性:对于一个视力障碍者,这段描述能帮助他/她在多大程度上理解图像所传达的基本信息。这是图像描述任务一个非常重要的应用导向的评价标准。

主流数据集: 目前图像描述研究主要集中在英文,常用数据集有:

  • MS COCO:最流行的数据集之一。训练集82783张、验证集40504张(合计约12.3万张,另有测试集40775张),每个划分中每张图片都配有5句独立的人工描述。使用多句描述可以有效避免同义词、语法习惯等差异带来的评价偏差。
  • Flickr30k / Flickr8k:分别约3万张(常用划分28000/1000/1000)和8千张(6000/1000/1000),均从Flickr收集,每张图片同样配有5句描述。

这些数据集为模型训练和性能评估提供了标准化的基础。

📝 动手练一练

  1. 概念辨析:BLEU和ROUGE的核心区别是什么?为什么在神经网络图像描述模型评价中,ROUGE所关注的方面可能同样重要?
👉 点击查看参考答案

核心区别:BLEU基于精确率(Precision),计算的是模型生成的描述中的n-gram有多少出现在参考描述中。ROUGE基于召回率(Recall),计算的是参考描述中的n-gram有多少被模型生成的描述覆盖。

ROUGE的重要性:神经网络模型具有很强的语言生成能力,容易产生流畅但可能包含图像中不存在信息的描述(“幻觉”)。ROUGE关注的召回率能够检查模型是否“遗漏”了参考描述中的关键信息,确保生成的描述对图像内容的覆盖度。因此,结合BLEU(看生成是否准确)和ROUGE(看覆盖是否全面)能更全面地评价模型。

  1. 手动计算:假设参考描述为 ["a cat sits on a mat", "there is a cat on the mat"],候选描述为 "the cat is on the mat"。请手动估算其BLEU-1和ROUGE-1分数(忽略简洁惩罚和复杂平滑),体会计算过程。
👉 点击查看参考答案

步骤1: 分词

  • 候选: ["the", "cat", "is", "on", "the", "mat"]
  • 参考1: ["a", "cat", "sits", "on", "a", "mat"]
  • 参考2: ["there", "is", "a", "cat", "on", "the", "mat"]

步骤2: 计算BLEU-1(精确率)

  • 候选unigram: ["the", "cat", "is", "on", "the", "mat"],共6个(“the”出现两次,按出现次数计入分母)。
  • 对候选中的每个词,先求它在两句参考中的最大出现次数,再与它在候选中的实际次数取较小值(交集计数):
    • "the": 参考1出现0次、参考2出现1次,最大值为1;候选出现2次,匹配 min(2, 1) = 1。
    • "cat": 两句参考各出现1次,最大值为1;候选出现1次,匹配1。
    • "is": 参考2出现1次,匹配1。
    • "on": 两句参考各出现1次,匹配1。
    • "mat": 两句参考各出现1次,匹配1。
  • 总匹配unigram数 = 1+1+1+1+1 = 5。
  • 候选总unigram数 = 6。
  • BLEU-1精确率 = 5 / 6 ≈ 0.8333。

步骤3: 计算ROUGE-1(召回率)

  • ROUGE与BLEU正好镜像:以参考为分母,统计参考中有多少n-gram被候选覆盖(同样按较小出现次数截断)。多句参考时,通常对每句参考分别计算后取最大值。
  • 参考1 ["a", "cat", "sits", "on", "a", "mat"],共6个:cat、on、mat 被覆盖,3 / 6 = 0.5。
  • 参考2 ["there", "is", "a", "cat", "on", "the", "mat"],共7个:is、cat、on、the、mat 被覆盖,5 / 7 ≈ 0.7143。
  • 取最大:ROUGE-1召回率 = 5 / 7 ≈ 0.7143(若改用两句平均则为 (0.5 + 0.7143) / 2 ≈ 0.6071)。

结论:候选描述用词准确(BLEU-1为0.8333),但参考1中的“sits”、参考2中的“there”“a”都没被覆盖,召回率明显更低。这也说明为什么两个方向要一起看。

本章小结

本节课我们深入学习了图像描述(图说)模型的性能评价体系。我们从借用自机器翻译/自动摘要的BLEU和ROUGE指标入手,理解了基于n-gram精确率和召回率的基本评价思想。接着,我们探讨了更精细的METEOR指标,它通过引入同义词匹配和语序连贯性(chunk)惩罚,使得评价结果与人类判断更接近。最后,我们学习了专为图像描述设计的CIDEr指标,它利用TF-IDF加权机制,能够自动区分不同词汇的重要性。

需要给这套指标一个历史定位:BLEU(2002)、ROUGE(2004)、METEOR(2005)和CIDEr(2015)是2015—2019年前后图说论文的标准报告口径,属于那一时期的方法体系。它们共同的局限在于只比较字面n-gram、不理解语义,因此后来出现了SPICE(2016)、BERTScore(2020)、CLIPScore(2021)等语义级/多模态指标,以及今天更常见的人工评审或大模型评审协议。不过BLEU-4、METEOR、CIDEr至今仍是论文中并列报告的经典指标,读懂它们依然是阅读图说文献的基本功。

此外,我们还了解了流畅度、相关性、助盲性等主观评价维度,以及MS COCO等提供多参考描述的数据集如何支持更可靠的评估。

📋 行动清单

  • 理解核心区别:能够清晰说出BLEU、ROUGE、METEOR、CIDEr这四个指标各自的核心设计思想和侧重点。
  • 解读模型论文:在阅读图像描述相关的学术论文时,能够看懂其性能对比表格中各项指标(如BLEU-4, METEOR, CIDEr)的数值含义。
  • 尝试简易实现:根据伪代码和讲解,尝试用Python(不使用NLP库)实现一个非常简化的BLEU或CIDEr计算函数,加深对算法流程的理解。

—— 小象教研组