资讯动态

PyTorch图像描述实战:从CNN编码器到LSTM解码器的完整指南

发布时间:2026/10/20 17:26:48 来源:尧图企业网站定制
我刚开始接触图像描述Image Captioning这个方向时觉得它特别神奇——分类网络告诉你是“猫”检测网络告诉你“猫在窗台上”而 Caption 模型要自己组织语言输出一句完整的、像人话的句子“一只橘猫趴在窗台上盯着窗外树上的鸟。”这已经不是单纯识别视觉内容的问题了它横跨计算机视觉和自然语言处理两个领域模型不仅要看懂图片还要学会把看到的场景按语法规则讲出来。这篇文章就结合我用 PyTorch 实现的一个完整项目把从数据准备、模型搭建到训练推理、踩坑调优的整个链路过一遍适合已经会跑分类任务、想往多模态方向进阶的读者参考。1. 先把问题说清楚看图讲故事本质上是个条件生成任务1.1 从“一个标签”到“一句话”的距离图像分类是这样一个过程输入一张图输出一个概率分布取最大概率对应的类别标签整个过程本质上是一个离散的映射。但描述一张图的时候输出不再是固定集合里的某个元素而是一串长度可变的单词序列。同一个场景可以有无数种表达方式“一个女孩在公园遛狗”“在公园里一个女孩正牵着一只狗散步”“穿红衣服的女孩和她的狗在草地上”。这些句子语法不同、长度不同、措辞不同但语义上都对。这就是图像描述任务和分类任务最本质的区别分类是判别式任务模型只要学会“区分”就够了描述是生成式任务模型必须学会“组织语言”。一个合格的 Caption 模型要面对双重挑战——视觉上它得知道图上有什么、物体之间是什么关系语言上它得知道一个合乎语法的句子该如何开始、如何推进、如何结束。也就是说模型内部要同时学到一个“视觉概念库”和一个“语言模型”还要找到两者之间的对齐方式。所以业界的主流做法不是试图训练一个单一大杂烩网络直接端到端地完成所有事而是把问题拆成两个明确阶段先由一个“视觉编码器”把图片变成紧凑的特征向量再交给一个“语言解码器”逐词生成句子。这个思路从早期经典论文开始就被反复验证到现在依然是绝大多数 Caption 系统的骨架。1.2 拆解主流方案CNN编码器负责提取图像特征LSTM解码器负责逐词输出编码器负责把图片降维、提炼成语义向量。具体做法很朴素拿一个在ImageNet上预训练好的残差网络ResNet去掉最后用于分类的全连接层让网络输出一个比较抽象的特征表示。这个特征不光包含“有什么物体”还隐含着物体的空间关系、场景氛围等高层信息。为了把任意尺寸的图像统一起来在最后一层卷积之后接一个自适应平均池化最终得到一个固定长度的向量比如 2048 维。解码器这边用的是带记忆能力的循环神经网络最经典的就是 LSTM。它的输入是单词输出也是“下一个单词的概率分布”。整个生成过程可以这样理解编码器给了 LSTM 一个“视觉记忆起点”LSTM 拿到这个起点后先根据当前已经生成的单词预测下一个词每一步都把自己的内部状态更新一下相当于在脑子里不断刷新“已经说了什么、接下来该说什么”的草稿。这个过程会一直持续到模型输出句子结束的特殊标记为止。这两个模块拼接在一起后整个模型要学习的参数主要是两部分词嵌入矩阵以及 LSTM 内部和输出映射层的参数。预训练好的 CNN 编码器大多数情况下直接冻结或者只用很小的学习率微调。至于为什么要这么做后面第三章会详细说。1.3 用数学语言描述条件语言模型的最大化对数似然如果用一句话概括整个任务那就是给定图片 I生成一个单词序列 y (y1, y2, ..., yT)使得条件概率 p(y1, y2, ..., yT | I) 尽可能大。这个联合概率可以按链式法则拆解p(y1,...,yT | I) p(y1 | I) · p(y2 | y1, I) · p(y3 | y1, y2, I) · ... · p(yT | y1,...,y(T-1), I)也就是说模型在每个时间步要做的事其实就是在给定图片和前面所有已生成单词的条件下预测下一个单词的条件概率。训练时我们会把整个训练集的平均负对数似然作为损失函数让模型学会最大化所有正确句子的概率。这个表达式看上去简单但它深刻影响了后面的所有工程决策为什么用 LSTM 而不是前馈网络、为什么训练时要用 Teacher Forcing、为什么推理时还需要 Beam Search 来搜索更优序列——全都是围绕着这个条件概率分解展开的。2. 数据准备这是一切效果的隐形天花板2.1 数据集怎么选训练集和验证集怎么切图像描述任务最常用的公开数据集有 Flickr8k、Flickr30k 和 COCO 这类大规模数据集。Flickr8k 一共有大约 8000 张图片每张图配 5 句人工标注的描述数据量适中一张普通显卡就能在可接受的时间内完成训练非常适合作为项目起步的选择。Flickr30k 有 3 万多张图规模更大但训练时间也成倍增加。COCO 更大单张图片的标注质量也更好适合追求效果上限的进阶实验。数据划分有讲究。官方一般会给出标准划分比如 Flickr8k 常见的做法是 6000 张训练、1000 张验证、1000 张测试。千万不要自己用随机抽样来切因为同一个场景的多张相似图片可能同时出现在训练集和测试集里导致评估结果虚高。图像描述领域的论文里经常强调“测试集图片与训练集图片没有语义重叠”这一点随机切分很难保证这一点。如果你的数据是本地文件夹加标注文件的形式通常需要写一个解析脚本。标注文件的格式一般是“图片名 - 图片名 - 编号 描述语句”的结构。解析出来的最终产物建议统一整理成字典结构键是图片文件名值是对应的所有描述句子列表。2.2 图片预处理从原始像素到网络输入图片这块的预处理和图像分类任务基本一致核心逻辑是让输入分布尽量接近预训练网络见过的分布。以 ResNet 系列为例标准流程是先等比缩放让短边至少达到 256 像素然后随机裁剪出 224×224 的区域作为训练样本。随机裁剪可以起到数据增强的作用让模型对物体的位置和尺度不那么敏感。裁剪之后进行水平随机翻转也能提高鲁棒性。最后要做的是标准化也就是每个通道减去均值、除以标准差。ImageNet 预训练模型使用的均值是 [0.485, 0.456, 0.406]标准差是 [0.229, 0.224, 0.225]这三个数在各类预训练模型的配置里都能直接找到属于固定经验值。验证和测试阶段则不同不再随机裁剪而是先等比缩放到短边 256再直接中心裁剪 224×224保证评估结果的确定性。用 PyTorch 的 torchvision.transforms 可以很轻松地把这些操作串联起来。2.3 词表构建与特殊标记 、 、 、 缺一不可文本处理是整个项目中看似简单、实际决定上限的环节。首先要做的是对全部标注句子做分词然后统计词频设置最小词频阈值来过滤掉那些只出现一两次的生僻词。阈值一般取 3 到 5这样得到的词表大小通常在几千到一万左右既不会太大导致模型难以学习也不会太小导致太多单词被替换成未知标记。构建词表时四个特殊标记必不可少pad句子的 padding 标记用于 batch 内对齐长度start句子的开始标记告诉解码器“准备发第一个词”end句子的结束标记模型输出它即表示句子生成完毕类似句号的作用unk未知词标记词表外的词统一映射到这里每个训练句子在送入模型前需要做一次“加头去尾”的处理把start插在句子开头把end加在句子末尾。训练时LSTM 看到的是“以,start开头、以最后一个真实单词结尾”的输入序列但预测目标是“从第一个真实单词开始、以end结尾”的下一个词序列。理解这个错位关系很重要它保证了模型见到的每一个输入 token都有对应的预测目标。最后把所有句子按长度降序排列并组成 batch用pad补齐到相同长度再通过转置得到按时间步组织的输入张量。这些预处理逻辑写起来不难但每一步都直接影响训练是否能够正常收敛。3. 网络结构搭建编码器、解码器与各种维度的取舍3.1 编码器冻结预训练 CNN 不是玄学是工程决策编码器部分我直接用了在 ImageNet 上预训练好的 ResNet-152。去掉最后的全连接分类层后再接一个自适应平均池化让任何尺寸的输入图片都输出 2048 维的特征向量。为什么选 152 层这么深的网络而不是更轻的 ResNet-18因为编码器的质量直接决定了解码器拿到的视觉信息有多丰富。越深的网络学到的特征层次越深对训练 caption 模型的帮助越明显。代价是多一次前向传播的耗时但图片编码只需要在训练过程中计算一次之后可以保存到本地文件中反复使用所以这个成本完全可以接受。要不要微调编码器是一个值得思考的决策。一开始我也试过对 ResNet 的所有参数都做反向传播结果显存占用飙升训练速度明显变慢而且验证集效果并没有显著提升。深层 CNN 在大量数据上已经学到了非常通用的视觉特征你的 caption 数据集通常只有几千张图微调很容易破坏这些通用特征导致过拟合。所以我的做法是冻结 ResNet 的全部参数只把图片过一遍编码器生成特征向量并缓存下来。训练时解码器直接从缓存中读取特征不再触碰卷积层。这样既节省了显存又天然避免了任务数据量太小导致视觉特征被破坏的问题。如果你用的是带有 Batch Normalization 的模型还需要注意一个细节BatchNorm 层在冻结后必须设置为 eval 模式否则它会继续更新 running mean 和 running variance影响特征分布的稳定性。3.2 解码器LSTM 是怎么把视觉特征翻译成句子的解码器的输入是词向量序列输出是每一步对词表中所有单词的概率分布。整体结构并不复杂核心组件包括一个词嵌入层、一个 LSTM 层和一个输出映射层。词嵌入层负责把离散的单词索引映射为密集向量维度通常取 256 或 512。映射后的向量和图片特征如何融合是解码器设计的关键点常见方案有两种。第一种是把图片特征作为 LSTM 的初始隐状态输入第二种是在每个时间步把图片特征和当前词的嵌入向量拼接后再喂给 LSTM。我采用的是第二种方案将经过可学习的线性映射压缩后的图片特征复制一份并与每个时间步的词嵌入拼接。这样做的好处是模型在每个时间步都能重新“看到”图片信息而不只是在句首看一眼。生成“窗帘是什么颜色的”这类细节描述时模型需要在不同的时间步反复参考图像的特定区域每步都输入图片特征可以显著降低视觉信息被遗忘的风险。在具体维度选择上我踩过一个不小的坑LSTM 的隐层维度过小会让模型“记不住”已经生成的内容导致句子前后逻辑混乱维度过大又容易过拟合。一个比较稳妥的组合是词嵌入 256 维、LSTM 隐层 512 维、LSTM 层数 1 层。单层 LSTM 在这个任务上的表现已经足够好堆多层 LSTM 会明显增加过拟合风险效果提升却微乎其微。3.3 一张表说清我的超参数配置下面的表格是我在项目中实际使用的核心配置可以给刚开始搭建模型的你做一个参考。当然这些参数不是标准答案但它们是经过多轮实验验证的、比较稳的起点。组件配置项数值/策略备注编码器骨干网络ResNet-152去掉全连接层冻结参数编码输出特征池化AdaptiveAvgPool (1x1)输出 2048 维向量图像特征映射线性层2048 → 512降低维度后与词嵌入拼接词嵌入嵌入维度256随机初始化解码器LSTM 结构单层隐层 512batch_firstTrue输出层映射维度512 → 词表大小共享权重方案可尝试优化器类型Adamlr4e-4betas(0.9, 0.999)梯度策略梯度裁剪clip0.5防止 LSTM 训练中出现梯度爆炸批大小单卡可承受上限128视显存调整数据按句子长度排序减少 padding学习率策略调度ReduceLROnPlateau连续 3 轮验证指标不升则衰减 0.5训练轮数最大 epoch30配合早停通常 15-20 轮开始收敛关于嵌入层维度为什么要跟 LSTM 隐层维度区分开这里补充一点嵌入维度太小会导致模型无法区分近义词太大则会让整个模型的参数量膨胀。256 维在几千到一万规模的词表上已经能容纳足够的语义信息而 LSTM 隐层需要更宽一些是因为它要同时承担“语言建模”和“视觉信息对齐”两个任务属于计算瓶颈所在。4. 训练策略Teacher Forcing、损失函数与那些让 loss 正常下降的细节4.1 Teacher Forcing 和它为什么重要训练序列生成模型时最自然的想法是让模型自己生成句子、然后和真实句子对比、调整参数。但这样做的代价很大——模型在刚开始训练时生成的内容完全是随机噪音如果把这些噪音当作下一步的输入模型会越学越偏收敛极慢。所以训练阶段普遍采用 Teacher Forcing 策略无论模型上一步输出了什么我们都强制把真实句子中的下一个词作为它下一步的输入。通俗讲就是在每个时间步给模型“透题”让它始终基于正确的上下文来预测下一个词。这样一来训练变得更加稳定模型只需要专注学习每个单独时间步的映射关系。代价是训练和推理之间存在一定的不一致推理时模型面对的是自己生成的、可能包含错误的内容。这就像学骑自行车训练时有人扶着车把推理时突然松手一开始肯定歪歪扭扭。缓解这个问题的手段是用计划采样训练后期以一定概率让模型把“自己上一步的输出”作为这一步的输入而不是总用真实值。我的经验是前 10 轮不要启用等 loss 降得差不多再逐渐提高采样概率否则分布抖动太剧烈不容易收敛。4.2 训练循环的核心逻辑损失计算与梯度裁剪训练循环本身不复杂但有几个细节决定成败。先说损失函数直接用交叉熵但要记得把 padding 位置忽略掉。PyTorch 的 CrossEntropyLoss 自带 ignore_index 参数传入pad的索引即可这是最容易遗忘的一步——如果忘记关掉 padding模型会花大量精力去学习预测那些“不是单词的占位符”损失永远降不到正常水平。再说输入和目标的构建数据装载器返回的是句子张量 caplens其中每个真实单词之后跟了大量pad。训练的时候我们要把解码器每一步的输入设为除最后一个 token 外的所有 token预测目标设为除第一个 token 外的所有 token。下面是一段关键逻辑的伪代码展示了训练循环里怎么组织数据# 假设 batch 内句子张量形状: (batch_size, max_len) # 输入去掉最后一列 - (batch_size, max_len - 1) # 目标去掉第一列 - (batch_size, max_len - 1) captions_in captions[:, :-1] # 以 start 开头 targets captions[:, 1:] # 以 end 结尾 outputs decoder(features, captions_in) loss criterion(outputs.reshape(-1, vocab_size), targets.reshape(-1))解码器内部需要自己管理 LSTM 的初始状态。常见的做法是把编码器输出的图像特征过一层线性变换生成 LSTM 的初始隐状态和记忆单元状态。这里要注意初始状态必须包含两个——hidden state 和 cell state不能只传一个。遗忘初始 cell state 等于让 LSTM 从完全空白开始模型很难学会稳定的长期依赖。最后Python 里做反向传播前必须有一个梯度裁剪步骤torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm0.5)。LSTM 对这种长序列任务特别容易出现梯度爆炸表现为某个 batch 算完 loss 后直接成了 NaN。加了裁剪之后这个问题基本能被彻底压制。4.3 从 loss 曲线判断训练状态是否正常训练过程中最影响心情的就是 loss 曲线不加分析地乱跳。这里给你我调试时总结的几个判断方法。第一看起始值。如果初始 loss 明显比 log(词表大小) 小很多说明词表里各词的概率分布不均匀或者数据加载顺序有问题。正常的初始 loss 应该接近均匀分布的熵在词表 5000 左右时大概是 8.5 左右。如果从一开始就低得离谱八成是 loss 计算时把 padding 也算进去了或者目标张量没对齐。第二看下降速度。若前 5 轮 loss 降幅很小我首先会检查数据装载器有没有 bug比如句子标签和图片错位。图像描述任务里最常见的数据 bug 就是字典键值没对齐模型乱学一气。先打印几个 batch 的样本确认图片文件名和句子内容能对上再去怀疑网络结构。第三看验证指标。loss 下降不代表一切正常因为生成任务存在“loss 很低但生成内容完全跑题”的情况。我在训练中会每隔一个 epoch 做一次 beam search 解码随机挑 5 张验证集图片看一眼输出句子这个习惯比任何指标都直观。宁可多花几分钟做可视化检查也别等到训练结束才发现模型学会了“万能句式”来敷衍所有图片。5. 推理与评估Beam Search 和 BLEU 背后的真相5.1 贪心解码和 Beam Search 的取舍训练完成后进入推理阶段最朴素的解码方式是贪心每个时间步取概率最高的词直接作为下一步输入直到输出end或达到最大长度。这种方式的优点是快、简单缺点也显而易见局部最优不等于全局最优。语言里有很强的搭配关系比如“a flock of birds”是常见表达贪心生成可能在“a”之后选择了概率最高的“cat”导致后续整个句子越走越偏。Beam Search 的思路是保留多个候选序列。以 beam size 3 为例初始时在第一个时间步选出概率最高的 3 个词组成 3 条候选接下来每一步每条候选都要预测下一个词的概率分布于是得到 3×词表大小 个候选再从中挑出总概率最高的 3 条如此不断扩展和裁剪直到所有候选都生成end或达到长度上限。实现 Beam Search 时最需要注意的是防止出现重复句子。同一个end可能让多条候选同时终止如果直接把这些候选都移出待处理队列容易出现“多条候选句子其实只有句首不同”的情况。另一个实用技巧是长度惩罚长句子的联合概率天然低于短句子如果不做任何修正模型会倾向于输出异常短的句子。常见的做法是在累加 log 概率时除以一个长度惩罚项我的经验是惩罚系数取 0.7 左右比较稳定句子不会过短也不会过度冗长。Beam size 不是越大越好。我把 beam size 从 1 调到 3 再调到 5 对比过beam3 相对 greedy 解码能带来明显的 BLEU 提升beam5 的提升就非常有限了但推理耗时翻了一倍不止。实际使用时建议先用 beam3 快速验证确定模型效果达标后再提升到 5。5.2 BLEU 指标怎么算以及它的盲区图像描述模型效果好不好行业内用得最广泛的自动评估指标是 BLEU。它的思路是计算模型生成的句子和人工标注句子之间的 n-gram 重合度同时加上一个长度惩罚因子。n 可以取 1 到 4分别对应单个词、双词、三词和四词片段的匹配率。BLEU-1 衡量的是词汇选得对不对BLEU-4 衡量的是语序和结构是否接近人工描述。用 Python 计算时可以直接借助nltk.translate.bleu_score。这里有一个常见的坑如果你直接只传一个参考句子进去nltk 会因为句子过短报出警告甚至返回 0。正确的做法是把同一张图片的 5 句人工描述全部作为参考句子再用 SmoothingFunction 方法做平滑处理。这样得到的分数才比较接近论文中报告的数值范围。但我要提醒你BLEU 对“语义正确但表达不同”的句子非常不友好。比如模型生成“a dog is playing in the grass”而参考句子写的是“a puppy runs on the lawn”词面重合度不高BLEU 就给了低分但这句话实际上描述的是同一件事。所以 BLEU 只能作为参考指标绝不能当作唯一的目标函数来反向优化模型。我自己评估模型时会额外人工检查几十张图并统计生成句子里有没有常见的语义错误比如把“猫”说成“狗”。自动指标只能筛掉明显不合格的模型真正的效果判断还是得靠“肉眼观察 分类统计”。5.3 注意力可视化让“看图讲故事”真正有据可查如果只是做“图像特征向量进、句子出”模型相当于闭着眼睛写作文——它“看”过图片但不清楚它写某个单词时到底在关注图片的哪个区域。为了让结果更有说服力也为了排查模型是不是在瞎编我给解码器加了一个软注意力模块在 LSTM 的每个时间步根据当前状态计算特征图上每个位置的权重并用加权后的特征参与本步的单词预测。训练时这个注意力模块参与反向传播。推理时我会把每个时间步的注意力权重保存下来对应到原始图片的坐标上用热力图叠加展示。这样就能直观地看到模型说“猫”的时候注意力热力图集中在图片里猫所在的位置说“窗台”的时候注意力转移到窗台区域。注意力图还能帮我发现模型的毛病——有一次模型在说“water”时注意力落在了一只狗的耳朵上仔细检查后发现训练集里“水”相关描述的图片恰好有不少小狗出镜属于数据集本身存在统计偏差。注意力机制的实现不复杂本质是“图片特征矩阵上的加权求和”。每个位置的权重是当前 LSTM 隐藏状态与该位置特征向量的点积经过 softmax 得到的结果。下面给出一个简化版本# features: (batch, num_boxes, feature_dim) # hidden: (batch, hidden_dim) attention_scores torch.tanh(fc_att(features) fc_hidden(hidden).unsqueeze(1)) alpha torch.softmax(attention_scores, dim1) context torch.sum(alpha * features, dim1)实际上做的时候要特别注意广播维度的对齐fc_hidden(hidden).unsqueeze(1)很容易漏掉这个 unsqueeze。如果漏了广播机制不会报错但计算结果会错得非常隐蔽。6. 我实际踩过的坑从 泛滥到重复词再到训练中断6.1 一张故障排查表覆盖 90% 的起步问题项目进行到后期我把自己和朋友在实际操作里遇到过的问题整理成了一张排查表每次出问题先对照这张表过一遍能省下大量调试时间。现象根本原因解决办法loss 初始值远低于预期目标张量没有对齐如把输入当目标或 padding 参与了 loss 计算检查 captions 切片逻辑确认 ignore_index 设置训练过程中 loss 突然变成 NaN梯度爆炸LSTM 长序列误差累积加梯度裁剪降低学习率生成的句子出现大量unk词频阈值过低、生僻词太多或词表构建时未保留unk标记提高词频阈值到 3-5确保unk索引正确生成的句子很短且全是通用套路训练数据不足或模型容量不够模型学会了“安全句式”增大 beam size尝试引入注意力机制不同图片生成几乎完全相同的句子解码器忽略图像特征特征融合方式有问题改成每个时间步都输入图像特征或增加注意力模块验证集 BLEU 高但实际效果差BLEU 对同义表达不敏感或数据划分存在同场景泄漏人工检查输出重新核验数据划分逻辑显存不足批大小太大或编码器未冻结冻结编码器并缓存图像特征降低批大小6.2 过拟合与早停小数据集的生存之道Flickr8k 这类数据集只有几千张图即便每张图有 5 句描述模型需要学习的“图片-句子”对应关系也远远不够。所以过拟合几乎是必然面临的课题。一个明显的信号是训练 loss 持续下降但验证集的 BLEU 或人工检查结果在某轮之后开始停滞甚至变差。我总结了一套应对办法。第一是词表尽量精简词频阈值不要太低把那些只出现一两次的罕见词直接降级为unk减少模型记忆负担。第二是 dropout 要舍得加词嵌入层和 LSTM 输出层各加一个 0.5 dropout效果立竿见影。第三是早停保存验证集上表现最好的模型权重而不是训练结束时那份。关于 checkpoints 还有一个小建议除了保存模型参数务必把 optimizer 的 state_dict 和词表 dict 也一并保存。否则模型训练中断后接着跑时优化器的动量信息丢失学习率可能回到初始状态后续训练表现会很奇怪。幸好项目后期我才学会把词表信息存进 checkpoint改起来非常麻烦。6.3 重复词循环的问题与破解模型生成“a cat a cat”这样的重复内容是训练不充分的典型信号。根本原因是 LSTM 在生成序列时当前时间步的预测只依赖隐状态一旦模型进入了某个“模式”很难单靠隐状态自己走出来就容易在原地打转。想要真正杜绝重复光靠等模型自己学好是不够的。第一种可用的缓解方法是训练阶段引入“scheduled sampling”的平滑版——计划采样第二种更实用是在推理阶段对已经出现过的 n-gram 做一个惩罚。具体做法是生成候选词时如果这个词会导致某个 2-gram 或 3-gram 已经出现过就给对应候选的分数打一个折扣。这个技巧实现起来非常简单但对输出质量的提升特别明显生成句子的可读性会立刻提高一个档次。这类问题的根治方法是从模型结构上升级比如引入自注意力机制让模型生成每一步时能回顾已经生成的上下文而不只是靠一个固定长度的隐向量“硬记”。不过如果你只是想把基础版项目跑通先做解码惩罚就够了不要一上来就去改模型结构。写在最后几个我从这个项目里带走的经验做完这个项目我的一个很深的体会是图像描述任务里数据整理和词表构建占据的精力比模型结构本身多得多。一次偶然的标签错位或者一个没设置对的 ignore_index都可能浪费你两三天的时间去排查。我的习惯是每写完一个数据处理的组件立刻打印几条实际样本人眼检查等整个 pipeline 跑通后再回头看模型结构。另外编码器冻结加特征缓存的策略对起步实验有非常大的加速作用。整个训练过程里图像特征完全不需要重复计算GPU 资源全部集中到解码器上batch size 可以开得很大训练速度肉眼可见地提升。等基础版本验证通过后再做注意力、做编码器微调按需逐步加复杂度。如果你也想动手实现一个看看效果建议先用最小的公开数据集跑通整个流程用贪心解码输出几个样本确认训练没有异常再逐步加入 Beam Search、注意力可视化和评估指标。后面的每一步都能看到明确的变化这是这个项目最有意思的地方。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑