想象你在逛一场画展,墙上挂着一幅画:阳光斜斜洒落,一棵大树下趴着一只小狗。旁边有位讲解员,只看了一眼就脱口而出:“太阳照着树下的小狗。”你或许觉得这稀松平常——但请细想,这位讲解员其实完成了一件极其复杂的事:他用眼睛看清画面,用注意力锁定重点,在脑子里组织出一句通顺的话,还悄悄比较了“树下的小狗”“小狗在晒太阳”等多种说法,最终挑了最恰当的一句讲给你听。 “让 AI 把图片翻译成文字”,就是训练这样一位不知疲倦的“画展讲解员”。它需要一双能读懂图像的眼睛(视觉编码器),一张能组织语言的嘴(文本解码器),还要有目光聚焦的本事(注意力机制)、在心里预演多种说辞的功夫(束搜索),以及被游客打分后不断改进的自觉(评估指标)。听起来很神奇?其实每一步都可以拆解成普通人能懂的小机关。

岗位关联

图生文是跨模态生成的核心技能,掌握它,你就能参与无障碍辅助、智能文案、内容创作等真实产品的研发——这是当前 AI 落地最旺盛的人才缺口之一。

目录
  1. 可视化演示
  2. 任务全景:讲解员到底在做什么
  3. 视觉编码器:讲解员的眼睛
  4. 文本解码器:讲解员的嘴
  5. 注意力机制:讲解员的目光
  6. 束搜索解码:在心里预演多套说辞
  7. 质量控制:让讲解员不翻车
  8. 评估指标:游客手里的打分卡
  9. 部署优化:从展览馆走向千家万户
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

动态演示图生文的核心机制,通过基础/核心/应用/扩展四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

图生文:图生文任 图生文任务概述与生成形式 编码器解码器生成架构 核心机制可视化 图生文整体架构与关键组件

任务全景:讲解员到底在做什么

画展讲解员的工作,表面是“看图说话”,内里却是一道翻译题:把一种语言(图像像素)翻译成另一种语言(自然语言文字)。先给你一张图片 \(x\),要求输出一段描述文字 \(y\),比如“太阳照着树下的小狗”。这段文字里,既有物体(太阳、树、小狗),也有关系(照着)、位置(树下)——这正是图生文和“图像分类”“目标检测”最本质的区别:分类只回答“这是什么”,而图生文要回答“发生了什么”。

从数学上看,模型在估计一个条件概率:给定图片 \(x\),最可能的句子 \(y\) 是什么。由于句子是一个词一个词吐出来的,这个概率被拆成一连串“下一步说什么”的乘积。

图生文的魅力正在于此:它把“看懂一幅画”这个庞然大物,拆解成了“一次只看一个词”的连续决策——每一步都不难,连起来却创造了惊人的智能表现。接下来的几节,我们逐一拆解这位讲解员的眼、嘴、心、脑。

p(y∣x)=∏t=1Tp(yt∣y<t,x)\displaystyle p(y \mid x) = \prod_{t=1}^{T} p(y_t \mid y_{<t}, x)
就像讲解员每说完一个词,都要根据“已经说的话+眼前的画”决定下一个词,把所有步骤的概率乘起来,就得到整句话的把握程度。
  1. 条件概率 \(p(y \mid x)\)在已知图片 \(x\) 的条件下,句子 \(y\) 出现的可能性。条件符号 \(\mid\) 读作“在……下”。
    p(y∣x)p(y \mid x)
  2. 句子 \(y\) 拆成词序列\(y = y_1, y_2, \dots, y_T\),每个 \(y_t\) 是第 \(t\) 个词,\(T\) 是句子长度。
    y=(y1,y2,…,yT)y = (y_1, y_2, \dots, y_T)
  3. 历史条件 \(y_{<t}\)表示第 \(t\) 个词之前已经生成的词。生成靠的是“已有词+图片”,而不是“未来词”。
    y<t=(y1,…,yt−1)y_{<t} = (y_1, \dots, y_{t-1})
  4. 连乘符号 \(\prod\)把从 \(t=1\) 到 \(T\) 的每个词概率相乘,合成整句概率。
    ∏t=1Tp(yt∣y<t,x)\prod_{t=1}^{T} p(y_t \mid y_{<t}, x)

视觉编码器:讲解员的眼睛

讲解员的眼睛不是普通的眼睛,而是一台精密的“浓缩器”。一幅画可能有几百万个像素,但讲解员真正需要的是:哪里有什么,长什么样。视觉编码器就是干这个的——它把原始图像 \(I\) 变成一组紧凑的特征序列 \(V\),每个特征向量浓缩了画面某个位置/区域的信息。

传统做法用卷积神经网络(CNN)先提取整图的特征图,再把特征图划分成网格,逐格取出特征向量;进阶做法则先用目标检测器框出“可疑区域”(比如一只狗、一棵树),再对每个区域提取特征。无论哪种,最后都得到一张“特征表”:\(L\) 个位置,每个位置用 \(d\) 维向量描述。

有了这沓“便签”,讲解员就不再对着原始像素发愁了。下一节看它如何把这些便签“说”成人话。

V=CNN(I)∈RL×d\displaystyle V = \text{CNN}(I) \in \mathbb{R}^{L \times d}
可以理解为:讲解员把画纸打上格子,对每个格子写了张“便签”——内容、颜色、形状都浓缩成几个数字。整幅画最后变成 \(L\) 张便签,叠成一沓。
  1. 输入图像 \(I\)一张原始图片,通常表示为宽 × 高 × 三通道(RGB)的数值矩阵。
    I∈RH×W×3I \in \mathbb{R}^{H \times W \times 3}
  2. CNN 特征提取卷积神经网络逐层扫描图像,从边缘、纹理一直学到物体级别的语义,输出特征图。
    CNN(I)\text{CNN}(I)
  3. 输出特征序列 \(V\)特征图被切分为 \(L\) 个空间位置/区域,每个位置对应一个 \(d\) 维特征向量。
    V=[v1,v2,…,vL],vi∈RdV = [v_1, v_2, \dots, v_L], \quad v_i \in \mathbb{R}^{d}
  4. 形状标记 \(\mathbb{R}^{L \times d}\)\(L\) 代表位置数,\(d\) 代表每个位置的向量维度,整体是一张 \(L\) 行 \(d\) 列的表。
    V∈RL×dV \in \mathbb{R}^{L \times d}

文本解码器:讲解员的嘴

有了眼睛,还得有嘴。文本解码器的任务,是逐个词地把特征“翻译”成句子。它像一个特别健谈的讲解员:每说一个词,就回头看看“已经说过的词”和“手里的画面便签”,决定下一个词说什么。

具体实现中,常用循环神经网络(LSTM)维护一个“瞬时记忆” \(h_t\)——记住说到哪了。在每一步 \(t\),解码器把上一词的嵌入和由注意力得到的上下文向量拼在一起,更新记忆,然后用一个线性层把记忆映射成词表大小的分数向量,最后经过 softmax 变成每个词的“被选中概率”。

注意,训练时常用 Teacher Forcing:不管模型上一句说得多离谱,都拿真实词喂给下一步。这就像讲解员排练时,哪怕说错了也照剧本继续练,而不是当场罚站——这样学习效率高得多。

p(yt∣y<t,V)=softmax(Woht+bo)\displaystyle p(y_t \mid y_{<t}, V) = \text{softmax}(W_o h_t + b_o)
相当于讲解员每说完一个词,心里就有一排“候选词”在同时举手,哪个词得分最高,哪个就被说出口。
  1. 隐状态 \(h_t\)解码器在第 \(t\) 步的“瞬时记忆”,浓缩了已生成词和视觉信息。
    ht=LSTM(ht−1,[ct−1,e(yt−1)])h_t = \text{LSTM}(h_{t-1}, [c_{t-1}, e(y_{t-1})])
  2. 线性映射 \(W_o h_t + b_o\)把隐状态向量乘上权重矩阵 \(W_o\) 并加偏置 \(b_o\),得到长度等于词表大小 \(|\mathcal{V}|\) 的分数向量。
    zt=Woht+bo∈R∣V∣z_t = W_o h_t + b_o \in \mathbb{R}^{|\mathcal{V}|}
  3. softmax 归一化把分数向量变成和为 1 的概率分布,第 \(i\) 个词的概率正比于 \(\exp(z_{t,i})\)。
    softmax(zt)i=ezt,i∑j=1∣V∣ezt,j\text{softmax}(z_t)_i = \frac{e^{z_{t,i}}}{\sum_{j=1}^{|\mathcal{V}|} e^{z_{t,j}}}
  4. 采样或取 argmax训练时按此分布采样,推断时通常取概率最大的词,或交给束搜索全局挑选。
    yt=arg⁡max⁡ipiy_t = \arg\max_i p_i

注意力机制:讲解员的目光

如果讲解员每说一个词就“平等地看整幅画”,那就成了背书机器。真正的讲解员会聚焦:说“太阳”时盯着太阳,说“树下”时盯着树根。注意力机制(Attention)就是给模型装上这双会聚焦的眼睛。

每一步 \(t\),模型给特征序列的每个位置 \(i\) 打一个“相关度分” \(e_{ti}\),再用 softmax 变成权重 \(\alpha_{ti}\),最后按权重把特征加权求和,得到“当前最该看的内容” \(c_t\)。

注意力不仅提升了生成质量,还带来了一个副产品——可视化解释。你可以把每步的 \(\alpha_{ti}\) 画成热力图,直观看到模型说每个词时在看哪里。但注意,这只能说明“它看了这里”,不能证明“它是因为看了这里才这么说”——可解释性工具不等于因果证据。

αti=exp⁡(eti)∑j=1Lexp⁡(etj),ct=∑i=1Lαtivi\displaystyle \alpha_{ti} = \frac{\exp(e_{ti})}{\sum_{j=1}^{L} \exp(e_{tj})}, \quad c_t = \sum_{i=1}^{L} \alpha_{ti} v_i
讲解员心里有个“聚光灯”:目光扫过每个便签,越相关的越亮,最后所有便签按亮度混合成一幅“重点画面”。
  1. 相关度打分 \(e_{ti}\)用一个小网络或点积计算“当前想说的词”和“第 \(i\) 个区域特征”的匹配程度。
    eti=v⊤tanh⁡(Wahi+Uast−1)e_{ti} = v^{\top} \tanh(W_a h_i + U_a s_{t-1})
  2. 权重归一化 \(\alpha_{ti}\)对同一时刻的所有位置做 softmax,让权重和为 1,代表“目光分配比例”。
    αti=exp⁡(eti)∑j=1Lexp⁡(etj)\alpha_{ti} = \frac{\exp(e_{ti})}{\sum_{j=1}^{L} \exp(e_{tj})}
  3. 上下文向量 \(c_t\)把全部区域特征按权重加权求和,得到这一步的“聚焦结果”。
    ct=∑i=1Lαtivic_t = \sum_{i=1}^{L} \alpha_{ti} v_i
  4. 隐状态更新注意力上下文 \(c_t\) 会拼进解码器的输入,指导下一步选词。
    st=LSTM(st−1,[ct,e(yt−1)])s_t = \text{LSTM}(s_{t-1}, [c_t, e(y_{t-1})])

束搜索解码:在心里预演多套说辞

解说员有职业病:讲一句话之前,总要在脑中快速预演几套说辞。“太阳照着树下的小狗”好,还是“小狗在树下晒太阳”更自然?贪心做法是每步只选当前最顺口的词——但这样容易“走一步算一步”,可能在第三步就走进死胡同。束搜索(Beam Search)则聪明得多:它维持一个“候选清单”,每一步都同时扩展多条路径,最终挑选整体得分最高的句子。

在长度为 \(L\) 的候选句上,模型给每条候选打总分:词的 log 概率逐项相加,再用长度归一化消除“短句天然分高”的偏差。

束搜索是“讲解员”们的看家本领,但它不是银弹:K 过大会让模型更倾向流畅却可能重复的句子,K=1 又退化成贪心。真实项目中 K 常在 3~5 之间,配合下一节的质量控制手段一起使用。

score(y)=1Lϵ∑t=1Tlog⁡p(yt∣y<t,x)\displaystyle \text{score}(y) = \frac{1}{L^{\epsilon}} \sum_{t=1}^{T} \log p(y_t \mid y_{<t}, x)
这就像讲解员把三套说辞同时写在草稿纸上,每说一个词就同步更新三张草稿,最后选读起来最顺、意思最准的那一版。
  1. 每条候选的得分\(y\) 是一条完整的候选句子,得分由各词的对数概率累加得到。
    ∑t=1Tlog⁡p(yt∣y<t,x)\sum_{t=1}^{T} \log p(y_t \mid y_{<t}, x)
  2. 长度惩罚 \(L^{\epsilon}\)\(L\) 是句子长度,\(\epsilon\) 是惩罚系数(通常 0.6~1.0)。长度越长,分母越大,避免模型偏向输出过短句子。
    1Lϵ\frac{1}{L^{\epsilon}}
  3. 归一化后的得分用长度惩罚后的分数进行比较,选分数最高者作为最终输出。
    y^=arg⁡max⁡yscore(y)\hat{y} = \arg\max_{y} \text{score}(y)
  4. 束宽 \(K\)每一步保留 K 条最优候选,K 越大搜索越充分但计算量也越大。
    beams(t)=Top-K(beams(t−1)×V)\text{beams}^{(t)} = \text{Top-}K\left(\text{beams}^{(t-1)} \times \mathcal{V}\right)

质量控制:让讲解员不翻车

再好的讲解员也有嘴瓢的时候:把同一句话重复三遍、越说越啰嗦、或者蹦出不合适的词。生成质量控制就是一套“应急预案”,常见手段有三个:重复惩罚(凡说过的高频词,下次打分时打折)、长度控制(通过长度归一化调整长短句偏好,或用“不结束惩罚”防止太早收尾)、温度采样(调整选择词的“冒险程度”)。

温度采样是控制生成风格的关键旋钮。原始分数 \(z_i\) 先除以温度 \(T\) 再 softmax:

有了这套“嘴瓢急救包”,讲解员就能在“流利”和“忠实”之间找到平衡。实际产品中,一般先按温度和惩罚系数生成多条候选,再根据评估指标挑最好的——这就到了打分环节。

pi=exp⁡(zi/T)∑j=1Vexp⁡(zj/T)\displaystyle p_i = \frac{\exp(z_i / T)}{\sum_{j=1}^{V} \exp(z_j / T)}
温度就像讲解员的心情:\(T\) 调小,他变得保守,只敢说最有把握的词;\(T\) 调大,他变得大胆,偶尔蹦出让游客惊喜的冷门词。
  1. 原始分数 \(z_i\)解码器给词表第 \(i\) 个词的未归一化 logit,可以取正取负。
    zi∈Rz_i \in \mathbb{R}
  2. 温度缩放 \(z_i / T\)\(T\) 是温度参数。当 \(T > 1\),分数被压平,分布更均匀;当 \(T < 1\),分数被放大,分布更尖锐。
    ziT\frac{z_i}{T}
  3. softmax 归一化缩放后的分数经指数运算后归一成概率,总和为 1。
    pi=exp⁡(zi/T)∑j=1Vexp⁡(zj/T)p_i = \frac{\exp(z_i / T)}{\sum_{j=1}^{V} \exp(z_j / T)}
  4. 极端情况\(T \to 0\) 时概率趋于 argmax(接近贪心);\(T \to \infty\) 时趋于均匀分布(完全随机)。
    lim⁡T→0pi=1[i=arg⁡max⁡jzj]\lim_{T \to 0} p_i = \mathbb{1}[i = \arg\max_j z_j]

评估指标:游客手里的打分卡

讲解员讲得好不好,不能自己说了算,得看游客打分。图生文领域也有一套“游客评分卡”,最经典的是 BLEU:把模型生成的句子和人工写的参考句子做 n-gram(连续 n 个词)重合度比较。

BLEU 简单好用,但只看字面重合,不关心语义。于是有了 ROUGE(侧重召回,看参考句里的词有没有漏掉)、CIDEr(对词做 TF-IDF 加权,稀有词更关键)、SPICE(把句子解析成语义图再比对,更接近“理解”)。真实评测中,工程师通常同时看 2~3 个指标——就像评分不仅要看用词,还要看流畅度、信息量、画面还原度。

BLEU=BP×exp⁡(∑n=1Nwnlog⁡pn)\displaystyle \text{BLEU} = \text{BP} \times \exp\left(\sum_{n=1}^{N} w_n \log p_n\right)
就像评分员拿着参考讲解稿,数着“你和我稿子里连续两个字、三个字相同的比例”,再打个折——句子越短越要打折,防止偷工减料。
  1. n-gram 精确率 \(p_n\)n 取 1~4,分别计算生成句和参考句中 n 连词的重合比例。
    pn=∑c∈cands∑ngram∈cCountclip(ngram)∑c∈cands∑ngram∈cCount(ngram)p_n = \frac{\sum_{c \in \text{cands}} \sum_{\text{ngram} \in c} \text{Count}_\text{clip}(\text{ngram})}{\sum_{c \in \text{cands}} \sum_{\text{ngram} \in c} \text{Count}(\text{ngram})}
  2. 取对数并加权对每个 \(p_n\) 取对数,再按权重 \(w_n\)(通常各 0.25)求和。
    ∑n=1Nwnlog⁡pn\sum_{n=1}^{N} w_n \log p_n
  3. 指数还原外层 \(\exp\) 把对数分数映射回 0~1 区间。
    exp⁡(⋅)\exp(\cdot)
  4. 长度惩罚 BP若生成句比参考句短,BP < 1,对分数进行折扣。
    BP=min⁡(1,e1−r/c)\text{BP} = \min\left(1, e^{1 - r/c}\right)

部署优化:从展览馆走向千家万户

讲解员培训好了,下一步是让它到处巡展——手机端、网页端、甚至离线设备。部署优化要解决三个问题:模型太大(装不进手机)、生成太慢(用户等不了)、数据敏感(图片不想上传云端)。常用对策包括模型量化、键值缓存和端侧部署。

量化是压缩利器:把 32 位浮点权重变成 8 位整数,内存直接降到 1/4,推理还能加速。公式上,每个权重 \(\theta\) 先乘缩放因子 \(s\) 再四舍五入:

除量化外,工程上还会缓存解码时算过的 Key/Value 向量,避免每生成一个词就重算前面所有词;如果场景允许,优先用贪心或小束宽换取低延迟。这样,那位才华横溢的“讲解员”才能真正活跃在每个人的手机里。

θq=round(θ⋅s)s,s=127max⁡∣θ∣\displaystyle \theta_q = \frac{\text{round}(\theta \cdot s)}{s}, \quad s = \frac{127}{\max |\theta|}
相当于把讲解员的“精细笔记”改用简笔符号记录——大部分信息还在,本子却薄了四分之三。
  1. 缩放因子 \(s\)由权重最大值决定,把权重范围映射到 8 位整数范围(-127~127)。
    s=127max⁡∣θ∣s = \frac{127}{\max |\theta|}
  2. 缩放并取整\(\theta \cdot s\) 放大后四舍五入,模拟“丢掉小数精度”。
    round(θ⋅s)\text{round}(\theta \cdot s)
  3. 还原 \(\theta_q\)除以 \(s\) 回到原尺度,此时数值已带量化误差。
    θq=round(θ⋅s)s\theta_q = \frac{\text{round}(\theta \cdot s)}{s}
  4. 误差来源误差约为 \(\pm \frac{1}{2s}\),权重最大值越大,相对误差越小。
    ∣θq−θ∣≤12s|\theta_q - \theta| \leq \frac{1}{2s}

AI 应用场景

无障碍辅助:帮视障用户“看见”世界

阶段:整体推断链路(编码器 → 注意力 → 解码器 → 质量控制)

解决的问题:视障人士无法“看”图片,传统读屏软件只能朗读文件名或 alt 文本,信息大量缺失。图生文模型可以实时将相机拍摄的画面(比如面前的障碍物、朋友发来的照片)自动转成语音描述,让视障用户“听懂”世界。

具体案例:某无障碍 App 内置压缩版图生文模型,用户举起手机拍下前方场景,1 秒内生成“前方两米处有个消防栓,旁边停着自行车”,再由 TTS 朗读。模型经过 INT8 量化后单帧推理仅需 300ms,可完全在端侧运行,保护用户隐私。

电商文案自动生成:一张商品图秒出详情页

阶段:质量控制和采样策略(温度/重复惩罚 + 多候选评估)

解决的问题:电商运营为几十上百个商品写标题和卖点描述,耗时且重复。图生文能把商品主图直接翻译成“米白色简约陶瓷马克杯,带木质杯盖,适合办公室使用”这类文案。

具体案例:某跨境电商 SaaS 平台接入图生文接口,商家上传商品图后,系统生成 5 条候选文案,用 CIDEr 与历史爆款文案做相似度排序,自动挑出最优 3 条供运营微调,文案产出时间从 30 分钟压缩到 10 秒。

社交媒体内容创作:随手拍即刻配文

阶段:束搜索解码 + 温度采样组合

解决的问题:用户发朋友圈/小红书时头疼“配什么文字”。图生文模型可生成多个风格的描述,配合可调温度让文案在“稳妥达意”和“活泼有趣”之间切换。

具体案例:某内容社区 App 的“智能配文”功能,默认温度 \(T=0.8\) 生成通顺描述,用户拉高滑块到 \(T=1.2\) 即可获得“今天的天空是橘子汽水味的”这类创意文案,日调用量超百万次。

Python 演示

python66 行
"""图生文简化演示:用 Beam Search 从模拟词表生成图像描述"""import math  class BeamSearchDecoder:    """模拟图生文模型的束搜索解码器(真实模型用 CNN+LSTM,此处聚焦解码逻辑)"""     def __init__(self, beam_size=3, max_len=8):        self.beam_size = beam_size        self.max_len = max_len        # 模拟的小词表:0=结束符 1=开始符        self.vocab = {0: '<eos>', 1: '<bos>', 2: '太阳', 3: '照着',                      4: '树下', 5: '小狗'}        # 理想句子的 token 顺序,用于模拟训练好的解码器打分        self.ideal = [2, 3, 4, 5, 0]     def predict_logits(self, prefix):        """模拟解码器输出的 logits:下一理想词给高分,接近结尾时鼓励结束"""        logits = {token: -0.5 for token in self.vocab}        if len(prefix) < len(self.ideal):            ideal_next = self.ideal[len(prefix)]            logits[ideal_next] = 3.0            if prefix and prefix[-1] == self.ideal[-2]:                logits[0] = 2.5  # 已经说了"小狗",鼓励输出结束符        return logits     def step(self, prefix, score):        """扩展当前前缀:计算每个候选词的分数"""        if prefix[-1] == 0:            return [(prefix, score)]  # 已完成,不再扩展        logits = self.predict_logits(prefix)        total = sum(math.exp(v) for v in logits.values())        results = []        for token, value in logits.items():            prob = math.exp(value) / total            if token == 0 and len(prefix) < 2:                continue  # 太短的句子不允许结束            results.append((prefix + [token], score + math.log(prob)))        return results     def decode(self):        """束搜索主循环:每步只保留 K 条最优候选"""        beams = [([1], 0.0)]  # 以 <bos> 开始        for _ in range(self.max_len):            all_cands = []            for prefix, score in beams:                all_cands.extend(self.step(prefix, score))            all_cands.sort(key=lambda x: x[1], reverse=True)            beams = all_cands[: self.beam_size]            if all(p[-1] == 0 for p, _ in beams):                break        best = max(beams, key=lambda x: x[1])[0]        words = [self.vocab[t] for t in best if t not in (0, 1)]        return ' '.join(words)  def main():    print('== 图生文 Beam Search 演示 ==')    for k in (1, 3, 5):        decoder = BeamSearchDecoder(beam_size=k)        result = decoder.decode()        print(f'beam_size={k} -> {result}')  if __name__ == '__main__':    main()
目的:用一个极简模拟词表演示图生文推理阶段最核心的束搜索解码逻辑——如何维护 K 条候选并找出整体最优句子,对比不同束宽对结果的影响。
  1. self.beam_size = beam_size相当于讲解员同时预演几套说辞,K 越大考虑越周全但更耗时。
  2. self.vocab = {0: '<eos>', 1: '<bos>', ...}词表包含特殊符(结束/开始)和四个正常词,模拟真实词表的缩影。
  3. logits[ideal_next] = 3.0模拟训练好的解码器“知道”下一个最该说哪个词,给它更高的原始分。
  4. prob = math.exp(value) / total把原始 logit 经过 softmax 变成概率,是解码器输出的标准形式。
  5. if token == 0 and len(prefix) < 2: continue防止模型说出“太阳<结束>”这种过短句子,对应质量控制中的长度约束。
  6. all_cands.sort(key=lambda x: x[1], reverse=True)按句子得分从高到低排序,让好候选浮上来。
  7. beams = all_cands[: self.beam_size]只保留前 K 条,是束搜索与穷举的核心区别。
  8. if all(p[-1] == 0 for p, _ in beams)当所有候选都以结束符结尾时,提前停止生成。

常见误区

误区图生文不就是目标检测加标签拼接吗?识出“太阳”“树”“小狗”,然后拼成一句话“太阳、树、小狗”就算完成。

正解真正的图生文要生成语法正确、语义连贯的句子,包含物体间的空间关系、行为动作甚至情感氛围。“太阳照着树下的小狗”和“太阳、树、小狗”的信息量天差地别。模型需要学会“照着”“树下”这种关系词,这要求解码器不仅看到物体,还要理解它们的互动。

为何常见:因为“图像描述”这个名字容易让人联想到“看图识字”,而且早期简单模型确实长这样。看到任务名就望文生义,没深入理解其生成性质。

误区把注意力热力图当作模型的“内心想法”,权重高的区域就是模型“理解”最透彻的地方。

正解注意力权重只是模型在计算时分配给各位置的数学权重,可以被多种因素激活;它适合做调试和可视化工具,但不是严格的因果解释。说“模型看这里所以这么说”需要额外的因果实验来证明,不能仅凭热力图断言。就像讲解员目光扫过一幅画,不代表他内心就“懂”了这幅画。

为何常见:人类天然喜欢用“注意力”这个拟人词,热力图又直观得像“视线追踪”,很容易激起过度解读。

误区模型生成的句子 BLEU 越高,说明它越懂图、说得越好,完全可以用 BLEU 作为上线标准。

正解BLEU 只衡量生成句与参考句的 n-gram 字面重合度,如果模型用完全不同的词表达了同样意思(“小狗打盹” vs “小狗睡觉”),BLEU 会打低分;反之,字面像但语义错的句子可能拿高分。生产环境通常要 BLEU、CIDEr、人工评估三者结合,才能覆盖流畅度、信息量、忠实度多个维度。

为何常见:BLEU 实现简单、数值直观,很多教程拿它当唯一指标,初学者容易把“指标”当成“目标”。

误区束搜索的 K 值调得越大,候选空间越全,句子质量一定越高,所以上线就把 K 设成 20。

正解K 过大时,模型容易选出“全局流畅但偏离图片内容”的句子,且计算量线性增长、延迟变高。实际工程中 K 通常在 3~5,配合长度惩罚和重复惩罚使用。增大 K 只在 K 较小时收益明显,超过某个阈值后不仅边际收益递减,还可能因过度追求语言流畅而牺牲视觉忠实度。

为何常见:“搜索越广越聪明”的直觉很符合常理,但忽略了生成任务中“过拟合语言先验”的风险——这也再次提醒我们,语言模型不是搜索引擎。

面试题

Q1. 图生文(Image Captioning)的核心目标是什么?

单选题 · easy

  • A.根据文本生成对应图片
  • B.输入图片输出描述文字← 正确答案
  • C.识别图片上的所有物体
  • D.对图片做分类和检索

答案:B。图生文是跨模态生成任务,输入图像、输出自然语言描述。识别物体(C)和目标检测类似,分类/检索(D)也是判别式任务,都不产生“句子”。A 是文生图方向,方向刚好相反。

Q2. 视觉编码器把图像转换成什么送给解码器?

单选题 · easy

  • A.原始像素点的复制
  • B.浓缩后的特征序列← 正确答案
  • C.压缩后的图片文件
  • D.图中物体的位置框

答案:B。编码器(如 CNN)把图像编码成一批特征向量组成的序列 \(V \in \mathbb{R}^{L \times d}\),保留语义、丢弃冗余像素。A 是原始输入而非编码结果;C 是图片压缩而非语义特征;D 只是检测框,缺少外观和语义信息。

Q3. 解码器生成“树下”这个词时,主要输入是什么?

单选题 · mid

  • A.只有上一个词“照着”
  • B.只有整张原始图片
  • C.上词与注意力上下文← 正确答案
  • D.训练集中的全部句子

答案:C。解码器每一步输入 = 上一词的嵌入 + 注意力加权得到的上下文向量 \(c_t\)。A 少了视觉上下文;B 多了冗余像素;D 是训练数据而非推理输入。只有 C 同时包含语言历史与视觉信息。

Q4. 关于注意力机制,以下说法正确的是?

多选题 · mid

  • A.用打分函数衡量相关度← 正确答案
  • B.权重需要 softmax 归一← 正确答案
  • C.权重高就代表真正理解
  • D.对特征做加权求和平稳← 正确答案

答案:ABD。注意力先打分 \(e_{ti}\) 再 softmax 归一得 \(\alpha_{ti}\)(A、B 对),最后加权求和得上下文 \(c_t\)(D 对)。C 是常见误区:注意力只是权重分配,不等同于模型的因果理解,热力图不能作为“理解”的铁证。

Q5. 贪心解码的主要问题是什么?

单选题 · mid

  • A.局部最优非全局最优← 正确答案
  • B.每一步都费时费力
  • C.无法在 GPU 上运行
  • D.依赖大量人工标注

答案:A。贪心每步只选概率最大的词,可能到第三步才发现整句不通,但已无法回头。束搜索通过维护多条候选缓解这个问题。B、C、D 都不是贪心解码的固有缺陷,贪心反而快且简单。

Q6. beam size K=3 的含义是什么?

单选题 · mid

  • A.最多生成三个句子
  • B.每步保留三条最优候← 正确答案
  • C.词表大小被限制为三
  • D.需要三张测试图片

答案:B。束搜索每步从全部候选扩展中保留分数最高的 K 条路径,K=3 就是始终维护 3 条候选句子。A 是最终输出数量(通常只输出 1 条);C 混淆了词表与束宽;D 与解码过程无关。

Q7. 温度参数 T 调大(如从 0.7 调到 1.3),生成结果会怎样?

单选题 · mid

  • A.更保守,只选最稳词
  • B.更随机,富有多样性← 正确答案
  • C.产生大量重复词句
  • D.直接停止生成句子

答案:B。温度缩放 \(z_i/T\) 在 T 增大时把 logits 压平,softmax 后分布更均匀,低概率词也有机会被选中,多样性上升。T 变小才更保守(A 反了);重复问题主要由重复惩罚处理,C 不一定发生;D 无依据。

Q8. 注意力打分公式 \(e_{ti} = v^{\top}\tanh(W_a h_i + U_a s_{t-1})\) 中,\(v^{\top}\) 的作用是什么?

单选题 · extreme

  • A.映射成标量相关分数← 正确答案
  • B.对图像区域做卷积
  • C.替代 softmax 的归一化
  • D.直接把两个向量拼接

答案:A。\(\tanh\) 输出的是向量,\(v^{\top}\)(转置权重向量)把它点成一个标量分数 \(e_{ti}\),再进入 softmax 归一化。B 是编码器操作;C 错,softmax 归一化仍然需要;D 是拼接操作,不是打分网络的最终输出。

Q9. 图生文模型部署优化中,哪些做法合理?

多选题 · hard

  • A.量化压缩模型内存← 正确答案
  • B.缓存键值加速生成← 正确答案
  • C.全部改用贪心解码
  • D.端侧部署保护隐私← 正确答案

答案:ABD。INT8 量化可把内存降到 1/4(A 对);缓存已算过的 K/V 向量避免重复计算(B 对);端侧推理图片不出设备,隐私更好(D 对)。C 太绝对:贪心能降延迟但牺牲质量,通常只在延迟极敏感且质量可接受时使用。

Q10. 生成质量控制中,下列哪些属于常用手段?

多选题 · hard

  • A.重复惩罚避免复读← 正确答案
  • B.温度采样调节多样性← 正确答案
  • C.长度归一平衡长短句← 正确答案
  • D.把 beam size 设成无限大

答案:ABC。重复惩罚对已生成词的历史分数打折(A 对);温度 T 控制概率分布的尖锐/平坦(B 对);长度归一化 \(1/L^\epsilon\) 让长短句可公平比较(C 对)。D 不可行:beam size 无限大等于穷举,词表指数级组合,计算上完全不可行。