查看全课大纲(第 86 / 93 节)
- 1.计算机视觉概述
- 2.计算机视觉应用场景
- 3.困难与挑战
- 4.开源库介绍
- 5.图像显示与存储
- 6.CLAHE
- 7.腐蚀膨胀与开闭运算
- 8.滤波与边缘填充
- 9.各种滤波
- 10.图像金字塔
- 11.傅里叶变换
- 12.短时傅里叶变换与小波变换
- 13.颜色特征与颜色直方图
- 14.几何特征_边缘
- 15.几何特征-角点与斑点
- 16.局部特征-SIFT特征描述子
- 17.局部特征-SURF特征描述子
- 18.局部特征-ORB特征描述子
- 19.其他特征描述子
- 20.传统图像分割技术
- 21.GraphCut
- 22.GrabCut
- 23.人脸检测的传统方法
- 24.行人检测的传统方法HOG+SVM
- 25.行人检测DPM
- 26.人工神经网络的架构
- 27.目标函数与梯度下降
- 28.误差反向传播
- 29.可手算的神经网络
- 30.改进目标函数与克服梯度消散
- 31.神经网络之传统神经网络与深度网络的差异
- 32.各种梯度下降算法
- 33.如何选择合适的梯度下降算法
- 34.避免过适应
- 35.CNN的架构
- 36.CNN的误差反向传播_卷积层
- 37.CNN的误差反向传播_池化层
- 38.分类所用的数据集
- 39.Alexnet详解
- 40.VGG详解
- 41.GoogLeNet_v1
- 42.BatchNormalization
- 43.GoogLeNet_v3v4
- 44.ResNet
- 45.ResNeXt
- 46.CNN设计准则
- 47.图像检索与推土机距离
- 48.基于颜色相似性
- 49.基于形状相似性
- 50.基于纹理相似性
- 51.基于局部特征相似性
- 52.DL的二值哈希编码
- 53.高维空间中检索KDTree
- 54.高维空间中检索LSH
- 55.目标识别任务综述
- 56.RCNN
- 57.SPP-Net
- 58.Fast R-CNN
- 59.Faster R-CNN
- 60.R-CNN系列模型回顾
- 61.R-FCN的设计思路
- 62.R-FCN的实现
- 63.YOLOv1
- 64.YOLOv2_9000
- 65.YOLOv3
- 66.图像分割应用场景与数据集
- 67.上采样的实现方式
- 68.FCN网络架构的由来
- 69.FCN构建细节
- 70.DeepLabv1
- 71.CRF
- 72.DeepLabv2
- 73.DeepLabv3
- 74.特定的医学影像分割任务
- 75.U-Net
- 76.3D U-Net
- 77.V-Net
- 78.DenseNet
- 79.病理切片分析任务及数据集
- 80.病理切片分析
- 81.图说任务及其传统处理方法
- 82.深度语言模型与RNN
- 83.LSTM及其变种
- 84.NIC模型
- 85.SAT模型
- 86.图说的性能指标
- 87.判别模型与生成模型
- 88.KL散度与JS散度
- 89.VAE
- 90.GAN的基本原理
- 91.DCGAN与CGAN
- 92.Wasserstein GAN
- 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还引入了两项改进:
- 截断计数(clipping):同一 n-gram 的匹配次数取 ,避免候选靠重复某个词刷分。需要说明的是,BLEU 本身不做停用词处理,它对所有 n-gram 等权——这正是它后来被 METEOR、CIDEr 等方法改进的主要缺点之一。
- 惩罚过短句子:引入“简洁惩罚”(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的基础上做了重要改进:
- 同义词和词干匹配:不仅要求完全相同的词匹配,还利用WordNet等词汇知识库,将同义词(如参考写“计算机”、模型写“电脑”)和同一词干的不同词形(如“running”与“run”、“dogs”与“dog”)视为匹配。这解决了“词对但形式不同”被误判的问题。
- 综合准确率与召回率:METEOR同时计算unigram级别的准确率(P)和召回率(R),然后计算它们的调和平均数(F值)。这比只关注单一指标更全面。
- 惩罚碎片化匹配:引入“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向量,然后计算候选描述向量与一组参考描述向量之间的余弦相似度。
具体步骤:
- 构建词表:使用n-gram(通常n=1到4)作为“词项”(term)。
- 计算TF-IDF权重:
- TF(词频):某个n-gram在当前句子中出现的频率。频率越高,可能越重要。
- IDF(逆文档频率):
log(总图片数 / 包含该n-gram的图片数)。如果一个n-gram在很多图片的描述中都出现(如“a”, “the”, “is”),那么它对区分图片内容的作用就小,IDF值低,权重被抑制。反之,像“skateboard”、“umbrella”这类特定物体相关的n-gram,IDF值高,权重更大。 - TF-IDF = TF * IDF:这样既考虑了句子内的重要性,又考虑了在整个数据集中区分不同图片内容的能力。
- 向量化与打分:将每个句子表示为其所有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。
主观评价指标与常用数据集
除了上述客观的自动化指标,图像描述任务还有重要的主观评价维度,通常由人工进行评判:
- 流畅度:生成的描述是否语法正确、读起来自然通顺。
- 相关性:描述是否包含了图像中重要的物体、属性、动作和关系,是否与图像内容紧密相关。
- 助盲性:对于一个视力障碍者,这段描述能帮助他/她在多大程度上理解图像所传达的基本信息。这是图像描述任务一个非常重要的应用导向的评价标准。
主流数据集: 目前图像描述研究主要集中在英文,常用数据集有:
- MS COCO:最流行的数据集之一。训练集82783张、验证集40504张(合计约12.3万张,另有测试集40775张),每个划分中每张图片都配有5句独立的人工描述。使用多句描述可以有效避免同义词、语法习惯等差异带来的评价偏差。
- Flickr30k / Flickr8k:分别约3万张(常用划分28000/1000/1000)和8千张(6000/1000/1000),均从Flickr收集,每张图片同样配有5句描述。
这些数据集为模型训练和性能评估提供了标准化的基础。
📝 动手练一练
- 概念辨析:BLEU和ROUGE的核心区别是什么?为什么在神经网络图像描述模型评价中,ROUGE所关注的方面可能同样重要?
👉 点击查看参考答案
核心区别:BLEU基于精确率(Precision),计算的是模型生成的描述中的n-gram有多少出现在参考描述中。ROUGE基于召回率(Recall),计算的是参考描述中的n-gram有多少被模型生成的描述覆盖。
ROUGE的重要性:神经网络模型具有很强的语言生成能力,容易产生流畅但可能包含图像中不存在信息的描述(“幻觉”)。ROUGE关注的召回率能够检查模型是否“遗漏”了参考描述中的关键信息,确保生成的描述对图像内容的覆盖度。因此,结合BLEU(看生成是否准确)和ROUGE(看覆盖是否全面)能更全面地评价模型。
- 手动计算:假设参考描述为
["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计算函数,加深对算法流程的理解。
—— 小象教研组