My Blog
Agent 学习

Agent 学习第 2 周:深度学习原理

从损失函数、梯度下降到反向传播,手敲四个小脚本加一个多分类作业,把深度学习的数学地基打牢。

发布于 2026/9/11更新于 2026/9/11阅读约 13 分钟
只问这篇文章 →

第二周从数学基础一路讲到反向传播。这是整个课程里公式最密集的一周,但也是最该硬啃的一周——后面所有内容都建立在这套东西上。

我这周写了四个小脚本(均方误差、交叉熵、全连接层、训练过程),最后做了一个多分类任务的作业。手敲一遍公式再看代码,比只看 PPT 强太多。


一、够用就行的数学

课上讲得很克制,只讲深度学习真正用得上的那几个:

概念一句话
向量有序数值列表,既有大小又有方向
内积`a·b =
矩阵乘法(m×n)×(n×p)=(m×p),左矩阵列数必须等于右矩阵行数
导数某点的斜率/瞬时变化率
链式法则dy/dx = dy/du · du/dx
梯度所有偏导数组合成的向量

内积那条后面会反复用到——余弦相似度、Attention 的 QK^T,本质都是内积。cosθ=1 是同向,0 是垂直无关,-1 是反向。

链式法则则是反向传播的全部数学基础,就这一个公式。


二、「学习」到底是什么

这一节把整件事说透了。

从找极小值说起

先看一个纯数学问题:怎么找函数的极小值?

任取一点 → 算导数 → 根据正负决定调大还是调小 → 迭代直到不再变化

然后做一个替换:

  • 把 x 换成模型权重 W、b
  • 把 f(x) 换成损失函数

这就是深度学习的训练过程。 所谓「学习」,就是不断调整参数 W,让预测尽量接近真实答案。

损失函数:两种就够了

回归 → 均方误差 MSE = (ŷ - y)²
分类 → 交叉熵      = -Σ yᵢ·log(ŷᵢ)

我写 上午学习-均方误差.py 和 下午学习-交叉熵损失.py 就是把这两个手算了一遍,再和 PyTorch 的实现对比,确认数值一致。

这里有个后面会反复踩的坑:PyTorch 的 CrossEntropyLoss 内部自带 softmax。如果你在模型的 forward 里已经做了 softmax,再送进这个损失函数就等于做了两次,训练会很奇怪但不报错。

梯度下降

W ← W − η·∇L(W)

沿负梯度方向更新参数。学习率 η 是这里唯一的超参数,但影响巨大:

  • 太大 → 震荡甚至发散
  • 太小 → 收敛极慢
  • 合适 → 平稳收敛

反向传播

神经网络本质是多层复合函数,所以用链式法则从损失开始逐层往回算梯度。

前向传播:算预测和损失
反向传播:算梯度
更新参数:梯度下降

一句话总结:深度学习训练 = 梯度下降 + 反向传播。每次迭代就是这三步循环。


三、神经网络的基本构件

全连接层

y = Wx + b

多个全连接层堆叠就是多层感知机(MLP),层数越深表达能力越强。

我在 下午学习-全连接层.py 里手写了一个,和 nn.Linear 对比输出,主要是确认自己理解了矩阵的形状怎么变。

激活函数:为什么必须有

这个点我一开始没在意,后来发现很关键:

如果没有激活函数,多层线性叠加还是线性。

W₂(W₁x + b₁) + b₂ 展开之后仍然是 Wx + b 的形式,堆一百层和一层没区别。激活函数引入非线性,深度才有意义。

四个常用的:

函数值域用途
ReLU max(0,x)[0, +∞)最常用,隐藏层默认
Sigmoid(0,1)二分类输出
Tanh(-1,1)零中心
Softmax概率分布多分类输出

优化器的三种变体

用多少数据特点
BGD 批量梯度下降全部稳但慢
SGD 随机梯度下降单样本快但噪声大
Mini-batch SGD一小批折中,最常用(批大小通常 32/64/128)

学习率调度

固定学习率不总是最优的。三种常见调度:

  • 阶梯衰减:每隔固定轮次衰减
  • 余弦退火:按曲线平滑衰减
  • Warmup:初期从小学习率线性增大,避免开局梯度爆炸

直觉是先大步探索,后期小步精调。


四、动手:多分类任务

这周的作业是写一个多分类任务(week2/task/多分类任务.py)。

结构是课上给的标准模板,后面几周的作业都沿用了这套骨架:

TorchModel(nn.Module)   模型定义
build_sample            造单条样本
build_dataset           批量造数据
evaluate                每轮评估
main                    训练主循环
predict                 加载模型做预测

有个设计我觉得挺巧妙,是 forward 的双模式:

def forward(self, x, y=None):
    # 传了 y → 训练模式,返回 loss
    # 没传 y → 推理模式,返回预测结果

一个方法同时服务训练和推理,调用方不用关心内部差异。

训练完要看的两件事

  1. 保存权重:torch.save(model.state_dict(), "model.bin")
  2. 画曲线:用 matplotlib 画 acc / loss 随轮次的变化

第二件事很重要。光看最终数字看不出训练是否健康——loss 是平稳下降,还是震荡,还是早就不动了,只有画出来才知道。


这周的收获

这周内容偏理论,但有三个点让我觉得值得反复看:

  1. 「学习」就是求损失函数的极小值。 把这句话想明白,梯度下降、学习率、优化器这些概念就都串起来了,不再是孤立的名词。

  2. 激活函数的必要性。 没有它,深度就是假的。这个点在纸上推一遍展开式比任何解释都有说服力。

  3. 手写公式再看框架实现。 我这周四个脚本都是「先自己算一遍,再和 PyTorch 对比」。这个过程发现了好几处我以为懂了其实没懂的地方——比如交叉熵里 log 的底、以及为什么要取负号。

作为后端转过来的,最不适应的是调试方式变了。以前程序错了有栈追踪,现在是「loss 不降」,可能是学习率、可能是数据、可能是模型太小、也可能是哪里写反了符号。这周开始养成画曲线的习惯,就是为了让问题「看得见」。

下周讲深度学习的常用组件——Embedding、CNN、RNN、LSTM、池化、归一化、Dropout,一次性把工具箱配齐。

相关文章