图像描述中的 Beam Search:为什么搜索策略对生成质量影响这么大

我最早以为 Beam Search 就是个「多加几条候选路径」的批处理技巧:每一步把概率最高的几个词都留着,相当于给解码上一道保险,没什么值得深究的。直到我调自己的图像描述模型,发现一个很邪门的现象——beam size 从 5 加到 20,CIDEr 不但没涨,反而掉了两个多点。

AI technology illustration

搜索范围扩大,结果反而变差?这不合理。我一度怀疑是代码写错了,翻了翻这个领域的研究,才发现 beam search 背后藏着一连串反直觉的坑:长度偏置、概率校准、搜索目标与人类评价的错位。这篇文章把我踩过的坑和想通的道理一次讲清楚。

贪心解码:每一步都对,整句全错

图像描述的标准套路是 encoder-decoder:一张图先被 CNN 编码成特征,再用一个自回归模型一个字一个字往外吐。吐到第 t 步时,模型给词表里每个词一个概率,然后要做一个选择:接下来出哪个词?

最朴素的做法是贪心——每次都选概率最大的那个词。听起来天经地义,但贪心只有一步的远见。假设模型已经生成了「a little girl」,下一步概率最高的是 in(0.4),紧跟着是 playing(0.38)。选 in,句子大概率走向「a little girl in a room」这种平庸描述;选 playing,后面能接 with a dog、on a swing,整句的质感完全不同。贪心在每一步都选当下的最优,可一步选错,整个句子都没法回头。

那能不能把所有句子都搜一遍,再挑最好的?词表一万个词,句子最长 20 个词,候选句子的数量是一万的 20 次方,也就是 1080——和可观测宇宙的原子总数差不多。穷举这条路,从数学上就被堵死了。2015 年 Show, Attend and Tell 把视觉注意力引入图像描述时,用的就是 beam search,从此它成了这个领域的默认配件。

Beam Search 的机制:同时保留 k 个「如果」

beam search 的思路一句话就能说清:每一步不只看最优的那一个候选,而是保留 k 个候选(k 就是 beam size),让它们并行生长,最后从 k 条完整句子里挑得分最高的一条。k=1 时它退化成贪心,k 越大,搜索越接近穷举。

你可能会想:每一步都选概率最大的词,最后整句不就是概率最大的吗?——还真不是。局部最优的叠加不等于全局最优,贪心会错过那些「当前不是最好、但组合起来更好」的路径,而 beam search 恰恰给了这些路径存活的机会。

具体执行过程是这样的:

  1. 第一步,模型对所有词打分,保留 log 概率最高的 k 个词,作为 k 条独立的「故事线」。
  2. 接下来每一步,每条故事线都基于自己的历史,对词表里所有词打分——一共产生 k × V 个新候选。
  3. 把所有新候选按累计 log 概率排序,只保留前 k 个,其余全部剪掉。
  4. 重复直到每条故事线都输出结束符,最后选累计得分最高的一条作为描述。

计算代价很直观:每一步要做 k × V 次打分。k=5、词表一万,就是每一步五万次前向计算,所以 beam search 比贪心慢好几倍。换来的是「后悔药」:某条线早期选错了词,只要整句累计概率足够高,后面仍有翻盘机会。

概率乘积里的长句歧视

这里有一个我当初完全没意识到的坑。一个句子的概率,是所有词的条件概率相乘的结果。每个词的概率都不超过 1,乘得越多,总概率越小。这在数学上意味着:长句天生吃亏

我最早调试的时候发现,beam search 生成的描述总是比贪心解码短一截,而且经常莫名其妙地提前收尾。我一开始以为是模型没学会说长句,后来才想通——不是模型不会说,是搜索目标在惩罚长句。句子的 log 概率是个负数,每多一个词就多负一点,beam search 在拼命最大化这个负分,当然倾向于尽快结束。

解决办法是长度归一化Google 神经机器翻译论文给出的做法是,把累计 log 概率除以一个随长度增长的惩罚项:

长度归一化的公式与直觉

score = log P(Y) / ((5 + |Y|) / 6)^α,其中 |Y| 是句子长度,α 是超参数,经验上取 0.6 到 0.7。分子是累计 log 概率(负数),分母随长度增大,长句被扣掉的分被「补偿」回来。分母里的 5 相当于给句子一个最低长度配额,防止归一化过度鼓励短句。

加了长度归一化之后,beam search 的输出长度才恢复正常。这件事给我的教训是:解码策略从来不是「选词」这么简单,它内嵌了模型对句子长度的先验偏好,不改就会偏。

搜索越彻底,句子越平庸

更诡异的问题出在搜索深度上。Freitag 和 Al-Onaizan 在 WMT 上做的系统实验扫描了 beam size 从 1 到 50 的整个区间,结论是一条倒 U 形曲线:BLEU 先升后降,最优区间大致在 5 到 10,再大就回退。图像描述里的经验值也类似——今天排行榜上的 SOTA 模型,比如 M2 Transformer,推理时用的 beam size 就是 5。

为什么搜索得越彻底,结果反而越差?Yang 等人把这个现象称为「beam search 的诅咒」,并且指出根源在概率校准:模型的条件概率和人类对质量的判断并不一致。用一句话概括他们的实验结论:

beam size 增大时,模型自己给的分数一路走高,而 BLEU 这类外部指标掉头向下——因为模型把很多低质量句子打出了高分。

翻译成图像描述的场景:模型学的是训练集的统计规律,训练集里出现频率最高的描述,往往是「a woman standing on a beach」这种安全但空洞的句子。这类句子在模型眼里概率极高,在人类眼里没有信息量。beam 越大,搜索得越「充分」,反而越容易一头扎进这种平均脸

这也解释了我开头遇到的那个怪现象:把 beam size 从 5 加到 20,模型在它错信的概率空间里搜索得更彻底,自然更坚定地走向平庸。

图像描述为什么还守着 beam search?

你可能要问:beam search 毛病这么多,为什么不换成采样?采样是每一步按概率分布随机抽一个词,而不是选最大的,天然能避开「总是走向平均值」的倾向,生成更丰富的句子。但代价是稳定性——采样可能抽到概率很低、根本不连贯的词,尤其在图像描述这种短句任务里,一个错词就毁掉整句。

Holtzman 等人发现,在开放生成场景里(比如让 GPT-2 续写一篇新闻),beam search 会陷入无限重复的死循环,因为「最可能的词」往往就是刚说过的那几个。但图像描述属于受限生成:输出只有 5 到 20 个词,有图像内容作为事实约束,评价指标(BLEU、CIDEr)也和标准答案做 n-gram 匹配。任务约束越强,取概率最大的词就越安全,beam search 的缺点被压住了。

四类解码策略的取舍,大致是这张表:

解码策略 保留候选 优势 软肋 适合场景
贪心 1 条 最快 一步选错,全局翻车 实时推理、基线
Beam search k 条 稳定、质量高 长度偏置、趋于平均 图像描述、机器翻译
采样 1 条(随机) 多样性好 可能不连贯 开放对话、创意生成
Diverse beam search k 条(去重) 候选差异大 实现复杂、调参多 一次生成多个候选描述

放大器,不是修复器

最后说我的判断。Beam search 是一个放大器:训练目标对,它能把好模型的能力发挥到极致;训练目标有问题,它会把模型的偏见放大给你看。它做的全部事情,是在当前模型的概率分布里找最可能的句子;「模型认为最可能」和「人类觉得最好」之间的裂缝,它补不上。

要补这道缝,只能从训练阶段下手。Self-Critical Sequence Training 用强化学习直接优化 CIDEr,让模型的概率分布向评价指标靠拢;Yang 等人也证明,改成序列级训练目标之后,加大 beam size 才真正变成收益。搜索策略和训练目标必须匹配,这也是为什么「交叉熵模型 + 大 beam」的组合总是不如「RL 模型 + 小 beam」。

我现在的调参习惯是:交叉熵训出来的模型,beam size 给 3 到 5,长度归一化 α 取 0.6 到 0.7,绝不盲目加大;用了 RL 或序列级训练之后,才放心把 beam 加到 10 以上。最后提醒一句:如果 beam search 的输出开始出现重复词,别怀疑 beam size——去检查训练目标,那才是病根。

原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/555.html

(0)
上一篇 2天前
下一篇 2天前

相关推荐