03_损失函数和优化算法
1 损失函数
损失函数(loss function),也叫代价函数(cost function)、误差函数(error function)、目标函数(objective function),是用来衡量模型参数质量的函数,衡量的方式是比较网络输出(预测值)和真实输出(真实值)的差异。模型通过最小化损失函数的值来调整参数,使其输出更接近真实值。主要有性能评估和优化指导两大作用。
1.1 分类任务
1.1.1 二元交叉熵
二分类任务常用二元交叉熵损失函数(Binary Cross-Entropy Loss)。
$$L=-\frac{1}{n}\sum_{i=1}^{n}\left(y_{i}\mathrm{log}\widehat{y}_{i}+(1-y_{i})\mathrm{log}(1-\widehat{y}_{i})\right)$$
- 𝑦𝑖 为真实值(通常为 0 或 1)
- 𝑦̂𝑖 为预测值(表示样本 𝑖 为 1 的概率)
这个公式是针对单个样本的,它根据真实标签 y 的取值(0 或 1)只保留其中一项来计算惩罚。BCE 只惩罚模型对正确分类的预测概率,预测概率越大,损失越小。
使用 sigmoid 激活函数在输出层进行二分类时,输出层只有一个节点,这个节点的输出表示样本属于类 1 的概率。
1 | |
预测概率为 1 的概率为:
tensor([[0.6219],
[0.5057],
[0.5565]])
损失为:0.664
1.1.2 多分类交叉熵
多分类任务常用多分类交叉熵损失函数(Categorical Cross-Entropy Loss)。
$$L=-\frac{1}{n}\sum_{i=1}^n\sum_{c=1}^Cy_{i,c}\log\widehat{y_{i,c}}$$
- C 为类别数
- yi, c 表示第 i 个样本是否为 c 类,使用独热编码 0 或 1
- $\widehat{y_{i,c}}$ 表示第 i 个样本是类别 c 的预测概率

这个公式是针对 C 个类别的多分类问题,它利用了 One-Hot 编码的特性,只保留其中一项来计算惩罚,CCE 只惩罚对真实类别 c 的预测概率 $\widehat{y_{i,c}}$,相当于对每一个样本的正确标签预测概率值取 log ,然后求和。
使用 softmax 进行多分类时,有几个分类,输出层就有几个神经元,每个神经元输出一个分类的概率,所有概率和为 1。
1 | |
1 | |
预测概率:
tensor([[0.0875, 0.1952, 0.2651, 0.3005, 0.1516],
[0.1701, 0.5141, 0.1368, 0.0314, 0.1476],
[0.3212, 0.2801, 0.0933, 0.1782, 0.1272]])
损失:1.463
自定义交叉熵损失:1.4625852902730305
1 | |
真实值:
tensor([[0.3730, 0.2605, 0.1388, 0.1145, 0.1133],
[0.0738, 0.0385, 0.4177, 0.2543, 0.2157],
[0.3849, 0.4449, 0.0261, 0.1309, 0.0132]])
预测概率:
tensor([[0.0875, 0.1952, 0.2651, 0.3005, 0.1516],
[0.1701, 0.5141, 0.1368, 0.0314, 0.1476],
[0.3212, 0.2801, 0.0933, 0.1782, 0.1272]])
损失:1.823
注意:
CrossEntropyLoss内部完成了 softmax 操作和计算损失,因此不需要再进行 softmax 操作,并且返回的是一批次的平均损失,结果是标量。CrossEntropyLoss等价于LogSoftmax+NLLLoss。
1.2 回归任务
1.2.1 MAE(L1 Loss)
平均绝对误差(Mean Absolute Error,MAE),也称 L1 Loss。
$$L=\frac{1}{n}\sum_{i=1}^n|y_i-\hat{y_i}|$$
L1 Loss对异常值不太敏感,0 点不可导,产生稀疏矩阵,常常作为正则化项添加到其他损失函数中。 但是L1 Loss 最大的问题就是在 0 处不平滑,在优化过程中会跳过极小值。
1 | |
L1Loss: 1.000
1.2.2 MSE(L2 Loss)
均方误差(Mean Squared Error ,MSE),也称 L2 Loss。
$$L=\frac{1}{n}\sum_{i=1}^{n}(y_{i}-\widehat{y}_{i})^{2}$$
L2 Loss 由于平方会放大误差,因此对离群点敏感,当预测值与真实值偏差较大时,容易发生梯度爆炸。也常常作为正则化项。
梯度爆炸:网络层之间的梯度(值大于1.0)重复相乘导致的指数级增长会产生梯度爆炸。
1 | |
MSELoss: 2.375
至于为什么 API 命名为
L1Loss和MSELoss,如此不对称,是因为数学传统,L1Loss是基于 L1 范数的,而MSELoss基于 L2 范数的,但 MSE 是平方而不是平方根,为了避免歧义,直接使用了 MSELoss,而不是 L2Loss。
1.2.3 Smooth L1
MAE 对异常值不敏感,但在 0 处不可导,MSE 在 0 处光滑,但在误差较大时容易梯度爆炸。于是我们将两者结合,在绝对值小于 1 时使用 MSE,大于 1 时使用 MAE,并进行缩放和平移,得到 Smooth L1 损失函数,既光滑又对异常值不敏感。
$$SmoothL1= \begin{cases} \frac{1}{2}(y_i-\widehat{y}_i)^2,|y_i-\widehat{y}_i|<1 \\ |y_i-\widehat{y}_i|-\frac{1}{2},|y_i-\widehat{y}_i|\geq1 & \end{cases}$$
1 | |
SmppthL1Loss: 0.688
可视化三个损失函数,L1 Loss 是将 MSE 压缩 0.5 倍,并将 MAE 下移 0.5,使二者对齐平滑。此外还有很多对齐方法,比如 0.25 倍的 MSE 和 下移 1 的 MAE,在 x=2 时可以对齐。
1 | |
<matplotlib.legend.Legend at 0x310ada210>
2 数值微分
损失函数的值越小,说明我们的参数选择的越合适。想要求得损失函数的最小值,最基本的想法就是对损失函数求导,解出导数为 0 的点判断是否为极小值/最小值。然而实际的函数直接求导是困难的,不容易得到解析解,这时可以使用数值微分的方式,求到某点的导数,在实际工程中非常常见。
注意:实际上,深度学习中的优化器(Optimizer)在训练时使用的并不是数值微分,而是基于解析梯度(Analytical Gradient),通过一个名为 反向传播(Backpropagation, BP) 的算法来计算梯度,运算效率极高,这里使用数值微分旨在帮助理解梯度和它的作用。
2.1 导数
回忆导数的定义:
$$f^{\prime}(x)=\frac{df(x)}{dx}=\lim_{\Delta x\to0}\frac{f(x+\Delta x)-f(x)}{\Delta x}$$
当 x 发生一个微小的变化 Δx 时,函数值 f(x) 也会发生变化;当 Δx 趋近于 0 时,此时 f(x) 的“变化率”就是 x 这一点的导数值。
利用这个定义,在深度学习这种黑箱中,我们可以在不知道导数表达式,甚至不知道函数表达式的情况下,直接以数值计算的方式,利用微小的差分来求函数某点的导数值,这种方法称为数值微分。
1 | |
x=2 处的导数:4.000
x=4 处的导数:8.000
这里以 x 为中心,计算两边发生微小变化后的差分,可以避免只计算单向增大时的误差。这种方法称为 中心差分。另外,微小值 delta 不能太小,否则会导致浮点数表示的精度不够,出现舍入误差。
2.2 偏导数
如果函数 f 的自变量并非单个元素,而是多个元素。比如:
f(x, y) = x2 + y2 + xy
可以将其他自变量都置为常数,只求 x 和 y 一个自变量的导数,称为偏导数:
$$ \frac{\partial f}{\partial x} = 2x + y \qquad \frac{\partial f}{\partial y} = 2y + x$$
推广到多个自变量:
$$\frac{\partial f}{\partial x_i}(a_1,a_2,...,a_n)=\lim_{\Delta x_i\to0}\frac{f(a_1,...a_i+\Delta x_i,...,a_n)-f(a_1,...a_i,...,a_n)}{\Delta x_i}$$
偏导数同样可以用数值微分的方法求解,即只改变一个自变量、其它不变,做差分计算函数值的变化率。应用到深度学习中,就是只改变一个参数、其他不变,计算损失函数的偏导数。
2.3 梯度
多元函数 𝑓(𝑥1, …, 𝑥𝑛) 关于每个变量 𝑥𝑖 都有偏导数 $\frac{\partial f}{\partial x_i}$,在点 𝑎 处,这些偏导数定义了一个向量,称为 f 在点 a 的梯度:
$$\nabla f(a)=\left[\frac{\partial f}{\partial x_1}(a),...,\frac{\partial f}{\partial x_n}(a)\right]$$
函数 f 在点 a 有无数个方向导数,沿方向 d̂ 移动时函数变化率为:
Ddf = |∇f|cos θ
其中 θ 是 ∇f 与 d̂ 的夹角,要想找到让函数下降最快的方向,也就是让变化率最负,显然当 cos θ = −1 时,也就是梯度的反方向,下降最快。
应用到深度学习中,使用数值微分计算出在 a 点关于每个参数的偏导数,得到的向量也就是该点的梯度,梯度代表的是函数值增大最快的方向,寻找损失函数的最小值需要沿着负梯度方向。负梯度代表的是函数值减小最快的方向,但并不一定直接指向函数图像的最低点。
在函数的极小值、极大值和鞍点处,梯度为 0。
1 | |
array([[ 4., 6.],
[ 8., 10.],
[12., 14.]])
2.4 利用数值微分训练神经网络
这里不使用 PyTorch,手动实现一个两层的神经网络,利用数值微分的思想计算梯度,来完成经典案例———手写数字识别。
没有损失函数表达式如何求最小值?通过固定其他参数,只改变一个参数,求解损失函数对于该参数的导数,对所有参数做此操作,得到在当前点的梯度向量,然后按照梯度向量的反方向进行参数更新。
激活函数实现:
1 | |
损失函数在 1.1.2 节已经实现完毕,梯度下降在 2.3 节已经实现完毕,这里不再重复。
定义两层神经网络模型:
- 输入层:输入维度 64,对应 8 * 8 的图片
- 隐藏层:输入维度 50 ,经过 Tanh 激活函数,输出维度 10
- 输出层:输入维度 10,经过 Softmax 激活函数,对应 10 个数字类别
1 | |
定义函数获取数据集。
1 | |
定义函数进行训练,这里可以使用 tensorboard
动态地可视化训练过程。使用 pip install tensorboard
安装。
1 | |
Epoch: 01[==============================] 100.00% Loss: 1.295 Acc: 65.903%
Epoch: 02[==============================] 100.00% Loss: 0.349 Acc: 92.639%
Epoch: 03[==============================] 100.00% Loss: 0.222 Acc: 95.139%
Epoch: 04[==============================] 100.00% Loss: 0.156 Acc: 96.944%
Epoch: 05[==============================] 100.00% Loss: 0.111 Acc: 97.708%
使用现成工具 tqdm 显示进度条,不需要自己手写
print。使用pip install tqdm 安装。
1 | |
训练: 100%|██████████| 100000000/100000000 [00:06<00:00, 16450174.04it/s]
训练: 100%|██████████| 100000000/100000000 [00:06<00:00, 16451340.61it/s]
训练: 100%|██████████| 100000000/100000000 [00:06<00:00, 16359374.67it/s]
也可以动态调整进度条后方显示的内容。
1 | |
Epoch 1: 100%|██████████| 10000/10000 [00:02<00:00, 3789.39it/s, acc=0.4, loss=4]
Epoch 2: 100%|██████████| 10000/10000 [00:02<00:00, 3831.96it/s, acc=0.7, loss=2]
Epoch 3: 100%|██████████| 10000/10000 [00:02<00:00, 3960.02it/s, acc=1, loss=0.0002]
绘制损失函数和正确率对于训练轮次的曲线图。
1 | |
Text(0.5, 0, 'Epoch')
如果使用 TensorBoard,在命令行中输入
tensorboard --logdir=runs(runs 为保存日志文件的目录)启动
TensorBoard,在浏览器中打开 http://localhost:6006。

在测试集完成预测,输出分类报告。
1 | |
precision recall f1-score support
0 1.00 0.97 0.99 36
1 0.97 0.95 0.96 37
2 1.00 1.00 1.00 35
3 0.90 1.00 0.95 37
4 1.00 0.94 0.97 36
5 1.00 0.89 0.94 36
6 0.95 1.00 0.97 36
7 1.00 1.00 1.00 36
8 0.90 1.00 0.95 35
9 0.94 0.89 0.91 36
accuracy 0.96 360
macro avg 0.97 0.96 0.96 360
weighted avg 0.97 0.96 0.96 360
3 梯度下降和优化
3.1 梯度下降法
梯度下降法(Gradient Descent)就是一种利用梯度最小化损失函数的迭代优化算法。核心是沿着损失函数的负梯度方向逐步调整参数,从而逼近函数的最小值。

模拟梯度下降优化目标函数 w1 ** 2 + w2 ** 2 + 5,经过 15
轮迭代已经非常逼近目标函数的最小值
5,充分体现了梯度下降可以通过迭代寻找目标函数的最小值。
1 | |
epoch: 1, w1=1.600, w2=2.400, loss=13.320
epoch: 2, w1=1.280, w2=1.920, loss=10.325
epoch: 3, w1=1.024, w2=1.536, loss=8.408
epoch: 4, w1=0.819, w2=1.229, loss=7.181
epoch: 5, w1=0.655, w2=0.983, loss=6.396
epoch: 6, w1=0.524, w2=0.786, loss=5.893
epoch: 7, w1=0.419, w2=0.629, loss=5.572
epoch: 8, w1=0.336, w2=0.503, loss=5.366
epoch: 9, w1=0.268, w2=0.403, loss=5.234
epoch: 10, w1=0.215, w2=0.322, loss=5.150
epoch: 11, w1=0.172, w2=0.258, loss=5.096
epoch: 12, w1=0.137, w2=0.206, loss=5.061
epoch: 13, w1=0.110, w2=0.165, loss=5.039
epoch: 14, w1=0.088, w2=0.132, loss=5.025
epoch: 15, w1=0.070, w2=0.106, loss=5.016
array([0.07036874, 0.10555312])
3.2 训练术语
- Epoch:1 个 Epoch 表示模型完整遍历一次训练数据集的过程。 单次遍历数据集通常不足以让模型收敛,模型需要多次遍历数据集才能逐步优化模型参数、学习数据中的模式,
- Batch Size:Batch Size
是每次训练时输入的样本数量。例如
batch_size=32表示每次用 32 个样本计算一次梯度,并取平均值作为本次迭代的参数更新方向。 小批量数据计算梯度比单样本更稳定,比全批量更高效。并且较小的 Batch Size 可能带来更多噪声,有助于模型泛化。 - Iteration:一次 Iteration 表示完成一个 Batch 数据的正向传播(预测)和反向传播(更新参数)的过程,也就是训练轮数和批次数的乘积。
3.3 SGD
SGD(Stochastic Gradient
Descent)原本只随机选择一个样本计算梯度来更新参数,但是在 PyTorch
中经常使用 optim.SGD 配合
DataLoader,实际上执行的是 Mini-Batch Gradient Descent
(小批量梯度下降)。
每个样本都对应一个自己的损失函数,Mini-Batch 的思想就是选取一小批样本,计算它们的平均损失对模型参数的梯度,用来近似整个训练集的损失函数对参数的梯度。
由于 Mini-Batch 引入了梯度的随机性,这间接提高了模型的泛化能力并避免过拟合。
Mini-Batch 是对整个训练集真实梯度的一个有噪音的估计,这种噪音让优化过程不会笔直地冲向损失函数表面的最尖锐、最狭窄的局部极小值,而尖锐极小值通常与较差的泛化能力(过拟合)相关。随机性帮助优化过程探索更广阔的区域,更容易找到平坦的极小值。平坦的极小值意味着模型对输入数据的微小变化更不敏感,通常能带来更好的泛化能力。
| Batch Size | 梯度估计 | 泛化能力 | 收敛速度(时间) |
|---|---|---|---|
| 大 Batch (e.g., 256+) | 准确稳定 | 倾向于收敛到尖锐极小值,泛化能力可能较差(更容易过拟合)。 | 训练时间短(利用并行计算) |
| 小 Batch (e.g., 16-64) | 噪音大 | 倾向于收敛到平坦极小值,泛化能力强(不容易过拟合)。 | 训练时间长(利用效率低) |
| Full Batch (全批量) | 最准确 | 最容易过拟合 | 训练时间最长 |
注意这里讨论的是泛化能力,而不仅仅是收敛稳定性。
虽然大批量的梯度更新在训练时看起来更稳定、路径更平滑,但它们会倾向于找到训练集损失最低但泛化能力差(对测试数据微小变化敏感)的尖锐极小值。
而小批量的训练路径虽然波动,但这种波动(随机性)却是一种正则化形式,帮助模型找到了一个泛化性能更好、更鲁棒的平坦极小值。
SGD 的更新公式:
W ← W − η∇
SGD 实现简单,理解方便,然而有些问题,比如:
- 局部最优解:陷入局部最优,尤其在非凸函数中,难以找到全局最优解。
- 鞍点:陷入鞍点,梯度为 0,导致训练停滞。
- 收敛速度慢:高维或非凸函数中,收敛速度较慢。
- 学习率选择:学习率过大导致震荡或不收敛,过小则收敛速度慢。

针对以上问题,有些常用的优化算法如:
- 引入动量
- Momentum
- 学习率衰减
- 自适应学习率
- AdaGrad
- RMSprop
- 结合自适应学习率和动量
- Adam
3.4 Momentum
Momentum(动量法)模拟物理学中的动量概念。在梯度下降时,不仅仅考虑当前梯度,还考虑之前的梯度方向。
$$v\leftarrow\alpha v+(1-\alpha)\nabla \\ W\leftarrow W-\eta v$$
- v: 动量,历史负梯度的加权和
- α: 动量的衰减率,也就是历史梯度的权重,通常取 0.9
- η: 学习率
- ∇: 当前梯度
动量法通过累计历史梯度,能够减缓优化过程中的震荡,并且很有可能在遇到鞍点或局部最优解时,冲过去从而取得更优解。
1 | |
- 优点:
- 平滑梯度,减少梯度方向的震荡
- 加速收敛,梯度方向一致时,可以加速参数的更新
- 可以帮助模型冲出局部最小值
- 缺点:
- 动量系数需要手动调整
- 动量过大,模型可能越过最优解
3.5 学习率衰减
较大的学习率可以加快收敛速度, 但可能在最优解附近震荡或不收敛;较小的学习率可以提高收敛的精度,但训练速度慢,可能陷入局部最优解。学习率衰减是一种平衡策略,初期使用较大学习率快速接近最优解,后期逐渐减小学习率,使参数更稳定地收敛到最优解。
- 等间隔衰减:每隔固定的训练周期(epoch),学习率按一定的比例下降。
1 | |
[0.1] [0.1] [0.1] [0.1] [0.1] [0.1] [0.1] [0.1] [0.1] [0.06]
- 制定间隔衰减:在指定的 epoch,让学习率按比例衰减。
1 | |
<torch.optim.lr_scheduler.MultiStepLR at 0x3160cf6b0>
- 指数衰减:学习率按照指数函数进行衰减,一般底数要接近 1。
1 | |
<torch.optim.lr_scheduler.ExponentialLR at 0x316895d30>
3.6 AdaGrad
Adagrad(Adaptive Gradient)是一种自适应梯度优化算法,Adagrad 的核心思想是为每个参数维护一个独立的学习率。它会根据每个参数的历史梯度平方和来调整学习率,对于更新频繁的参数,学习率会降低;对于更新不频繁的参数,学习率会增加。
$$G_i \leftarrow G_i+\nabla^2 \\ W_i \leftarrow W_i-\frac{\eta}{\sqrt{G_i}+\epsilon}\nabla$$
- Gi:第 i 个参数的历史梯度平方和
- η:学习率
- ϵ:一个很小的值,防止除零
随着训练进行,累计梯度平方和变大,所对应的学习率会逐渐减小,所以 AdaGrad 刚开始可以使用较大的学习率。
1 | |
- 优点:
- 自适应学习率,不用手动调整
- 适用于稀疏特征,大多数特征值为 0,对应的梯度也可能为 0,对应参数的累计梯度和较小,能够保持较大的学习率,促进这些特征的学习,能够有效利用数据中信息
- 缺点:
- 随着训练的进行,学习率最终会减小到非常小的值,过早使学习率过低可能导致算法无法找到最优解。
3.7 RMSProp
RMSProp(Root Mean Square Propagation,均方根传播)是在 AdaGrad 基础上的改进,旨在解决 Adagrad 在训练后期学习率降低过快的问题。它并非累计每个参数的历史梯度平方,而是逐渐遗忘过去的梯度,采用指数移动加权平均,呈指数地减小过去梯度的尺度。
$$G_i \leftarrow \alpha G_i+ (1-\alpha)\nabla^2 \\ W_i \leftarrow W_i-\frac{\eta}{\sqrt{G_i}+\epsilon}\nabla$$
- α:用于控制历史梯度的影响程度,通常取 0.9-0.99 之间的值
- η:学习率
- Gi:第 i 个参数的近期梯度平方的加权平均值
- ϵ:小常数防止除零
1 | |
优点同 AdaGrad 相同,解决了学习率过早衰减的问题,并且在非凸优化问题的解决上表现良好,缺点是超参数 α 需要手动设置。
3.8 Adam
Adam(Adaptive Moment Estimation,自适应矩估计)结合了 Momentum 和 RMSprop 的优点,同时利用梯度的一阶矩估计(即动量)和二阶矩估计(即 RMSprop 中的平方梯度),能够适应性地调整每个参数的学习率,同时利用历史梯度的信息来加速训练。
$$\
WW-$$
- v:一阶矩估计,类似动量
- h:二阶矩估计,类似平方梯度
- α1:一阶矩估计的指数衰减率,控制历史梯度的影响程度,一般取 0.9。值越大,历史信息的影响越大,梯度变化越平滑。
- α2:二阶矩估计的指数衰减率,控制历史平方梯度的影响程度,一般取 0.999。值越大,历史信息的影响越大,学习率调整越平滑。
- v̂ 和 ĥ:修正后的估计,由于 α 初始值较大,而历史梯度没有经过累计还很小,当前梯度信息被压缩太小,整个 v 和 h 会很小,通过除去指数修正偏差。
- t:迭代次数
- ϵ:小常数防止除零错误
1 | |
- 优点
- 自适应学习率
- 快速收敛
- 适用稀疏数据
- 缺点
- 强大的自适应性可能导致过拟合
4 正则化
过拟合是在模型训练中很容易遇到的问题,通过正则化的方式可以降低模型复杂度,从而防止过拟合。在深度学习中神经网络容易遇到的问题还有梯度消失和梯度爆炸,借鉴机器学习的思路,扩展了正则化的范围,常见的正则化方法有 Batch Normalization、权值衰减、Dropout、早停法等。
4.1 Batch Normalization
在深度神经网络训练过程中,由于前面层的参数更新会导致后面层输入的改变,每一层输入的分布都在不断变化,这种现象被称为内部协变量偏移 (Internal Covariate Shift)。这会带来以下问题:
- 训练缓慢: 每层都需要不断适应新的输入分布,导致学习效率降低。
- 梯度消失/爆炸: 输入分布的变化可能导致梯度变得过大或过小,影响训练的稳定性。
- 对初始化敏感: 合适的初始化参数变得更加重要,否则难以训练。
Batch Normalization 通过将每层网络的输入归一化到一个标准分布,可以调整各层的激活值分布使其拥有适当的广度,BN 层通常放在激活函数之前,这意味着经过 BN 层之后的数据更加适合激活函数,不容易出现梯度爆炸和梯度消失。
$$\hat{x}=\frac{x-\mu}{\sqrt{\sigma^2+\epsilon}} \qquad y=\gamma\hat{x}+\beta$$
计算一个 batch 中每个特征通道的均值 μ 和方差 σ,然后除减均值除方差进行归一化(ϵ为小常数),为了保证网络的表达能力,引入两个可学习的参数 γ (缩放因子)和 β (平移因子)对归一化后的输出进行缩放和平移。
优点: - 加速训练:允许使用更高的学习率,加快收敛速度。 - 提高泛化能力:在一定程度上具有正则化效果,因为它在训练过程中引入了噪声(由小批量估计的均值和方差产生的噪声)。 - 缓解初始化敏感性:使得模型对参数初始化的依赖性减小,从而提高了训练的稳定性。
缺点: - 对批次大小敏感:当批次大小很小时,均值和方差的估计可能不准确,影响归一化效果。 - 在 RNN 中应用较为复杂:在循环神经网络(RNN)中应用 Batch Normalization 较为复杂,需要进行特殊的处理。
切换模型模式会有不同机制:
- 训练时:
model.train()- BN 层会计算当前批次的均值 μ 和方差 σ²,并对当前批次的数据进行规范化。
- BN 层还会维护一个全局均值和全局方差的移动平均值,用于推理阶段。
- 推理时:
model.eval()- 推理时,直接使用训练阶段计算的全局均值和全局方差。
1 | |
tensor([[ 0.6912, -0.1234, 0.1234],
[-1.8892, 1.1929, 1.4397],
[-0.0461, -1.4397, 1.7688],
[ 1.0598, -0.7816, -0.2057],
[-0.7833, -1.1106, -0.5347],
[-0.7833, 1.5220, -0.8638],
[ 0.6912, 0.5347, -1.1929],
[ 1.0598, 0.2057, -0.5347]], grad_fn=<NativeBatchNormBackward0>)
4.2 权值衰减
由于权重参数取值过大是很多过拟合产生的原因,因此可以在学习的过程中对大的权重进行惩罚,可以有效地抑制过拟合,这种方法被称为权值衰减。
一般会对损失函数加上一个权重的范数;最常见的就是 L2 范数的平方: $$L^{\prime}=L+\frac{1}{2}\cdot\lambda\cdot||W||^2$$
- ||W||:权重W = (w1, w1, ..., w1)的 L2 范数,即$\sqrt{w_1^2+w_2^2+...+w_n^2}$
- λ:控制正则化强度的超参数
惩罚项求导之后得到 𝜆𝑊 ,所以在求权重梯度时,需要为之前误差反向传播法的结果加上 𝜆𝑊。
4.3 Dropout
Dropout(随机失活,暂退法)是一种在学习的过程中随机关闭神经元的方法,通常放在激活函数之后,全连接层之前。
训练时每个神经元都有概率 𝑝 (通常为0.2~0.5) 被临时关闭,迫使网络不依赖特定神经元,强迫网络学习到更加鲁棒的特征表示,同时未被关闭的神经元的输出值以 $\frac{1}{(1−𝑝)}$ 的比例进行缩放,以保持期望值不变。
由于每次 Dropout 是随机失活,迭代训练不同的子网络,引入了随机性,近似集成 Bagging 的效果。

1 | |
tensor([[ 1.7553, 0.8046, -0.0000, 0.0000, -1.1799],
[-2.8858, 0.0000, 0.3864, 0.0000, -2.3464],
[-0.0000, -0.0000, -0.0000, 0.0000, -0.0000]])