
深度学习这四个字第一次接触的人多半会被一堆术语砸晕张量、卷积、epoch、batch size、学习率、损失函数、反向传播、过拟合……每个词单看都认识凑在一起就成了天书。我自己刚开始啃这块内容的时候最大的痛苦不是数学而是概念之间的从属关系搞不清楚——不知道谁是谁的上层不知道哪些参数会影响哪些结果更不知道面试或考试里问的“深度学习八股”到底在问什么。这份整理就是给同样卡在这一步的人准备的它不追求把每个公式都推导一遍而是把深度学习里最常出现的基本概念和术语按“数据—模型—训练—评估—环境”这条主线重新串一遍讲清楚每个词指什么、为什么存在、在实际项目里怎么用。不管你是刚上完第一节课的学生还是从传统算法转过来的工程师或者只是想看懂技术文章里那些缩写都可以顺着往下读。1. 先建立整体认知深度学习的概念地图1.1 从机器学习到深度学习关系到底是怎样的很多人会把机器学习和深度学习当成两个并列的东西其实它们是包含关系。机器学习是一个大框架核心思路是让程序从数据里自动找规律而不是靠人一条条写规则。深度学习是机器学习下面的一个分支它的特点是使用多层神经网络来自动提取特征。传统机器学习做图像分类往往需要人先设计特征比如边缘、角点、颜色直方图再把特征喂给分类器深度学习直接把原始像素丢进去让网络自己在训练中学会该看什么。这个区别带来两个直接后果。第一深度学习对数据量的要求更高因为要学的参数多得多几万张图往往只是起步。第二深度学习对算力的要求更高矩阵乘法是它的主要运算形式显卡的并行能力刚好适合干这件事。理解了这一点后面看到“GPU 环境配置”“显存不够”“batch size 调小”这些说法时你就知道它们不是玄学而是这条技术路线的必然产物。再往下分深度学习又衍生出卷积神经网络CNN、循环神经网络RNN、Transformer、生成对抗网络GAN、深度强化学习等方向。它们共享同一套底层机制前向传播算输出损失函数算误差反向传播算梯度优化器更新参数。把这条主线记住具体网络结构再怎么变你都能找到落点。1.2 一张术语地图数据、模型、训练、评估、部署我把深度学习的术语分成五大块这样记忆负担会小很多。数据相关样本、标签、特征、张量、批次、训练集、验证集、测试集、归一化、数据增强。模型相关神经元、权重、偏置、层、激活函数、卷积核、池化、参数量、感受野、网络深度。训练相关前向传播、损失函数、反向传播、梯度、学习率、优化器、epoch、iteration、batch size。评估与调优相关过拟合、欠拟合、正则化、Dropout、早停、准确率、精确率、召回率、F1、混淆矩阵。环境与工程相关框架、CUDA、cuDNN、显卡驱动、显存、混合精度、分布式训练、推理部署。这张地图的价值在于当你遇到一个陌生术语时先判断它属于哪一块再想它和相邻概念的因果链。比如“梯度消失”属于训练块它和激活函数、网络深度、权重初始化都有关再比如“mAP”属于评估块它只出现在目标检测任务里。分类清楚了查资料和提问都会精准很多。提示不要试图一次性背下所有术语。更有效的方式是先吃透“数据—模型—训练—评估”这条闭环然后每学一个新概念就把它挂到这条链上问自己三个问题它在哪一步起作用、它影响谁、它被谁影响。2. 数据与张量模型眼里的世界长什么样2.1 张量、形状与维度从标量到四维的直觉张量这个词听起来唬人本质上就是多维数组是深度学习框架里统一的数据容器。零维张量是标量比如一个损失值 0.32一维张量是向量比如一句话的词向量二维张量是矩阵比如一张灰度图三维及以上就叫高阶张量比如一张彩色图片的形状是 (通道, 高, 宽)加上批次维度就变成 (批次, 通道, 高, 宽) 的四维张量。为什么一定要强调形状因为绝大多数报错都和形状对不上有关。一个全连接层期待输入是 (batch, features)你却传了 (batch, channels, height, width)它就会直接报维度不匹配。卷积层则相反它期待 (batch, channels, height, width)如果你先把图展平了再喂进去空间信息就丢了。我自己的习惯是每写一行网络代码就在纸上标一遍张量形状的流动过程这个笨办法能省下大量调试时间。批次维度通常记作 N通道记作 C高宽记作 H、W这套 NCHW 记法在 PyTorch 里是默认的TensorFlow 早期常用 NHWC。看到别人代码里出现 permute 或 transpose多半就是在两个格式之间转换。2.2 数据集三件套训练集、验证集、测试集怎么分数据一般被切成三份。训练集用来更新模型参数验证集不参与参数更新只用来观察模型在没见过的数据上表现如何并据此调超参数、选模型测试集只在最后用一次用来给出一个相对客观的最终成绩。常见的划分比例是 6:2:2 或 8:1:1数据量越大验证集和测试集占比可以越小。小数据集上做交叉验证会更稳比如五折交叉验证每次用四折训练、一折验证把五次结果平均。这个做法虽然训练成本翻了几倍但能显著降低“运气好分到简单验证集”的误判。这里有一个新手极容易踩的坑数据泄漏。如果在划分之前就做了全局归一化或者把同一张原图增强出的多个副本分到了训练集和验证集两边验证成绩就会虚高。正确做法是先按样本或按主体划分再分别统计训练集的均值方差然后把同一套变换应用到验证集和测试集。注意测试集不是用来调参的。一旦你根据测试集结果反复调整模型测试集就事实上变成了验证集最终报告的成绩会偏乐观。2.3 归一化与数据增强让训练更稳的两个前置动作归一化的目的是把输入数据缩放到一个数值范围比较温和的区间通常是减均值再除以标准差。原因很直接如果输入特征量纲差异巨大梯度方向会被大数值维度主导训练就会抖。图像任务里常直接套用 ImageNet 的统计值均值约等于 [0.485, 0.456, 0.406]标准差约等于 [0.229, 0.224, 0.225]。这不是硬性规定但在使用预训练模型时保持和预训练阶段一致的归一化方式非常重要否则模型看到的分布就变了。数据增强是在不改变标签的前提下人为制造更多样的训练样本。图像里有随机裁剪、水平翻转、旋转、颜色抖动、随机擦除进阶一点的有 Mixup、CutMix。它的作用相当于一种免费的正则化能让模型对位置、光照、遮挡不那么敏感从而提升泛化能力。但增强不是越多越好。做过医学图像或工业缺陷检测的人都知道有些翻转和颜色变换会破坏语义比如把左右肺叶翻转、把金属反光调成另一种颜色模型学到的就是假规律。我的经验是先只加最保守的增强看验证集曲线再逐步加码每次只改一个因素。3. 模型结构神经元、激活函数与卷积3.1 神经元、权重、偏置与全连接层神经网络的基本单元是神经元。它做的事情朴素到不能再朴素把输入乘上一组权重加上偏置再经过一个激活函数得到一个输出。用公式写就是 y f(Wx b)。一个神经元能表达的东西很有限但把很多个神经元并排放在一层再把很多层叠起来表达能力就上来了。全连接层指的是这一层的每个神经元都和上一层的所有输出相连。它的参数量是输入维度乘输出维度再加输出维度。举个例子输入 512 维、输出 256 维参数量就是 512×256 256 131328。参数量一旦上万就很容易在小数据集上过拟合这也是为什么图像任务更青睐卷积——卷积通过权重共享把参数量压了下来。权重初始化也不是随便设的。全零初始化会让同一层所有神经元学到完全相同的特征对称性没法打破初始化太大会让激活值爆炸太小又会让信号逐层衰减。现在常用的做法是 He 初始化配合 ReLU或者 Xavier 初始化配合 Tanh 类激活函数。3.2 激活函数为什么 ReLU 成了默认选项没有激活函数的网络无论叠多少层整体仍然是线性的表达能力约等于单层。激活函数引入非线性才让深层网络有意义。早期常用 Sigmoid 和 Tanh它们的输出有界、形状平滑但有个致命问题当输入落在饱和区梯度接近零误差往浅层传的时候会越乘越小出现梯度消失。ReLU 的出现缓解了这个问题正半轴梯度恒为 1计算还特别便宜。它的缺点是负半轴直接归零神经元一旦长期落在负区就可能“死掉”。为了解决这个问题后续出现了 LeakyReLU、PReLU、ELU、GELU 等变体。当前在 Transformer 类模型里GELU 用得很多因为它比 ReLU 更平滑训练稳定性更好。分类任务的最后一层通常用 Softmax把输出变成一组和为 1 的概率二分类也可以用 Sigmoid 输出一个概率值。激活函数主要特点常见场景Sigmoid输出 0 到 1易饱和二分类输出层、门控结构Tanh输出 -1 到 1零中心早期 RNNReLU计算快正区不饱和CNN 默认选择LeakyReLU负区有小斜率缓解神经元死亡GELU平滑梯度性质好Transformer3.3 卷积、池化与感受野CNN 的三个关键词卷积层的核心是卷积核也叫滤波器本质是一个小矩阵比如 3×3 或 5×5。它在图像上滑动每到一个位置就和对应区域做逐元素相乘再求和得到一个输出值。滑动的步长叫 stride边缘补零的圈数叫 padding。输出尺寸可以用公式算输出边长等于 (输入边长 - 卷积核边长 2×padding) / stride 1。卷积最大的优势是参数共享和局部连接。一个 3×3 的卷积核只有 9 个权重无论图像多大它都用这 9 个权重扫全图参数量与图像尺寸无关。同时它只连接局部区域符合图像的空间局部性也能学到平移不变的特征。池化层用来降采样常见的是最大池化和平均池化。2×2、步长 2 的最大池化会把特征图长宽各减半保留每个小区域里最强的响应。它的作用是降低计算量、扩大后续层的感受野、提供一定的平移鲁棒性。现在有些新结构用步长卷积代替池化但池化仍然是理解 CNN 的基础。感受野指的是输出特征图上一个点对应到原始输入上的区域大小。层数越深、卷积核越大、步长越大感受野就越大。理解感受野有助于判断网络到底能不能看到全局信息比如检测大目标时感受野不够就力不从心。3.4 网络层数、参数量与模型容量网络层数通常指带可学习权重的层数比如一个 18 层的残差网络指的是它有 18 个带权重的层。层数增加会提升模型的表达能力也就是容量但不是无脑越深越好。层数太深会遇到梯度消失、训练困难、过拟合等问题残差连接通过跳跃连接让梯度有一条直通通道才让上百层的网络变得可训练。参数量是可学习权重的总数它直接影响显存占用和推理速度。一个实用的估算方法是拿模型结构里每个卷积层的卷积核大小乘输入通道乘输出通道再加上偏置全连接层同样按输入乘输出算。参数量不等于计算量后者通常用 FLOPs 衡量一个参数量小的模型可能因为特征图分辨率高而计算量很大。4. 训练过程损失、梯度、优化器与超参数4.1 损失函数模型怎么知道自己错了损失函数负责把模型输出和真实标签之间的差距变成一个标量训练的目标就是把这个标量压到最小。回归任务常用均方误差也就是预测值与真实值差的平方取平均分类任务常用交叉熵它衡量的是预测概率分布和真实分布之间的差异。二分类可以用二元交叉熵多标签任务里每个标签各自算一次二元交叉熵再加起来。交叉熵配合 Softmax 有个很好的性质梯度形式会化简为预测概率减去真实标签数值稳定、方向明确。这也是为什么分类任务几乎都这么搭。如果任务里正负样本极度不均衡比如正样本只占千分之一普通交叉熵会被负样本主导这时可以用带权重的交叉熵或者 Focal Loss让模型更关注难分的样本。选择损失函数时要盯着业务目标。比如缺陷检测里漏检的代价远高于误检那评估和损失都应该向召回率倾斜而不是只看总体准确率。4.2 反向传播与梯度下降参数是怎么被更新的前向传播把输入一路算到输出反向传播则从损失出发利用链式法则把梯度一层层往回传算出每个参数对损失的偏导数。这个过程不涉及什么神秘智能就是微积分里链式法则的工程化实现框架的自动微分功能帮你把这件事做了。拿到梯度之后就该优化器出场了。最基础的是批量梯度下降用全部样本算一次梯度再更新一次稳但慢。随机梯度下降每次只用一个样本快但抖。实际用的是小批量梯度下降每次用一批样本兼顾效率和稳定性。参数更新公式很朴素新权重等于旧权重减去学习率乘梯度。学习率决定了每次迈多大步。步子太大损失在最低点附近来回震荡甚至发散步子太小收敛慢还容易卡在局部平台。这也是为什么学习率成了最需要反复调的超参数。4.3 学习率、批大小、epoch、iteration 的区别这四个词经常被混用其实各指一件事。batch size一次前向和反向用多少样本。iteration参数更新一次也就是处理完一个批次。epoch把训练集里所有样本完整过一遍。学习率每次更新时参数移动的步长系数。它们的关系可以这样算假设训练集有 50000 张图batch size 设为 100那么一个 epoch 包含 500 次 iteration。训练 30 个 epoch 就是 15000 次参数更新。这几个量之间有耦合。batch size 调大梯度估计更准可以用更大的学习率但显存占用也会上升batch size 太小梯度噪声大训练曲线会很毛躁但有时反而有助于跳出尖锐的极小值。经验上调 batch size 时要同步考虑学习率常见做法是 batch size 翻倍时学习率也适当放大但这不是金科玉律具体要看任务。术语含义影响batch size单次喂入模型的样本数显存占用、梯度稳定性iteration一次参数更新决定训练步数epoch全量数据过一遍决定训练轮数学习率参数更新步长收敛速度和稳定性4.4 优化器演进从 SGD 到 Adam 再到 AdamW朴素 SGD 在所有方向上用同一个学习率遇到不同尺度或不同曲率的方向时效率不高。Momentum 引入了动量把历史梯度累积起来让更新像小球滚下山一样有惯性既能加速也能减少震荡。RMSProp 和 AdaGrad 的思路是给每个参数自适应不同的学习率频繁更新的参数步子小一点稀疏更新的参数步子大一点。Adam 把动量和自适应学习率结合起来还做了偏差修正在大多数任务上开箱即用收敛快因此成了默认选择。Adam 的已知问题是权重衰减的实现方式不够干净L2 正则和自适应学习率混在一起会让衰减效果打折扣。AdamW 把权重衰减从梯度里拆出来单独做现在在 Transformer 训练里基本成了标配。我自己的习惯是如果任务对最终精度极其敏感且有充足调参时间用 SGD 加 Momentum 往往能磨出更好的结果如果追求快速跑通和稳定收敛先上 Adam 或 AdamW。5. 评估与调优判断模型到底能不能用5.1 过拟合与欠拟合训练曲线怎么读训练过程中最常看的是两条曲线训练损失和验证损失。如果两条都在下降且没收敛说明还能继续训如果训练损失一直降但验证损失先降后升那就是过拟合模型开始背训练集的答案了如果两条都降不下去且都很高那是欠拟合模型容量不够或者训练不充分。应对过拟合的手段包括增加数据、数据增强、加正则化、减小模型、早停。应对欠拟合的手段包括加深加宽模型、减少正则化强度、延长训练、检查标签和输入是否有问题。我见过不少人一遇到验证集效果差就无脑加数据增强结果发现其实是学习率设得太大导致训练根本没收敛方向完全跑偏。先看曲线形态再决定动哪里这个顺序别搞反。5.2 正则化L2、Dropout、早停与批归一化L2 正则是在损失里加上权重平方和的惩罚项让权重倾向于变小模型更平滑。L1 正则则倾向于把部分权重压到零能起到稀疏作用适合做特征选择。Dropout 在训练时随机把一部分神经元的输出置零相当于每次训练一个不同的子网络推理时再全部打开。它强迫网络不依赖某几个特定神经元能有效缓解过拟合。注意 Dropout 只在训练阶段启用推理阶段要关掉框架里用 model.train() 和 model.eval() 切换。早停是盯着验证集指标连续若干轮不再提升就停止训练并回滚到最好的那一版权重。它简单、几乎零成本是性价比最高的正则手段之一。批归一化BatchNorm对每层的输入做标准化能加速收敛、允许更大的学习率还带一点正则效果。但它依赖批次的统计量batch size 特别小的时候表现会变差这时可以换 LayerNorm 或 GroupNorm。顺带说一句BatchNorm 在训练和推理时的行为不同训练用当前批次的均值和方差推理用训练阶段累积的滑动平均切换模式时千万别漏。5.3 评估指标别只盯着准确率准确率是最直观的指标但在类别不均衡时会骗人。一个把全部样本都判为负类的模型在正样本只占 1% 的数据上也能拿到 99% 的准确率显然没有意义。更细的指标来自混淆矩阵真正例、假正例、真负例、假负例。精确率是判为正的样本里真正为正的比例召回率是真正的正样本里被找出来的比例F1 是两者的调和平均。目标检测里还会用 IoU 衡量预测框和真实框的重叠程度用 mAP 综合不同类别和不同置信度阈值下的表现。分割任务常用 Dice 系数和 IoU。语音和图像生成任务里还有 PSNR、SSIM 这类指标。选指标的原则是让它贴近业务成本。医学筛查更看重召回率宁可多报也不能漏垃圾内容拦截可能更看重精确率避免误伤正常内容。5.4 迁移学习与预训练小数据集的最优解从头训练一个深层网络需要大量数据和算力现实中很多任务根本没有这个条件。迁移学习的思路是先拿一个在大规模数据上预训练好的模型把它的权重作为起点。常见做法有两种一是冻结主干网络只训练最后的新分类头适合数据量很小的场景二是解冻部分或全部层做微调用较小的学习率适合数据量中等偏上的场景。微调时学习率要调小通常是从头训练时的十分之一到几十分之一因为预训练权重已经比较好了大步长会把它们破坏掉。另外要注意替换分类头之后新头的参数量级和初始化方式会影响训练初期的稳定性可以先用几轮只训新头再解冻主干。预训练模型使用的归一化参数和输入尺寸最好保持一致否则分布偏移会削弱迁移效果。6. 环境配置把术语落到可运行的工程6.1 框架选择PyTorch、TensorFlow 与工业工具学术和教学场景里PyTorch 目前占据主流动态图写起来直观调试方便配合 Python 生态很顺手。TensorFlow 在工业部署和移动端有成熟链路Keras 接口对新手友好。选择哪个主要看你所在团队的技术栈和要交付的形态。除了通用框架还有一些面向特定场景的工具。比如工业视觉里常见的 Halcon 深度学习工具它把训练和推理封装进一套面向工程的接口适合产线上的缺陷检测和定位任务好处是部署链路短、和现有视觉流程衔接顺代价是灵活度不如通用框架网络结构基本固定。再比如 MATLAB 的深度学习工具箱适合教学演示和算法验证省去环境折腾但不适合大规模训练。选工具时先问自己三个问题数据规模多大、要不要自己改网络结构、最终部署在什么设备上。6.2 驱动、CUDA、cuDNN 与框架版本的关系显卡要参与计算需要装显卡驱动。框架要用显卡需要 CUDA 运行时而 cuDNN 是面向深度学习的加速库提供了卷积、池化等算子的高效实现。它们之间是层层依赖的关系驱动版本决定支持的 CUDA 版本上限CUDA 版本要和框架版本匹配cuDNN 版本要和 CUDA 版本匹配。任何一个对不上轻则跑不起来重则报一堆看不懂的符号错误。最省心的做法是用 conda 或虚拟环境隔离项目按官方文档给出的版本组合来装。安装时不一定要在系统里装完整 CUDA 工具包很多时候装框架自带的运行时就够了。装完之后用一行代码验证import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0))如果 is_available 返回 False先排查驱动再排查框架版本最后排查是不是装成了 CPU 版。这个顺序能省掉大量瞎试的时间。6.3 显存估算与常见省显存手段显存主要被四类东西占用模型参数、参数梯度、优化器状态、中间激活值。前三个大致和参数量成正比Adam 会为每个参数额外保存一阶和二阶动量所以它比 SGD 更吃显存。中间激活值的占用和 batch size、特征图分辨率、网络深度都有关往往是峰值占用的主要来源。一个粗略的估算是混合精度训练下每个参数大约需要 16 到 20 字节其中参数本身 2 到 4 字节梯度、优化器状态各占若干。一个一亿参数的模型光参数和优化器状态就可能吃掉好几 GB再加上激活值很容易撑爆消费级显卡。省显存的常用手段有减小 batch size、使用混合精度、梯度累积、梯度检查点、及时释放中间变量。梯度累积特别实用它用多个小批次累积梯度再更新一次效果接近大 batch但峰值显存只按小批次算。# 梯度累积示意4 个小批次等效于 1 个大批次 accum_steps 4 for i, (inputs, labels) in enumerate(loader): outputs model(inputs) loss criterion(outputs, labels) / accum_steps loss.backward() if (i 1) % accum_steps 0: optimizer.step() optimizer.zero_grad()注意用了梯度累积后学习率也要按等效 batch size 重新考虑否则更新幅度会和预期不一致。7. 常见问题速查与避坑心得7.1 术语速查表一页纸记住核心概念术语一句话解释张量多维数组框架里的统一数据格式前向传播输入经过网络算出预测值损失函数衡量预测与真实标签差距反向传播用链式法则从损失回传梯度学习率参数每次更新的步长batch size一次喂入模型的样本数epoch全量数据完整过一遍iteration一次参数更新过拟合训练集表现好、验证集表现差正则化抑制过拟合的一系列手段激活函数给网络引入非线性卷积核在图像上滑动提取局部特征的权重感受野输出点对应到输入上的区域大小迁移学习用预训练权重初始化新任务微调用较小学习率继续训练预训练模型7.2 新手最容易踩的坑我一条条踩过第一条忘了清零梯度。框架默认会把梯度累加如果你在每次反向传播前不调用 zero_grad梯度就会越加越大训练很快发散。正确顺序是先清零、再前向、再算损失、再反向、再更新。第二条训练和推理模式没切换。Dropout 和 BatchNorm 在两种模式下行为不同评估时忘记 model.eval() 会让验证指标忽高忽低还找不到原因。第三条学习率一开始设太大。损失曲线一上来就爆成 NaN十有八九是学习率过大或者数据没归一化。排查顺序是先降学习率再查输入范围再看有没有除零。第四条验证集和训练集做了同样的随机增强。验证集应该用确定性的预处理只做尺寸缩放和归一化不要做随机翻转裁剪否则每次评估结果都在变没法比较。第五条把通道顺序搞反。图像读进来是 (H, W, C)框架要 (C, H, W)中间少了 permute 这一步网络照样能跑但学到的东西完全错位准确率上不去还查不出原因。第六条盲目加大模型。数据量不够时加大模型只会更快过拟合。先把数据质量和增强做扎实再考虑加容量。第七条只看训练损失。训练损失降得很漂亮不代表模型能用一定要盯验证集指标并且固定一套评估流程避免指标口径变来变去。第八条忽略随机种子。不做对比实验时无所谓一旦要比较两个方案不固定种子就会让差异被随机性淹没。我习惯在实验脚本开头固定 Python、NumPy 和框架的随机种子并记录在实验日志里。第九条显存爆了就直接砍模型。先看是不是 batch size 或输入分辨率太大混合精度和梯度累积往往能救回来没必要一上来就动结构。第十条环境版本随便升。深度学习生态里版本兼容性很脆弱一次不经意的升级可能让整个项目跑不起来。用虚拟环境隔离把版本写进依赖文件别嫌麻烦。7.3 从术语到项目的学习路径建议如果你现在处于刚学完概念、想动手的阶段我给一条比较顺的路径。先用一个结构化数据集跑通全连接网络重点理解训练循环的每一步然后换到图像数据集手写一个简单的 CNN理解卷积、池化和张量形状的变化接着用预训练模型做一次迁移学习体会微调的价值最后挑一个完整项目把数据划分、增强、训练、评估、推理串起来。每学一个概念就回到代码里找它对应的那一行。比如学了学习率就在优化器那一行改改数值看曲线变化学了 Dropout就在模型里加一层再对比验证集表现。术语只有和代码、曲线、结果绑在一起才会真正变成你自己的东西。这也是我一直推荐看吴恩达那套课程配合动手写代码的原因概念讲得清楚配套练习也足够轻量适合用来打地基。最后分享我自己在调参上的一个习惯任何一次实验只改一个变量并且在日志里写清楚改了什么、为什么改、结果如何。听着很笨但当你回头复盘时这份日志就是最值钱的东西比任何网上的参数推荐都靠谱。模型的效果从来不是靠某个神奇超参数堆出来的而是靠对每个术语背后机制的理解一点点试出来的。