深度学习基础
深度学习基础
深度学习是 2012 年之后 AI 全面爆发的那次「技术跃迁」:图像识别超过人类、语音助手进入手机、AlphaGo 击败李世石,直到今天的大模型,底层的核心引擎都是深度学习。讲清深度学习是什么、神经网络怎么构成、怎么训练、CNN/RNN/GNN 等经典架构各解决什么问题,并用 Encoder-Decoder 解释变长序列如何训练与推理,为下一站 Transformer 架构 与 大模型基础 铺路。机器学习的基础概念(损失函数、过拟合、评估)见 机器学习基础,通用的训练、调试、部署与 MLOps 见深度学习工程实践。
什么是深度学习
深度学习(Deep Learning)是机器学习的一个分支,用「多层的神经网络」自动从数据中学习特征表示。「深」指的是网络层数多:从几层到上百层,数据在层与层之间逐级加工,越深的层学到越抽象的特征。
表示学习:从手工特征到自动特征
传统机器学习(见 机器学习基础)有一个绕不开的瓶颈:特征要靠人手工设计。识别一张猫的图片,人要告诉模型「耳朵尖、有胡须、脸圆」:这需要大量领域专家时间,而且很多特征人类自己也说不清(怎么用手工特征描述「这首歌伤感」?)。
深度学习把特征设计也变成了学习的一部分:输入层吃原始数据(像素、音频波形、文本 token),第一层学到边缘和色块,第二层组合出纹理与形状,再往上组合出眼睛、耳朵,最终层组合出「猫」这个完整概念:每一层自动从前一层的输出里提炼更抽象的特征,这就是表示学习。
| 维度 | 传统机器学习 | 深度学习 |
|---|---|---|
| 特征 | 人工设计(耗时、依赖专家) | 网络自动学习(端到端) |
| 数据需求 | 万级以下就能干活 | 越大越好,小数据容易过拟合 |
| 算力需求 | CPU 即可 | 依赖 GPU/TPU 并行计算 |
| 可解释性 | 好(规则、权重可读) | 差(黑盒,解释要靠事后归因) |
| 适用数据 | 表格、结构化数据 | 图像、语音、文本等非结构化数据 |
| 性能天花板 | 受特征质量限制 | 随数据量与模型规模提升 |
为什么 2012 年后爆发:数据 + 算力
神经网络的思想 1940 年代就有了,多层结构 1980 年代也有了,为什么 2012 年才起飞?因为深度学习的两个「燃料」直到那时才配齐:
- 数据:互联网沉淀出海量可用的数据(ImageNet 千万级标注图片、全网文本语料),深度学习是数据越多越强的模型:喂不饱,它就发挥不出优势。
- 算力:GPU 的并行计算让矩阵运算快了几个数量级。2012 年 AlexNet 在 ImageNet 竞赛上把错误率从 26% 打到 15%,靠的就是两块 GPU 训练出的深度卷积网络。这个事件被普遍视为深度学习时代的奇点时刻。
之后的路径清晰可辨:2014 年 VGG/GoogLeNet 加深网络,2015 年 ResNet 解决深网络难训练问题,2017 年 Transformer 登场,2018 年 BERT/GPT 开启预训练大模型时代,2022 年 ChatGPT 把这一切变成大众产品。这条路的每一步,都是更大的数据 + 更大的模型 + 更强的算力的循环。
端到端学习:一条流水线 vs 一段段拼装
传统方法做语音识别,是「声学模型 → 语言模型 → 词典」多段流水线,每一段单独训练、误差在段间累积。端到端学习让一个神经网络直接吃「音频波形 → 输出文字」,中间的特征、对齐、语言规律全部由网络自己学。省去大量领域工程的代价是:需要海量配对数据和大量算力,且中间过程不可观测、难调试。
产品经理的取舍:端到端上限高但难控(错了不知道错在哪段),分段模型每段可解释、可替换但误差累积。工程上常用折中:先分段做,再在数据足够后逐步端到端化:这也是语音助手、机器翻译产业演进的真实路径。
深度学习的核心假设:分层特征有效
深度学习赌的是一个关于世界的假设:复杂概念可以由简单概念分层组合而成:图像由边缘组合成纹理、纹理组合成部件、部件组合成物体;语言由字母组合成词、词组合成短语、短语组合成句子。如果这个假设成立(事实证明它在视觉与语言上都成立),分层堆叠就是参数效率最高的表达方式:每一层都复用前一层学到的零件。
局限与挑战:大力并非万能
深度学习的短板,产品经理要心里有数:
- 数据饥渴:性能与数据量强相关,小数据场景表现平平,数据质量差时「垃圾进、垃圾出」会被放大。
- 黑盒难解释:决策过程不可直接读,监管、审计、用户信任都需要额外成本(见文末「可解释性现状」)。
- 分布漂移敏感:训练分布与线上分布不一致时性能跳水;对抗样本(肉眼无差别的微小扰动)可以轻易骗过模型。
- 算力与环境成本:训练与推理都耗能,端侧部署要专门做压缩(量化、蒸馏)。
- 缺乏常识与因果:模型学的是相关性,不是因果:换一个它没见过的组合方式就可能犯低级错误。
这些局限是深度学习 vs 传统 ML vs 大模型选型的底层依据,完整对比见 机器学习基础 与 模型能力与边界。
产品经理视角:为什么「大力出奇迹」只在深度学习成立
传统 ML 的性能随数据增长先升后平(特征到头了),深度学习的性能在数据量足够后继续随数据与参数同步增长:这就是「Scaling Law」的雏形,也是行业敢持续烧钱堆数据堆算力的底气。
前提是:数据要够多。小数据场景深度学习反而打不过传统 ML,取舍见文末「产品视角」。
神经网络的基本构成
神经元:线性变换 + 激活
神经网络的最小单元是人工神经元,它做两件事:
- 线性变换:把输入 x 与权重 w 加权求和,再加一个偏置 b:z = w₁x₁ + w₂x₂ + … + b。
- 非线性激活:把 z 过一个非线性函数 f,输出 a = f(z)。
没有第 2 步,多层线性变换叠起来还是线性(一堆直线拼不出曲线),网络再深也表达不了复杂关系:激活函数是神经网络变弯的来源。多个神经元并排组成一层,层与层之间全连接(每个输入连到每个神经元),就是全连接网络;多层堆叠就是多层感知机(MLP)。
flowchart LR
input["原始输入<br/>像素 / 音频 / token"] --> layer1["隐藏层 1<br/>线性变换 + 激活"]
layer1 --> layer2["隐藏层 2<br/>组合更抽象特征"]
layer2 --> head["输出层<br/>类别概率 / 回归值"]
head --> loss["损失函数"]
loss -.梯度回传.-> layer2
layer2 -.梯度回传.-> layer1核心关系:隐藏层把原始输入逐层变成抽象表示,输出层产生任务结果,损失再沿计算图反向提供更新方向。
层、权重与偏置
- 层(Layer):一组并行的神经元。输入层吃数据,隐藏层逐级加工,输出层给结果(分类任务输出层是各类别概率)。
- 权重(Weight):每条连接的重要性,训练要学的核心参数。
- 偏置(Bias):每个神经元的自带底数,让激活可以在输入全 0 时也产生输出。
一个直觉:权重决定重视哪些输入,偏置决定什么条件下才激活。参数量 = 上一层神经元数 × 本层神经元数 + 本层偏置数:全连接层参数随层宽平方级增长,这是后来 CNN 用局部连接省参数的动机。
通用近似定理与参数初始化
- 通用近似定理:只要神经元够多、激活函数非线性,单隐藏层网络就能以任意精度逼近任何连续函数。听起来「一层就够了」?实际不行:单层需要指数级多的神经元,而深层的网络能用少得多的参数表达同样函数。深度的价值是参数效率,不是表达能力的有无。
- 参数初始化:训练开始时权重不能全为 0(所有神经元对称,梯度一样,永远学不出差异),也不能太大(一开始就梯度爆炸)。主流做法:按层大小设计的随机初始化(Xavier 针对 Sigmoid/Tanh、He 针对 ReLU),让每层输出的方差大致不变,训练才稳。
激活函数四兄弟
| 函数 | 形状与公式(文字表述) | 特点与用途 |
|---|---|---|
| Sigmoid | S 形曲线,输出 0 到 1 | 二分类输出概率的经典选择;两侧饱和,深层网络里梯度容易消失,隐藏层基本退役 |
| Tanh | S 形曲线,输出 -1 到 1,零中心 | 比 Sigmoid 收敛快一点(输出均值接近 0);同样两侧饱和,深度网络仍易梯度消失 |
| ReLU | 负数压成 0,正数原样保留 | 计算极快、正区间梯度恒为 1,深度网络主力激活;缺点是负数区梯度为 0,可能导致神经元死亡(永远不再激活) |
| GELU | 对输入按高斯概率做软开关 | 平滑、非单调,Transformer 与大模型 FFN 的主流选择(ReLU 的平滑改良版) |
一句话选型:隐藏层默认 ReLU(或其变体 Leaky ReLU),Transformer 用 GELU/SwiGLU,输出层看任务:二分类用 Sigmoid,多分类用 Softmax,回归不用激活或线性输出。
损失函数:MSE 与交叉熵
损失函数告诉模型错得有多离谱(定义见 机器学习基础「损失函数」一节),深度学习的两个默认选择:
- 均方误差(MSE):回归任务。预测与真实的差平方求平均。
- 交叉熵:分类任务。衡量预测概率分布与真实标签分布的距离,配合 Softmax 输出层使用:它的梯度直接正比于误差大小,误差大就学得快,不会像 Sigmoid + MSE 那样误差大时梯度反而被压没。
前向传播与反向传播
训练神经网络只有两个阶段,来回循环:
前向传播:数据从输入流到输出
把一批数据从输入层喂进去,逐层做线性变换 + 激活,最后在输出层得到预测结果,拿损失函数算出预测与真相的差距。前向传播就是一次完整的走网络:它不改变任何参数,只是算出当前模型错多少。
反向传播:误差从输出流回输入
反向传播(1986 年 Rumelhart 等人系统化)解决的是误差怎么分摊给每个参数。核心是微积分的链式法则:
- 损失对输出层的梯度最容易算(直接拿预测减真相);
- 输出层的梯度往前传一层时,乘上这一层的激活导数与权重,得到更前一层参数的梯度;
- 如此逐层往回,每个参数都拿到自己该为误差负多少责的数值,即损失对各权重的导数。
直觉就是把误差一层层分发回去:最后一层先说「我错了这么多」,前一层听到后按「我对这个错贡献了多少」分账,再往前传。有了每个参数的梯度,就可以用梯度下降更新参数,让损失变小。
flowchart LR
batch["输入 batch"] --> forward["前向传播"]
forward --> prediction["预测输出"]
prediction --> loss["损失函数"]
loss --> backward["反向传播:计算梯度"]
backward --> update["优化器更新权重"]
update -.-> forward核心关系:前向传播计算当前模型错多少,反向传播把误差分配给参数,优化器更新权重后进入下一轮。
计算图与自动微分
现代框架(PyTorch、TensorFlow)把网络记录成一张计算图,前向传播时顺手把每个运算的导数规则记下来,反向传播时自动沿图反向累乘:你永远不需要手算梯度。
这正是深度学习能快速迭代的工程基石。
训练循环的三个时间单位
工程师嘴里的「训练了几轮」是产品经理常听到的黑话,三个词说清:
| 术语 | 含义 | 直觉 |
|---|---|---|
| Step(步) | 用一个 batch 的数据做一次前向 + 反向 + 参数更新 | 走一步 |
| Epoch(轮) | 把整个训练集完整过一遍 | 把全部教材学一遍 |
| Batch size(批大小) | 每步用多少样本 | 每口吃多少 |
一轮的步数 = 样本总数 ÷ 批大小。比如 10 万样本、批大小 256,一个 epoch 约 391 步,训练 30 个 epoch 就是 1 万多次参数更新。epoch 越大越好是错觉:训练损失还在降、验证损失开始升的那一刻,就是该停的时点(早停)。
优化训练
梯度下降三兄弟
训练就是沿着损失下降最快的方向(负梯度)更新参数。按一次用多少数据算梯度,分三种:
| 方式 | 每次更新用多少数据 | 特点 |
|---|---|---|
| 批量梯度下降 | 全部数据 | 方向准但极慢,大模型根本用不起 |
| 随机梯度下降(SGD) | 1 个样本 | 每步噪音大、震荡,但快;几乎只在教学里出现 |
| 小批量 SGD(mini-batch) | 一批(如 32-512 个样本) | 兼顾效率与稳定,深度学习的事实标准 |
学习率与优化器
- 学习率:每次更新的步长。太大→震荡甚至发散;太小→训练慢得像蜗牛。现代做法是学习率调度:先 warmup(从小步长爬升,稳定早期训练),再按余弦/阶梯衰减。
- 动量(Momentum):让更新带上惯性,沿历史方向的累积前进,冲过小坑、加速收敛。
- Adam / AdamW:每个参数按历史梯度的均值与方差自适应调整步长,几乎免调学习率,是当前事实默认;AdamW 修正了 Adam 与权重衰减的耦合,大模型训练的标准选择。
梯度消失与爆炸:深网络的生死线
反向传播是连乘:每往回传一层,梯度就乘一次激活导数和权重。如果每层都乘小于 1 的数,传到浅层时梯度趋近 0:梯度消失,浅层永远学不动,网络实际退化成浅层;反过来每层都乘大于 1 的数,梯度爆炸,参数一步跨飞。
为什么 ReLU 和残差重要:ReLU 正区间的导数恒为 1,乘它不衰减;残差连接(ResNet)让梯度有一条直通快车道(见 CNN 一节)。另外还有:权重初始化(用 Xavier/He 初始化把初始方差控制好,避免开局就消失)、批归一化(把每层输入拉回标准分布)、梯度裁剪(梯度过大就砍一刀)。
归一化:批归一化与层归一化
归一化把每层的输入拉回均值 0、方差 1 的稳定区间,让深层网络不再被激活值尺度漂移折磨:
- 批归一化(BN):按一个 batch 内、每个特征维度统计均值方差归一化。CNN 标配,大幅加速收敛;缺点:依赖 batch 大小(小 batch 不稳)、训练与推理行为不一致(推理用累计统计量)。
- 层归一化(LN):按每个样本、所有特征维度统计归一化,与 batch 无关,训练推理行为一致:这正是 Transformer 选它不选 BN 的原因(详见 Transformer 架构)。
损失曲面:局部最优与鞍点
高维损失函数的形状不是我们熟悉的一个大坑,而是崎岖的高维山地:
- 局部最优:周围都比它高的小坑,梯度下降可能困在里面。高维下其实没那么可怕,大量研究表明局部最优的损失往往与全局最优接近。
- 鞍点:某个方向是下坡、另一个方向是上坡的马鞍,梯度接近 0 但既不是峰也不是谷:高维空间里鞍点远比局部最优常见,这才是训练卡住的头号嫌疑。
对策就是上一节的优化器家族:动量冲过鞍点、Adam 自适应步长,加上随机小批量带来的梯度噪声,大部分卡住都能被救回来。对产品经理而言,理解这一点就够了:训练不收敛常见,真到了死路罕见,先怀疑学习率与数据,再怀疑损失函数设计。
过拟合正则化全家桶
深度模型参数多,是过拟合重灾区。防过拟合的手段(除传统 ML 那套外):
- Dropout:训练时随机关掉一部分神经元(输出置 0),强迫网络不依赖特定神经元组合:效果等价于同时训练一堆子网络再平均;只在训练时生效,推理时全部保留。
- 权重衰减(L2 正则):损失里加权重平方惩罚,把权重压小,模型变「钝」更抗噪。
- 数据增强:对图像做翻转/裁剪/变色、对文本做同义改写,免费扩充数据(见 机器学习基础)。
- 早停(Early Stopping):盯着验证集损失,验证损失开始回升就停:训练损失还在降但模型已经在背答案了。
超参数速查:训练效果不好先查谁
| 现象 | 优先怀疑 | 对策 |
|---|---|---|
| 损失不降 | 学习率(太大震荡/太小爬行)、数据没归一化 | 调学习率,看损失曲线形状 |
| 训练好、验证差 | 过拟合 | 加正则、减模型、加数据增强、早停 |
| 训练验证都差 | 欠拟合 / 数据问题 | 换更大模型、查数据质量与标签 |
| 梯度爆炸(NaN) | 学习率过大、初始化不当 | 调小学习率、梯度裁剪 |
| 收敛极慢 | 学习率太小、优化器不合适 | 换 Adam、加大学习率加 warmup |
这些排查顺序有个共同原则:先看损失曲线,再动超参数:损失曲线的形状(震荡/平滑/先降后升)会直接告诉你问题出在哪一类。
卷积神经网络(CNN)
卷积神经网络专为图像设计,核心洞察:相邻像素比相隔万里的像素关系大得多,且同一特征(边缘、纹理)在全图各处都适用:因此不需要每个位置一套参数。
典型 CNN 把空间结构逐步压缩成语义表示,再接不同任务头:
flowchart LR
image["输入图像"] --> conv1["卷积块 1<br/>边缘 / 色块"]
conv1 --> pool1["池化 / 下采样"]
pool1 --> conv2["卷积块 2<br/>纹理 / 形状"]
conv2 --> pool2["池化 / 下采样"]
pool2 --> feature["高层特征图"]
feature --> classify["分类头"]
feature --> detect["检测头"]
feature --> segment["分割头"]核心关系:卷积与下采样逐层扩大感受野、提炼特征,最后保留空间信息的任务接检测或分割头,压缩成整图语义的任务接分类头。
卷积运算:局部连接 + 权重共享
卷积层用一个小的卷积核(如 3×3)在输入图像上滑动,每个位置计算核与局部像素的加权和,得到一个输出值:
- 局部连接:每个输出只看核大小的局部区域,参数从全连接的全图规模降到核规模。
- 权重共享:同一个核滑遍全图,同一套权重识别全图各处的同一种特征:参数再降一个量级,同时带来平移等变性:猫往左挪一格,识别「猫」的特征响应也跟着挪一格,模型天然对位置不敏感。
- 步长(Stride):核每次滑动几格,步长 2 等于输出缩小一半(下采样)。
- 填充(Padding):输入边缘补 0,让边缘像素也能被核覆盖、控制输出尺寸。
池化与感受野
- 池化(Pooling):对局部区域取最大值(最大池化)或均值(平均池化),进一步下采样,同时提供少量平移不变性;没有参数。
- 感受野:输出上一个点往回看到的输入区域大小。层越深、卷积叠加越多,感受野越大:浅层看细节、深层看整体,这就是 CNN 层次化特征的来源。
经典结构演进
| 网络 | 年份 | 关键贡献 |
|---|---|---|
| LeNet | 1998 | 第一个实用 CNN,手写数字识别 |
| AlexNet | 2012 | ImageNet 冠军,深度 + ReLU + Dropout + GPU,深度学习奇点 |
| VGG | 2014 | 规律堆叠 3×3 卷积,证明深的价值;代价是参数多、算力贵 |
| ResNet | 2015 | 残差连接:让层学残差(输出 = 输入 + 学到的变化),梯度有了直通路径,百层网络第一次可训练:深度学习深度的分水岭 |
常用卷积技巧
- 1×1 卷积:只跨通道、不跨空间的卷积,作用是调整通道数(升维/降维)和跨通道融合:ResNet 的 Bottleneck、轻量化网络的标配。
- 小核堆叠:两个 3×3 卷积的感受野等于一个 5×5,参数却更少、非线性更强:VGG 之后的默认习惯。
- 深度可分离卷积:把标准卷积拆成逐通道卷积 + 1×1 逐点卷积两步,参数与计算量降到约九分之一,代价是精度略降:MobileNet 系列用它在手机上跑出实时图像识别。
CNN 的三大任务形态
CNN 不只是图像分类这一个形态,同一套卷积-池化骨架撑起了计算机视觉的半壁江山:
| 任务 | 输出形态 | 代表结构 |
|---|---|---|
| 图像分类 | 整图一个类别 | 卷积骨干 + 全连接分类头 |
| 目标检测 | 框出每个物体的位置与类别 | YOLO(一步到位)、Faster R-CNN(先提候选再分类) |
| 语义分割 | 每个像素一个类别 | U-Net(编码-解码 + 跳跃连接)、DeepLab |
检测与分割这类输出也是空间结构的任务,是理解卷积特征图一路保留空间位置信息的最佳例子:分类把空间信息压缩没了,检测与分割必须留着它。
CNN 为什么适合图像:参数少(不易过拟合)、自带平移等变(位置变化不用重新学)、层次化感受野天然匹配局部细节 → 整体语义的视觉结构。这套优势让它统治图像十年;直到 ViT 证明图像切成 patch 当 token 扔进 Transformer 也能赢(见 Transformer 架构 与 多模态理解)。
循环神经网络(RNN)
序列建模:共享参数地处理每个时刻
文本、语音、时间序列的共同点是顺序:第 t 个词的意思依赖前 t−1 个词。RNN 的思路是:同一套循环权重在每个时刻重复使用,每步输入当前 token 与上一步的隐状态,输出本步隐状态:
- 循环权重:一个记忆模块,把过去的信息压缩进隐状态一路带下去:RNN 的参数与序列长度无关(共享),这是它与全连接的本质区别。
- 训练用随时间反向传播(BPTT):把时间轴展开成深网络再反向传播。
沿时间展开后,每个时刻都复用同一个 RNN 单元:
flowchart LR
x1["x₁"] --> cell1["RNN 单元"]
h0["h₀"] --> cell1
cell1 --> h1["h₁"]
h1 --> cell2["RNN 单元"]
x2["x₂"] --> cell2
cell2 --> h2["h₂"]
h2 --> cell3["RNN 单元"]
x3["x₃"] --> cell3
cell3 --> h3["h₃"]
cell1 -.共享参数.-> cell2
cell2 -.共享参数.-> cell3核心关系:每个时间步接收当前输入与上一步隐状态,输出新的隐状态;单元参数共享,所以序列变长不会新增一套权重。
长依赖问题与 LSTM/GRU
RNN 的隐伤和深网络同源:误差沿时间步连乘,几步之后梯度消失:距离远了,前面的话就记不住了(梯度爆炸同理,靠梯度裁剪治)。长依赖是序列建模的核心难题。
LSTM(长短期记忆,1997) 的解法是给记忆装门:用三个门控制信息的流进、流出与遗忘:
- 遗忘门:决定上一刻的记忆保留多少;
- 输入门:决定当前新信息写进记忆多少;
- 输出门:决定此刻的记忆对外输出多少。
GRU 是 LSTM 的简化版,把三个门合并成两个(更新门 + 重置门),参数更少、训练更快,效果通常与 LSTM 相当。两个模型的本质都是给长期记忆修了一条可以稳定传梯度的通道:门控让信息要么几乎原样保留、要么明确丢弃,而不是被连乘慢慢磨没。
双向 RNN:让每个词看见前后文
普通 RNN 只按时间正序读序列,第 t 步只能看见过去的词。双向 RNN 同时跑一个正向和一个反向的 RNN,每个位置把两个方向的隐状态拼接起来:于是每个词都同时获得前后文信息。命名实体识别、情感分析这类必须看后文才能定的任务,双向是标配。一个简单的例子:「苹果发布会」里的「苹果」到底是水果还是公司,要看了后文才知道:单向模型在「发布会」这个词上才恍然大悟,双向模型在「苹果」处就已经有正确答案了。
RNN 家族一览
| 模型 | 核心机制 | 优势 | 短板 |
|---|---|---|---|
| 朴素 RNN | 循环权重 + Tanh | 结构最简单 | 长依赖梯度消失,记不住远距离信息 |
| LSTM | 遗忘/输入/输出三门 | 长记忆能力强 | 参数多、训练慢 |
| GRU | 更新门 + 重置门 | 参数少、效果接近 LSTM | 略弱于 LSTM 的极致长记忆 |
| 双向 RNN | 正反两个方向拼接 | 每步获得完整上下文 | 不是因果结构,不能做自回归生成 |
这张表的演化主线就是怎么让信息传得更远:从循环连乘,到门控保护,再到双向补全。理解这条主线,就理解了 Transformer 为什么要彻底换一种传信息的方式(见 Transformer 架构)。
序列到序列与注意力的起源
机器翻译、摘要、对话这类序列 → 序列任务,经典结构是 seq2seq:编码器把整句压成最后一个隐状态,解码器再展开生成。瓶颈明显:一个定长向量装不下整句信息,长句必丢。
Bahdanau 等人把注意力加进这条链路:解码每一步不再只看编码器的最终向量,而是按当前解码状态给源序列各位置打分,加权读取相关隐状态(Neural Machine Translation by Jointly Learning to Align and Translate)。注意力因此先是机器翻译里的对齐模块,后来才被 Transformer 升级成唯一骨干。机制展开见 Transformer 架构。
Encoder-Decoder 的信息流与张量形状
张量形状、Teacher Forcing、collate_fn 与 loss mask 的工程契约见 深度学习工程实践。下面只保留信息流,便于衔接到 Transformer。
机器翻译把一个源序列转换成另一个目标序列。设源序列为 x₁...xₛ,目标内容 token 为 y₁...yₘ,训练样本会构造成 tgt=[<BOS>, y₁...yₘ, <EOS>]。源长度 S 与目标内容长度 M 没有固定相等关系,也不存在可靠的长度换算公式。中文分词、英文分词和语序都会改变 token 数量。
Encoder 读取完整的源序列,Decoder 根据源序列表示和已经生成的目标前缀逐步预测下一个 token:
1 2 | |
公式中的最后一步就是预测 <EOS>。
Encoder 与 Decoder 通常是两个独立的 RNN 模块:Encoder 的循环权重在所有源时间步共享,Decoder 的循环权重在所有目标时间步共享,但两套权重默认不相同。Encoder 的最终状态可以作为 Decoder 的初始状态,也可以把每个源位置的隐状态交给 Attention 使用。
以 batch_first=True 为例,下面的 S 是补齐后的源序列长度,T 是补齐后的目标 tensor 长度,目标 tensor 已包含 <BOS> 和 <EOS>,常见接口形状如下:
| 对象 | 典型形状 | 含义 |
|---|---|---|
| Encoder 输入 | [B, S] | 源 token ID |
| Encoder 输出 | [B, S, D×H] | 每个源位置的隐状态,双向时拼接两个方向 |
| Decoder 输入 | [B, T-1] | <BOS> 加上目标前缀 |
| Decoder logits | [B, T-1, V] | 每个位置对词表的预测 |
| 目标标签 | [B, T-1] | 右移后的真实 token |
| LSTM hidden | [L×D, B, H] | 层数、方向、batch、隐藏维度 |
其中 B 是 batch size,H 是 hidden size,V 是目标词表大小,L 是 RNN 层数,D 是方向数。双向 Encoder 通常有 D=2,自回归 Decoder 通常有 D=1。工程实现必须统一 batch_first、hidden state 形状和源/目标词表的约定。
训练时:目标右移与 Teacher Forcing
训练数据要显式加入特殊 token:<BOS> 表示开始,<EOS> 表示目标序列结束,<PAD> 只用于把一个 batch 补齐。目标句为:
1 2 3 | |
这种右移让 Decoder 在第 i 步根据前缀预测 yᵢ。Teacher Forcing 指训练时把真实的前一个 token 喂给 Decoder,而不是使用模型刚刚预测的 token。它让训练稳定、可以批量计算,但也造成训练和推理的输入分布不同:推理时一个错误会成为下一步的输入,这种不一致叫 exposure bias。工程上先用真实自回归评估确认错误是否由此引起;仍需使用 RNN 且误差累积明显时,再评估 scheduled sampling,长文本转换任务则通常比较 Transformer 基线。
训练时应把 Teacher Forcing 下的 loss 与真实自回归推理的质量分开记录。前者用于优化,后者才接近线上表现。<PAD> 位置不能参与 loss,否则模型会学会预测补位符,而不是学习翻译。
1 2 3 4 5 6 7 8 9 10 11 | |
变长 batch:padding、mask 与 packing
单条样本可以是不同长度,但 GPU 通常需要把多个样本组成规则张量。因此 DataLoader 会把短序列补成 batch 内的最大长度:
<PAD>:为了对齐形状加入的占位符,没有语义。<EOS>:表示一条序列在语义上结束,参与目标标签。- Padding mask:告诉 Encoder 或 Attention 哪些位置是补位,避免模型读取
<PAD>。 - Causal mask:限制 Decoder 不能看到未来 token,主要用于 Transformer Decoder。
- Loss mask:计算损失时忽略
<PAD>位置,通常通过ignore_index=PAD_ID实现。
RNN 中可以用 pad_sequence 组成 batch;当 padding 比例很高时,Encoder 可以使用 pack_padded_sequence 跳过补位计算,也可以先按长度分桶,让同一 batch 的样本长度更接近。使用 packing 时要同步维护原始 lengths、样本顺序和反排序逻辑,不能拿 padding 后的长度代替真实长度。
1 2 3 4 5 6 7 8 9 | |
最常见的变长 bug 是:长度字段和 padding 后的 batch 顺序不一致、mask 在 CPU 而 logits 在 GPU、把 <EOS> 也屏蔽掉、或让 <PAD> 参与交叉熵。排查时先打印一条样本的 token、长度、mask 和右移后的输入/标签,再看整体 loss。
推理时:<BOS>、<EOS> 与最大长度
推理时没有真实目标句,Decoder 从 <BOS> 开始,每一步把自己生成的 token 作为下一步输入。生成 <EOS> 后,该样本结束;如果模型始终不生成 <EOS>,达到 max_length 后强制结束。max_length 是防止死循环和异常输出的安全上限,不是模型真正理解出的目标长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
长度上限应从数据和业务约束共同确定:
- 统计验证集目标长度分布,用较高分位数加安全余量作为默认上限。
- 按用户可接受的等待时间、输出大小和成本设置绝对上限。
- 源序列长度的线性启发式只能作为兜底,不能把源长度直接当作目标长度。
- 线上记录
<EOS>命中率、max_length截断率、空输出率、输出长度分布和目标/源长度比。
如果训练标签中从未出现 <EOS>,模型就没有学到停止信号;如果第一个预测就是 <EOS>,需要按业务定义为空输出还是合法的空目标。批量推理时不同样本可以在不同时间结束,必须用 finished mask 隔离已结束样本,不能把后续的 <PAD> 或垃圾 token 当作有效输出。
解码策略:Greedy、Beam Search 与长度惩罚
- Greedy 解码:每一步选择当前概率最高的 token,速度快、结果稳定,适合作为基线。
- Beam Search:保留多个候选前缀,继续展开后比较完整序列得分;
beam_size=1可以看作 Greedy。翻译、摘要等任务常用它寻找整体概率更高的序列。 - 长度归一化或长度惩罚:直接累加 log probability 会偏好短序列,因为每增加一个 token 通常都会增加负分。长度惩罚用来缓解这种短序列偏置,但会带来新的长度偏好,需要在验证集上校准。
Beam Search 的代价是更多候选、更高延迟和显存占用,不代表一定更准确。对比解码策略时至少同时看序列质量、输出长度、<EOS> 命中率、截断率和延迟;开放式聊天通常优先使用采样或 Greedy,机器翻译等转换任务再评估 Beam Search。LLM 运行时的停止字符串和结构化约束见模型推理与部署。
状态生命周期:重置、截断与流式会话
RNN 的 hidden state 是数据的一部分,不是可以随意留在服务进程里的全局变量:
- 每个独立样本或独立请求默认重置 hidden state,避免不同用户、不同 batch 之间串状态。
- 只有同一条连续时间序列或同一会话,才跨 chunk 传递 state;服务接口应显式定义传入、返回和过期方式。
- 使用截断 BPTT 训练长序列时,在 chunk 边界对 hidden state 做
detach,否则计算图会随时间无限增长。 - 流式服务要定义 session ID、超时、显式 reset、服务重启后的恢复策略;无法可靠持久化时,宁可重新建立状态,也不要静默复用旧状态。
- 双向 Encoder 可以利用完整源序列的前后文,但不适合直接承担因果生成的 Decoder 角色。
RNN 的现状
大模型时代,RNN/LSTM 在长文本与大规模任务上已被 Transformer 全面超越;但语音、时序预测、小模型场景仍是它的舒适区,而且它对序列长度的计算成本是线性的(Transformer 是平方级):2023 年后 Mamba 等新一代序列模型也在延续线性成本 + 长记忆的路线。
历史作用上,RNN 是理解注意力机制为什么被发明的最佳教材。
图神经网络(GNN)
图数据:关系与结构本身就是信息
朋友关系、分子结构、知识图谱、交通网络:这些数据由节点(实体)和边(关系)构成,没有一行一个样本的规整结构,也没有固定的邻居数量:每个节点的邻居数都不一样。CNN 的卷积核、RNN 的时间步都套不上,于是有了图神经网络。
消息传递:向邻居「要信息」
GNN 的核心机制叫消息传递,每层做三件事:
- 聚合:把当前节点的邻居特征收集起来(求和、取平均、取最大,按任务选);
- 更新:把自己的特征与聚合到的邻居信息合并,经过线性变换与激活,得到本层新表示;
- 重复:堆多层,信息逐层扩散:第 1 层看到直接邻居,第 2 层看到邻居的邻居,层数越多视野越远。
GCN(图卷积网络) 是代表实现:把邻居加权求和写成矩阵运算(邻接矩阵 × 特征矩阵 × 权重),再用度矩阵归一化,避免大度节点(社交达人)的信息淹没小度节点。更进阶的 GAT 在聚合时用注意力给不同邻居分配不同权重:谁重要就多听谁的。
一层消息传递可以画成:
flowchart LR
neighbor1["邻居节点 A"] --> aggregate["聚合邻居消息<br/>求和 / 平均 / 注意力加权"]
neighbor2["邻居节点 B"] --> aggregate
center["中心节点自身特征"] --> update["更新节点表示"]
aggregate --> update
update --> next["下一层表示 hᵥ′"]核心关系:中心节点把自身特征与邻居消息合并,经过更新得到新表示;堆叠多层后,信息视野从一跳邻居扩展到多跳邻居。
三类任务:节点、边、整张图
GNN 的任务按预测对象分三类:
| 任务 | 预测什么 | 例子 |
|---|---|---|
| 节点分类 | 每个节点的类别 | 论文领域分类、用户画像、欺诈账户识别 |
| 链接预测 | 两个节点间有没有边/边强度 | 好友推荐、知识图谱补全、商品关联 |
| 图分类 | 整张图的类别/属性 | 分子毒性预测、程序代码语义分析 |
一个直觉例子:识别转账网络中的洗钱账户:单个账户的特征(金额、频率)不足以判断,但它在网络里的位置(把钱转给谁、谁又转给谁)是强信号。这就是 GNN 的核心价值:把关系结构本身变成特征。
应用:分子、社交、知识图谱
| 场景 | 节点 / 边 | 任务 |
|---|---|---|
| 分子性质预测 | 原子 / 化学键 | 预测毒性、药效(图分类) |
| 社交网络 | 用户 / 关注关系 | 好友推荐(链接预测)、社区发现 |
| 知识图谱 | 实体 / 语义关系 | 知识补全、问答推理 |
| 推荐系统 | 用户 / 商品 / 行为 | 兴趣扩散与冷启动 |
| 交通/电网 | 传感器 / 连接 | 拥堵、负荷预测(时空 GNN) |
词嵌入(Embedding)
分布假说:词的语义藏在它的邻居里
「国王」和「皇帝」为什么相似?分布假说的回答:因为它们在语料里经常出现在相似的上下文里。这是现代 NLP 的起点:把词的语义从人查字典变成统计邻居。
Word2Vec:静态嵌入的里程碑
Word2Vec(2013) 用神经网络把每个词映射成一个低维稠密向量(如 300 维):训练时让模型从上下文预测目标词(CBOW)或从目标词预测上下文(Skip-gram),学完后每个词对应一个向量:语义相近的词向量距离近,甚至出现经典的「国王 − 男人 + 女人 ≈ 女王」式向量运算。
但 Word2Vec 是静态嵌入:一个词只有一个向量,一词多义处理不了(「苹果」是水果还是公司?取决于上下文,向量却只有一个)。同期还有 GloVe(2014),用全局共现统计而非滑动窗口训练,各有所长;工程上如今都已被上下文嵌入取代。
上下文嵌入:ELMo 与 BERT
ELMo(2018) 第一次做到按上下文给词不同的表示:双向语言模型为每个词产出随语境变化的向量。BERT(2018) 更进一步,用 Transformer 双向编码,每个词的表示由整句话动态决定:「苹果」在水果句和科技句里得到完全不同的向量。从此 NLP 进入预训练 + 微调时代:先在海量文本上预训练出通用表示,再在少量标注数据上微调下游任务。
向大模型的过渡:BERT 之后,GPT 系列沿解码器 + 下一个词预测路线把同一个思想推向极致:预训练的规模从亿级参数涨到千亿级,嵌入从词级升级为 token 级、从静态变成逐层动态,最终成为今天的大语言模型(完整链路见 大模型基础)。
嵌入对 LLM 的意义
- 从词嵌入到 token 嵌入:现代大模型的输入层就是一张可学习的嵌入表,把 token 变成向量,之后每一层都在加工这些向量:Transformer 的整个计算都是向量之间的运算。
- 语义空间:嵌入空间里距离近 = 语义近,这是向量检索(RAG)的物理基础(见 RAG 与知识检索)。
- 多模态对齐:CLIP 把图像与文本嵌入到同一空间,是图文搜索与文生图的关键桥梁(见 多模态理解)。
- 嵌入的现代实现就是 Transformer 的输入层,详见 Transformer 架构。
嵌入在工程里的四个用法
嵌入不只是模型的输入层,它本身是产品可以反复利用的资产:
- 语义检索:把文档与查询都转成向量,按余弦相似度找最相关的片段:RAG 与语义搜索的核心,比关键词匹配更能处理同义不同词。
- 聚类与分群:把文本/商品/用户嵌入后做 K-means,得到语义分群:工单主题聚类、竞品评论分析,零标注就能出洞察(聚类见 机器学习基础)。
- 相似推荐:和你收藏的这篇最像的文章 = 向量最近邻;推荐系统里物品嵌入、用户嵌入的匹配是经典打法。
- 可解释诊断:把嵌入降维(如 t-SNE)画出来,肉眼检查模型是否把语义相近的样本聚在一起:模型行为的粗检。
产品经理能用嵌入做什么
嵌入是把非结构化内容变成结构化向量的万能转换器:文本、图片、音频都能变成数字向量,然后接上任何传统 ML 的玩法(检索、聚类、分类)。
很多 NLP 需求的最简实现,就是嵌入 + 向量检索 + 少量规则,不用微调大模型也能上线。
产品视角:深度学习的边界与成本
能力与数据量的关系曲线
深度学习的能力曲线不是线性的,大致三段:
- 数据很少(千级以下):深度模型大概率过拟合,传统 ML 或迁移学习更稳。
- 数据中等(万级到百万级):深度学习开始发力,数据越多优势越大;此时预训练模型 + 微调性价比最高:借一个大模型/预训练模型的先验知识,用少量自己的数据适配,是绝大多数 AI 产品团队的真实打法。
- 数据海量(千万级以上):深度学习/大模型一骑绝尘,传统 ML 触顶:这也是基础模型的领地。
训练成本:算力与数据标注
- 算力:深度学习训练是算力密集型。一张图分类模型在单卡上小时级;大模型预训练是 GPU 集群×数周的千万级账单(详见 模型训练与对齐 与 模型推理与部署)。
- 数据标注:监督学习需要标注数据,标注成本常常超过算力成本。缓解手段:自监督预训练(标签免费)、半监督、数据增强、主动学习(只标注模型最拿不准的样本)。
- PM 的成本观:小任务用预训练模型微调,几乎总是比从零训练便宜一个量级;只有在任务极特殊、数据极多、或要自研基础模型时,才谈得上从零训练。
什么时候值得上深度学习
| 场景 | 建议 | 原因 |
|---|---|---|
| 图像/语音/复杂文本 | 深度学习(或大模型) | 特征无法手工设计,表示学习是唯一解 |
| 表格数据、数据量小 | 传统 ML | 树模型又准又可解释,深度学习无优势(见 机器学习基础) |
| 低延迟/端侧 | 轻量 CNN/蒸馏小模型 | 深度模型可以压缩到手机端跑,但要专门做轻量化 |
| 强可解释合规场景 | 传统 ML 或事后归因 | 深度学习黑盒,监管解释成本高 |
| 有预训练模型可借 | 微调而非从零训练 | 数据、算力、时间都省一个量级 |
可解释性现状
深度学习的黑盒问题是产品化的真实约束。当前主流思路:
- 事后归因:Grad-CAM(图像热力图)、注意力权重可视化、LIME/SHAP(给局部决策找解释):解释的是模型看了哪里,不是模型为什么这么想,但已经够大部分产品与合规场景使用。
- 结构先行:用可解释的组件(规则、树)包裹黑盒,或让黑盒输出可解释的中间产物(引用来源、给出依据)。
- 评估兜底:解释不清,就用充分的测试与监控兜底:把为什么这样换成在各种情况下都测过了(方法论见 评估与评测)。
深度学习的评估指标速览
分类/回归的基础指标(准确率、F1、AUC)见 机器学习基础,深度学习的特色指标补几个:
| 任务 | 指标 | 含义 |
|---|---|---|
| 图像分类 | Top-1 / Top-5 准确率 | 第一名命中 / 前五名包含正确答案;ImageNet 时代的行业标准 |
| 目标检测 | mAP(平均精度均值) | 对不同置信度阈值下的精确率-召回率曲线求面积再平均,兼顾定位与分类 |
| 语义分割 | IoU / mIoU | 预测区域与真实区域交集 ÷ 并集,衡量画得准不准 |
| 生成质量 | PSNR / SSIM / FID | PSNR 看像素误差、SSIM 看结构相似、FID 看生成分布与真实分布的距离(生成类详见 图像生成) |
产品经理只需要记住:不同任务的好长得完全不一样,拿图像分类的准确率去验收检测模型、拿像素误差去验收生成模型,都会得出荒谬结论。验收指标在立项时就和团队对齐,写进验收标准,而不是模型上线前临时拍一个。
给产品经理的一句话
深度学习强在自动学特征,贵在数据 + 算力,短在解释与稳定。选型时先问:特征能不能人工设计?能→传统 ML;不能→深度学习;再问数据够不够、成本扛不扛得住、解释过不过得了关。
它是工具,不是信仰。
落地前清单:八个问题
深度学习项目立项时,把下面八个问题问完再拍板,能避开大部分坑:
- 任务能映射成什么输入输出?输入形态(图/文/音/表)直接决定架构选型。
- 数据有多少、质量如何?够不够支撑深度学习;不够就考虑迁移学习或传统 ML。
- 有没有可借的预训练模型?有就微调,别从零训练:这是性价比第一原则。
- 标注成本谁来扛?预算里有没有标注费;能不能用自监督/半监督省标注。
- 评估指标在立项时定好了吗?按任务定指标并写进验收标准(见上节)。
- 延迟与成本预算?端侧还是云端、每秒多少请求、单次推理预算,决定模型要不要轻量化。
- 失败怎么办?错误输出有没有兜底(降级链、人工复核、可回退开关)。
- 合规与可解释?数据授权、敏感信息、监管解释需求,越早对齐越省钱。
这八问和 AI 系统架构 的四层地图是同一套思路:先想清楚每一层要什么,再动手。
练习:检验你的理解
- 为什么激活函数必须是非线性的?如果全部用线性激活,堆 100 层会发生什么?
- 深度网络训练时梯度消失,为什么 ReLU 和残差连接能救?如果换成 Sigmoid,问题为什么更严重?
- LSTM 的门解决的是 RNN 的什么问题?这个问题的本质和深网络的什么问题同源?
- 公司要做工单文本分类,只有 2000 条标注:你会从零训练一个深度网络,还是用预训练模型微调?为什么?
- Word2Vec 与 BERT 的词表示有什么本质区别?「苹果公司」里的「苹果」,哪个模型能正确区分?
- 机器翻译中源句长度为
S、译文长度为T,为什么两者不必相等?<EOS>与max_length各自负责什么? - 一个 batch 中两个样本分别在第 4 步和第 8 步生成
<EOS>,如何用finished mask、<PAD>和 loss mask 处理? - Teacher Forcing 为什么会造成 exposure bias?为什么评估时必须运行真实的自回归推理?
参考答案提示:1) 线性函数的复合还是线性函数,堆多少层都等价于一层:非线性是网络表达复杂关系的唯一来源。2) ReLU 正区导数恒 1、残差提供梯度直通路径,连乘不再衰减;Sigmoid 最大导数只有 0.25,连乘必消失。3) 长依赖的梯度消失/爆炸,与深网络的梯度问题本质同源,都是连乘效应。4) 微调:数据太少,从零训练必然过拟合;预训练模型的知识是最大的杠杆。5) BERT 的表示随上下文变化,能区分一词多义;Word2Vec 每个词只有一个静态向量。6) S 和 T 分别由源语言与目标语言的 token 化和表达方式决定,没有固定换算;<EOS> 是模型学到的语义终止信号,max_length 是未终止时的安全上限。7) 各样本独立更新 finished mask,结束后输出位置填 <PAD> 并冻结状态;训练 loss 忽略 <PAD>,不能把补位符当作真实标签。8) 训练使用真实前缀,推理使用模型自己的前缀,错误会逐步累积;只有真实自回归结果才能暴露提前终止、重复和截断问题。
来源说明
本文为原创整理,概念与结论参考以下资料(引用日期:2026-09-04):
- Sutskever I, Vinyals O, Le Q V. Sequence to Sequence Learning with Neural Networks,2014:Encoder-Decoder 与序列到序列学习。
- Bahdanau D, Cho K, Bengio Y. Neural Machine Translation by Jointly Learning to Align and Translate,2014:Attention 与机器翻译对齐。
- Wu Y, et al. Google's Neural Machine Translation System,2016:神经机器翻译系统与长度惩罚。
- PyTorch NLP From Scratch: Translation with a Sequence to Sequence Network and Attention:变长序列、Teacher Forcing 与解码实现示意。
AIGC-Interview-Book(仅供维护者交叉验证,读者以公开论文、教材与官方文档为准) - 深度学习核心概念、网络架构、训练优化、注意力与图神经网络等考点提纲(微信读书《AIGC 面试指南》,WeThinkIn 团队;本地预取,非公开链接)
课程笔记(结构参考,未照抄) - 地球科学大数据课程笔记:2026-04-03(ANN 入门)、2026-04-10(ANN + CNN)、2026-04-17(RNN/LSTM/GRU)、2026-04-24(GNN)、2026-05-22(Transformer 第 1-2 节)
经典论文与教材 - LeCun Y, et al. Gradient-Based Learning Applied to Document Recognition (LeNet),1998 - Krizhevsky A, et al. ImageNet Classification with Deep Convolutional Neural Networks (AlexNet),2012(https://papers.nips.cc/paper/2012/hash/c399862d3b9d6b76c8436e924a68c45b-Abstract.html) - He K, et al. Deep Residual Learning for Image Recognition (ResNet),2015(https://arxiv.org/abs/1512.03385) - Hochreiter S, Schmidhuber J. Long Short-Term Memory (LSTM),1997(https://www.bioinf.jku.at/publications/older/2604.pdf) - Mikolov T, et al. Efficient Estimation of Word Representations in Vector Space (Word2Vec),2013(https://arxiv.org/abs/1301.3781) - Devlin J, et al. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding,2018(https://arxiv.org/abs/1810.04805) - 李航《统计学习方法》;Ian Goodfellow《深度学习》(Deep Learning,花书)——神经网络训练与优化原理的权威参考
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:AI-PM Wiki Team
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用