
上一篇文章我们系统学习了 ANN 的网络结构、激活函数、参数初始化和损失函数走完了前向传播的完整路径。但有一个关键问题还没回答——网络是怎么学习的答案就是反向传播Backpropagation。如果说前向传播是数据正向走一遍得到预测那么反向传播就是误差反向走一遍修正参数。没有反向传播神经网络就只是一个固定的函数根本学不到任何东西。今天这篇文章我们走完 ANN 的另一半核心从反向传播的原理出发理解梯度是怎么算出来的再看参数如何沿着梯度的反方向更新系统梳理六大常用优化器的原理与选型接着学习四种正则化手段解决过拟合问题最后用一个 MNIST 手写数字识别的完整案例把所有知识串起来。这是从理解神经网络结构到能动手训练模型的完整一跃。十、反向传播神经网络的学习引擎什么是反向传播定义反向传播是利用链式法则计算出神经网络每一层参数的梯度然后利用梯度更新参数使损失逐步减小的过程。这句话里有三个关键词链式法则、梯度、更新参数。我们逐一拆解。链式法则是微积分里的概念——对于复合函数求导可以把每层函数的导数乘起来。神经网络的前向传播就是一个大的复合函数输入经过第一层、再经过第二层……最后得到 loss。反向传播就是把这个复合函数的导数从后往前一层一层地算出来。梯度是每个参数的偏导数组成的向量它告诉我们这个参数往哪个方向动loss 会增加得最快。知道了梯度我们把参数沿着梯度的反方向挪一点点loss 就会下降一点点——这就是梯度下降。所以反向传播的本质就是从 loss 出发从后往前用链式法则把每一层每个参数的梯度都算出来。有了梯度后面的参数更新就水到渠成了。反向传播的三步流程前向传播 x → 隐藏层1 → 隐藏层2 → 输出 → loss 反向传播 ← ← ← ← ← ← 梯度逐层传递逐层计算反向传播可以概括为三步第一步从输出层开始计算梯度。先用损失函数算出预测值和真实值的误差再求损失函数对输出层输入的梯度。这是反向传播的起点——误差从这里开始往回传。第二步逐层向前传播梯度。从输出层往输入层的方向一层一层地计算。每一层做两件事一是算出本层每个参数w 和 b的梯度二是算出要传给上一层的梯度即损失对本层输入的梯度。这样一层一层往前传直到输入层。第三步计算完成。所有参数的梯度都算出来了存在各自的.grad属性中等待优化器来更新。计算图的概念PyTorch 的自动微分是基于计算图实现的。什么是计算图就是把前向传播的每一步运算用一张图表示出来——节点是张量边是运算。举个简单的例子y w * x b对应的计算图是w ──→ [*] ──→ [] ──→ y x ──→ ↑ ↑ b前向传播时PyTorch 边计算边构建这张图。调用loss.backward()时PyTorch 从 loss 节点出发沿着计算图的边反向走每经过一条边就乘上这条边对应的导数最后到达每个参数节点时就得到了该参数的梯度。这就是自动微分的工作原理。计算图是动态构建的——每一轮前向传播都重新构建一张新的图。这也是 PyTorch 被称为动态图框架的原因。反向传播的特点第一方向和前向传播相反。前向传播从前往后反向传播从后往前。一前一后构成一个完整的训练循环。第二依赖前向传播的结果。反向传播需要用到前向传播中每一层的输出值激活值因为求导的时候要代入。所以前向传播时PyTorch 会把中间结果缓存下来供反向传播使用。第三梯度可以累加。上一篇文章提到过多次调用.backward()梯度会累加。这是 PyTorch 的设计——既方便了梯度累积用小 batch 模拟大 batch也要求我们记得每次训练前清零梯度。十一、更新参数梯度下降的三种形态算出梯度之后下一步就是用梯度来更新参数。最基本的方法是梯度下降但梯度下降也有不同的口味——区别在于每轮更新用多少数据。三种梯度下降对比全量梯度下降BGD 随机梯度下降SGD 小批量梯度下降Mini-batch ───────────────── ────────────────── ────────────────────── 每次用全部数据 每次用1条数据 每次用一小批数据如32条 更新稳定但慢 更新快但震荡大 兼顾速度与稳定方法每次使用数据量优点缺点适用场景全量梯度下降 BGD全部样本收敛稳定梯度准确计算慢内存压力大小数据集随机梯度下降 SGD1 条样本更新快适合大数据震荡大不稳定很少直接使用小批量梯度下降 Mini-batch一小批32/64/128兼顾速度与稳定最常用需要选 batch_size深度学习默认选择全量梯度下降Batch Gradient Descent每轮把所有数据都跑一遍算出总梯度后再更新一次参数。优点是梯度准确、下降稳定缺点是数据量大的时候慢得离谱而且内存可能装不下。随机梯度下降Stochastic Gradient Descent每来一条数据就算一次梯度、更新一次参数。优点是更新快、适合在线学习缺点是单条数据的梯度噪声大参数更新方向飘忽不定loss 曲线震荡剧烈。小批量梯度下降Mini-batch Gradient Descent每次取一小批数据比如 32 条算这批的平均梯度然后更新一次参数。这是前两者的折中——既比全量快很多又比单条稳定是深度学习中最常用的方式。我们平时说的SGD很多时候其实指的是小批量 SGD。参数更新公式不管哪种梯度下降参数更新的公式都是一样的w w - lr × ∂L/∂w b b - lr × ∂L/∂b其中lr是学习率∂L/∂w是损失对权重的梯度。减号表示沿着梯度的反方向走——因为梯度指向 loss 增加最快的方向反方向就是 loss 减少最快的方向。学习率的选择很关键太大容易震荡甚至发散太小收敛太慢。这是调参时第一个要关注的超参数。十二、优化器让梯度下降更聪明基础的 SGD 虽然简单但有不少问题——遇到狭长的山谷震荡剧烈、对所有参数一视同仁、不会根据情况调整学习率。为了解决这些问题研究者们提出了各种改进的优化算法也就是优化器。PyTorch 把这些优化算法都封装好了使用时只需一行optimizer torch.optim.XXX(model.parameters(), lr...)。但想要用好它们得先理解每个优化器的原理和特点。SGD随机梯度下降特点最基础的优化器每次用当前 mini-batch 的梯度更新参数。optimizer torch.optim.SGD(model.parameters(), lr0.01)优点结构简单容易理解每个batch速度快占用内存小有一定的随机性可能有助于跳出局部最优缺点学习率是全局的所有参数用同一个学习率收敛速度慢容易在梯度小的方向停滞在梯度方向变化剧烈的地方震荡严重适用场景小数据集、简单模型、或者想自己精细控制训练过程时使用。Momentum动量法特点在 SGD 的基础上加入了动量——就像小球从山上滚下来越滚越快。它记录了历史梯度的加权平均通常用指数移动平均当前梯度加上历史动量共同决定更新方向和幅度。optimizer torch.optim.SGD(model.parameters(), lr0.01, momentum0.9)优点加速收敛特别是在梯度方向一致的维度减小震荡在梯度方向来回变的地方更稳定有助于跳出局部最优缺点多了一个超参数 β动量系数需要调速度太快可能冲过最优点动量系数通常设为 0.9意思是保留 90% 的历史动量加上 10% 的新梯度。NesterovNAG涅斯捷罗夫加速梯度特点Momentum 的改进版。Momentum 是先算当前梯度再加动量Nesterov 是先按动量往前迈一步再在那个位置算梯度最后加动量。相当于有了前瞻性——先看看前面的情况再决定怎么走。optimizer torch.optim.SGD(model.parameters(), lr0.01, momentum0.9, nesterovTrue)优点比 Momentum 更聪明减少冲过最优点的情况收敛更快更稳定缺点计算稍微复杂一点实际效果提升不一定很明显Nesterov 在理论上比 Momentum 更好但在深度学习的实践中两者差别不大很多时候 Momentum 就够用了。Adagrad自适应梯度特点每个参数有自己的学习率。它累积每个参数历史梯度的平方和学习率除以这个累积值——梯度大的参数学习率降得快梯度小的参数学习率降得慢。这样每个参数能根据自己的情况自适应调整学习率。optimizer torch.optim.Adagrad(model.parameters(), lr0.01)优点自适应学习率不同参数不同对待对稀疏数据效果好不常出现的特征梯度小学习率降得慢缺点学习率一直在衰减训练到后期学习率可能太小模型学不动了初始梯度大的话学习率降得太快Adagrad 的核心问题是学习率单调递减——越训越慢后期几乎不动。后面的 RMSprop 和 Adam 就是为了解决这个问题。RMSprop均方根传播特点在 Adagrad 的基础上做了改进——用指数移动平均来累积梯度平方而不是全部累加。这样早期的梯度会逐渐被遗忘近期的梯度更重要学习率不会一直衰减下去。optimizer torch.optim.RMSprop(model.parameters(), lr0.001, alpha0.99)优点解决了 Adagrad 学习率单调递减的问题自适应学习率适合非平稳目标在 RNN 等模型上表现不错缺点多了一个超参数 α通常设 0.9还是依赖全局学习率RMSprop 和 Adagrad 的关系就像 EMA 和普通累加的关系——一个会遗忘历史一个不会遗忘。Adam自适应矩估计特点Momentum RMSprop 的结合体。它同时维护两个指数移动平均值一阶矩梯度的均值类似动量和二阶矩梯度平方的均值类似 RMSprop。然后用这两个值来自适应调整每个参数的学习率。optimizer torch.optim.Adam(model.parameters(), lr0.001, betas(0.9, 0.999))优点结合了动量和自适应学习率的双重优势收敛快效果稳定对不同问题鲁棒性好调参成本低最常用的万能优化器缺点超参数多β1、β2、ε虽然默认值通常就很好有时候在某些任务上泛化性不如精心调过的 SGDMomentumAdam 几乎是现在深度学习的默认选择——如果你不知道用什么优化器先用 Adam 试试通常不会太差。怎么选优化器一张决策表优化器核心思想学习率收敛速度稳定性推荐指数SGD基础梯度下降全局固定慢一般★★Momentum加动量加速全局固定中较好★★★Nesterov前瞻性动量全局固定中快较好★★★Adagrad历史梯度平方累积自适应递减中好★★RMSprop指数平均梯度平方自适应稳定快好★★★★Adam动量 RMSprop 结合自适应最快很好★★★★★实用建议不知道用什么先试 Adam。学习率设 0.001大多数情况下都能跑起来效果还不错。追求最终精度试试 SGD Momentum。虽然收敛慢但如果调参得当最终泛化效果可能比 Adam 更好。稀疏数据 / 词嵌入Adagrad 或 RMSprop 效果通常不错。RNN 系列模型RMSprop 和 Adam 都是常用选择。最终建议先用 Adam 快速迭代验证想法确认模型没问题后如果想刷精度再换成 SGDMomentum 慢慢调。十三、正则化给模型戴上紧箍咒什么是过拟合在讲正则化之前先回顾一下过拟合。训练误差 ↘ ↗ 泛化误差 ↘ ↗ ↘ ↗ ↘ ↗ ↙ 最低点 训练轮数过拟合就是模型在训练集上表现越来越好但在测试集上先变好后变差。模型把训练数据的细节甚至噪声都记住了学到的不是通用规律而是背诵了训练集。换一批没见过的数据表现立刻跳水。深度学习模型参数多、容量大天生就容易过拟合。正则化就是一系列防止过拟合的技术核心思想是给模型增加约束降低它的自由度让它只能学到真正有用的规律。下面介绍四种最常用的正则化方法。L1 / L2 正则化核心思想在损失函数后面加一个惩罚项让权重不能太大。L2 正则化也叫权重衰减Weight Decay的损失函数总损失 原始损失 λ × (w₁² w₂² ... wₙ²)L1 正则化的损失函数总损失 原始损失 λ × (|w₁| |w₂| ... |wₙ|)其中 λ 是正则化强度——λ 越大惩罚越重模型越保守。L2 正则化惩罚权重的平方和。它让所有权重都变得比较小因为大权重会带来很大的惩罚。权重小了模型对输入的微小变化就不敏感泛化能力自然更强。L2 是最常用的正则化方式。为什么权重小了就能防止过拟合直觉上的解释是如果权重很小输入的微小变化不会导致输出剧烈变化模型更平滑。而如果权重很大一点点输入扰动就能让输出跳来跳去模型对噪声过于敏感。L2 正则化就是通过惩罚大权重强制模型走平滑路线从而提升泛化能力。L1 正则化惩罚权重的绝对值。它有一个特殊效果——会让很多权重变成 0相当于自动做了特征选择只保留最重要的特征。如果你的数据特征很多但大部分没用L1 可能更合适。两者对比方法惩罚形式效果特点L2 正则化权重平方和权重都变小更常用计算方便L1 正则化权重绝对值和很多权重变0稀疏化自动特征选择PyTorch 中的使用也很简单优化器自带weight_decay参数# L2 正则化weight_decay 就是 λ optimizer torch.optim.Adam(model.parameters(), lr0.001, weight_decay0.0001)一行代码就搞定了。weight_decay的值通常很小比如 0.0001 或 0.001——太大了模型会欠拟合。Dropout随机丢弃神经元核心思想训练的时候随机让一部分神经元暂时死掉输出设为 0迫使模型不能依赖任何单个神经元从而学习更鲁棒的特征。训练时随机丢弃 测试时全部使用 ○ ○ ○ ○ ○ ○ ○ ● ○ ○ ○ ○ ● ○ ● → ○ ○ ○ ○ ○ ○ ○ ○ ○ ● 表示被丢弃的神经元Dropout 的工作方式很巧妙训练时随机丢测试时全开。就像军训时每次随机抽几个人休息剩下的人必须顶上——这样每个人都得学会所有技能不能指望别人。Dropout 有一个参数 p表示神经元被丢弃的概率。比如 p0.5 就是每个神经元有 50% 的概率被丢掉。p 越大正则化效果越强但太大了模型学不到东西通常设 0.2 ~ 0.5。PyTorch 中使用 Dropout 非常简单import torch.nn as nn class Net(nn.Module): def __init__(self): super().__init__() self.fc1 nn.Linear(784, 256) self.dropout1 nn.Dropout(p0.3) # 30%的神经元被丢弃 self.fc2 nn.Linear(256, 128) self.dropout2 nn.Dropout(p0.3) self.fc3 nn.Linear(128, 10) self.relu nn.ReLU() def forward(self, x): x self.relu(self.fc1(x)) x self.dropout1(x) # 在激活之后加 Dropout x self.relu(self.fc2(x)) x self.dropout2(x) x self.fc3(x) return x注意 Dropout 在model.train()和model.eval()下的行为不一样训练时生效测试时自动关闭。所以别忘了在验证和测试时调用model.eval()。Dropout 还有一个有趣的特性——它相当于做了模型集成。每次随机丢弃不同的神经元相当于训练了一个不同的子网络。测试时把所有神经元都用上相当于把这些子网络的预测结果做了平均。这和随机森林的集成思想异曲同工——一个模型训练多个模型投票效果自然更好。早停Early Stopping核心思想训练过程中盯着验证集的表现一旦验证集性能不再提升就提前停止训练。性能 ↑ 训练集 . │ . ↗ │ . ↗ │ . ↗ ← 验证集达到最优停止训练 │ .↗.↘ │ ↗ . ↘ │ ↗ . ↘ └────────────────→ 训练轮数 最优epoch道理很简单——模型刚开始训练时训练误差和验证误差都在下降但当过拟合开始发生时训练误差还在降验证误差反而开始上升。早停就是在验证误差开始上升的那个点踩刹车把那个时候的模型保存下来。早停的实施步骤把数据分成训练集和验证集每训练一轮epoch在验证集上评估一次如果验证集性能比之前最好的还好就保存当前模型如果连续很多轮叫 patience验证集都没提升就停止训练PyTorch 中没有内置的早停功能但实现起来很简单best_val_loss float(inf) patience 10 # 容忍多少轮不提升 counter 0 for epoch in range(100): train(...) val_loss validate(...) if val_loss best_val_loss: best_val_loss val_loss torch.save(model.state_dict(), best_model.pth) counter 0 else: counter 1 if counter patience: print(早停模型不再提升) break早停是最简单也最有效的正则化手段之一——几乎没有额外计算开销效果还很好。实际项目中早停几乎是标配。数据增强Data Augmentation核心思想不增加数据采集成本通过对现有数据做各种变换人造出更多训练数据。数据越多模型越难记住所有样本泛化能力自然就提升了。数据增强在图像领域最常用常见的变换方式变换方式说明示例随机旋转图像旋转一定角度旋转 ±15°随机翻转水平或垂直翻转左右翻转随机缩放放大或缩小缩放 0.8~1.2 倍随机裁剪随机裁剪一部分再缩放回原尺寸随机裁剪亮度/对比度变化调整图像的亮度和对比度亮度 ±20%加噪声给图像加随机噪声高斯噪声PyTorch 的torchvision库提供了丰富的数据增强工具from torchvision import transforms transform transforms.Compose([ transforms.RandomHorizontalFlip(p0.5), # 随机水平翻转 transforms.RandomRotation(15), # 随机旋转 ±15度 transforms.RandomResizedCrop(224), # 随机裁剪再缩放 transforms.ColorJitter(brightness0.2, contrast0.2), # 颜色抖动 transforms.ToTensor(), transforms.Normalize(mean[0.5], std[0.5]) ])数据增强的好处是只增加训练时间不增加推理时间——因为推理的时候不需要做增强。它是提升模型泛化能力的免费午餐。需要注意的是数据增强不是越猛越好。增强的程度要和实际场景匹配——比如你识别的是正常的手写数字就没必要把图片旋转 90 度因为现实中没人把数字倒着写。增强过度反而会让模型学不到正确的模式甚至损害性能。正则化方法总结方法原理优点缺点适用场景L2 正则化惩罚大权重简单一行代码效果有限几乎所有场景Dropout随机丢弃神经元效果好灵活训练变慢全连接层后常用早停验证集不升就停零成本效果好需要验证集所有训练场景标配数据增强人工扩充数据提升明显不影响推理只增加训练时间图像数据首选实战建议这几种方法不是互斥的通常组合使用效果最好。比如 L2 Dropout 早停 数据增强四管齐下过拟合基本就不是问题了。十四、实战案例手写数字识别理论讲了这么多是时候动手了。我们用经典的 MNIST 手写数字识别数据集把前面学到的所有知识串起来数据加载 → 模型搭建 → 损失函数 → 优化器 → 训练循环 → 正则化 → 测试评估。MNIST 数据集包含 60,000 张训练图片和 10,000 张测试图片每张是 28×28 的灰度手写数字0-9。任务就是让模型识别图片中的数字是几。完整代码import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader from torchvision import datasets, transforms from torch.utils.tensorboard import SummaryWriter # 1. 数据准备 transform transforms.Compose([ transforms.ToTensor(), # 转 Tensor transforms.Normalize((0.1307,), (0.3081,)) # 标准化MNIST的均值和标准差 ]) train_dataset datasets.MNIST(root./data, trainTrue, downloadTrue, transformtransform) test_dataset datasets.MNIST(root./data, trainFalse, downloadTrue, transformtransform) train_loader DataLoader(train_dataset, batch_size64, shuffleTrue) test_loader DataLoader(test_dataset, batch_size1000, shuffleFalse) # 2. 模型搭建带 Dropout 正则化 class ANN(nn.Module): def __init__(self): super().__init__() self.fc1 nn.Linear(28 * 28, 256) self.fc2 nn.Linear(256, 128) self.fc3 nn.Linear(128, 10) self.relu nn.ReLU() self.dropout nn.Dropout(0.3) # Dropout 正则化 def forward(self, x): x x.view(-1, 28 * 28) # 展平[64, 1, 28, 28] → [64, 784] x self.relu(self.fc1(x)) x self.dropout(x) x self.relu(self.fc2(x)) x self.dropout(x) x self.fc3(x) return x model ANN() # 3. 损失函数和优化器带 L2 正则化 criterion nn.CrossEntropyLoss() optimizer optim.Adam(model.parameters(), lr0.001, weight_decay1e-4) # L2正则化 # 4. TensorBoard writer SummaryWriter(runs/mnist_ann) # 5. 训练循环带早停 best_acc 0.0 patience 5 counter 0 epochs 50 for epoch in range(epochs): # --- 训练阶段 --- model.train() train_loss 0 for batch_idx, (data, target) in enumerate(train_loader): optimizer.zero_grad() # 1. 梯度清零 output model(data) # 2. 前向传播 loss criterion(output, target) # 3. 计算损失 loss.backward() # 4. 反向传播 optimizer.step() # 5. 参数更新 train_loss loss.item() train_loss / len(train_loader) # --- 测试阶段 --- model.eval() test_loss 0 correct 0 with torch.no_grad(): for data, target in test_loader: output model(data) test_loss criterion(output, target).item() pred output.argmax(dim1, keepdimTrue) # 取概率最大的类别 correct pred.eq(target.view_as(pred)).sum().item() test_loss / len(test_loader) accuracy 100. * correct / len(test_loader.dataset) # 记录到 TensorBoard writer.add_scalar(Loss/Train, train_loss, epoch) writer.add_scalar(Loss/Test, test_loss, epoch) writer.add_scalar(Accuracy/Test, accuracy, epoch) print(fEpoch {epoch1}: 训练Loss{train_loss:.4f}, f测试Loss{test_loss:.4f}, 准确率{accuracy:.2f}%) # --- 早停 --- if accuracy best_acc: best_acc accuracy torch.save(model.state_dict(), best_mnist_model.pth) counter 0 print(f 模型已保存当前最高准确率{best_acc:.2f}%) else: counter 1 if counter patience: print(f 早停连续{patience}轮未提升) break print(f\n训练完成最高测试准确率{best_acc:.2f}%) writer.close()代码解读这段代码虽然长但每一部分都对应着我们学过的知识点数据准备用torchvision.datasets.MNIST加载数据集做了 ToTensor 和 Normalize 两个变换。Normalize 用的是 MNIST 数据集的全局均值和标准差这是预处理的标准操作——把数据变成均值 0、方差 1 的分布训练更稳定。DataLoader 的 batch_size 设为 64是一个比较经典的选择——太小了训练慢太大了显存不够。shuffleTrue让每个 epoch 打乱数据顺序防止模型记住数据的排列顺序。模型结构三层全连接网络中间夹着 ReLU 激活和 Dropout。输入层 78428×28→ 隐藏层1 256 → 隐藏层2 128 → 输出层 1010个数字类别。注意x.view(-1, 28*28)把二维图片展平成一维向量这是全连接网络处理图像数据的标准操作。损失函数与优化器多分类用CrossEntropyLoss优化器选 Adam学习率 0.001加了weight_decay1e-4做 L2 正则化。这里同时用了 Dropout 和 L2 两种正则化手段双管齐下。训练循环标准的五步循环——清零梯度 → 前向传播 → 算损失 → 反向传播 → 更新参数。注意训练前model.train()测试前model.eval()这个切换不能忘。测试评估用torch.no_grad()包裹不计算梯度节省内存。output.argmax(dim1)取出概率最大的类别作为预测结果和真实标签对比算出准确率。早停机制每轮测试后看准确率有没有创新高有就保存模型连续 5 轮没提升就停止训练防止过拟合。TensorBoard把训练 loss、测试 loss、测试准确率都记录下来训练过程中可以实时观察曲线变化。如果 loss 曲线下降平滑、准确率稳步上升说明训练正常如果测试 loss 先降后升说明过拟合了需要加大正则化或提前停止。对于 MNIST 这样的简单数据集一个三层的全连接网络加上适当的正则化测试准确率通常能达到97% 以上。虽然比不上 CNN 的 99%但作为 ANN 的入门实战这个结果已经足够说明问题了。十五、学习心得与建议第一反向传播是深度学习的引擎。前向传播是计算反向传播是学习。没有反向传播神经网络只是一个固定的函数有了反向传播神经网络才有了学习的能力。理解了链式法则和计算图你就理解了 PyTorch 自动微分的底层原理遇到梯度相关的问题也能更好地排查。第二优化器没有绝对的好坏只有适不适合。初学者可能会问哪个优化器最好但这个问题没有标准答案。Adam 最省心SGD 潜力最大Momentum 是经典选择。重要的是理解每个优化器的核心思想和适用场景根据具体任务做出选择。第三正则化是深度学习的基本功。不会正则化就等于不会调模型——因为深度学习模型天生容易过拟合。L2、Dropout、早停、数据增强这四个是最常用的必须掌握。实际项目中通常组合使用效果叠加。其中早停是性价比最高的——零成本效果好几乎是标配。第四动手跑一个完整案例胜过看十篇文章。MNIST 是深度学习的Hello World但麻雀虽小五脏俱全——数据加载、模型搭建、训练循环、正则化、评估该有的都有了。把这个案例跑通、调通、理解透你就具备了动手做深度学习项目的基础能力。写在最后两篇文章把 ANN 的知识体系完整地串了起来。上篇讲的是网络是什么样的——结构、神经元、激活函数、初始化、损失函数核心是前向传播。这篇讲的是网络是怎么学习的 怎么用得好——反向传播算梯度、梯度下降更新参数、优化器让更新更聪明、正则化防过拟合、实战案例串起全部知识核心是反向传播 参数优化 正则化 实战。前向传播和反向传播合在一起就是神经网络训练的完整故事。从数据输入到预测输出从误差计算到参数更新从过拟合防治到完整实战每一环都有它的位置每一步都有它的道理。ANN 是所有深度学习模型的基础。后面学 CNN、RNN、Transformer变化的只是网络结构和连接方式——前向传播、反向传播、损失函数、优化器、正则化这些核心机制都是通用的。把 ANN 学透了后面学任何模型都只是换个结构同样的训练流程。深度学习的大门已经打开里面的世界很精彩。一步一步来你也能成为那个驾驭模型的人。