Pytorch 解决过拟合问题(L2 权值衰减和 Dropout)
本方法总结自《动手学深度学习》(Pytorch版)github项目
- 部分内容延续 Pytorch 学习(五):Pytorch 实现多层感知机(MLP) 实现方法
上一节用 Pytorch 实现了多层感知器。在解决实际问题时,可能会出现过拟合现象,常用的解决方法有数据增广和正则化,L2 权值衰减和 Dropout 都属于正则化的范畴
以均值方差(MSE)损失函数为例,通常情况下
L
M
S
E
(
w
)
=
1
2
∣
∣
y
^
−
y
∣
∣
2
L_{MSE}(w)={\frac{1}{2}||\hat{y}-y||}^2
LMSE(w)=21∣∣y^−y∣∣2其中,
y
^
\hat{y}
y^ 为真值,
y
y
y 为预测结果。L2 正则化通过给损失函数添加权值的 L2 范式惩罚项对其进行约束
L
M
S
E
(
w
)
=
1
2
∣
∣
y
^
−
y
∣
∣
2
+
λ
2
∣
∣
w
∣
∣
2
L_{MSE}(w)={\frac{1}{2}||\hat{y}-y||}^2+\frac{\lambda}{2}{||w||}^2
LMSE(w)=21∣∣y^−y∣∣2+2λ∣∣w∣∣2其中,
λ
\lambda
λ 为权值衰减参数。当总损失不变时,损失函数总是期望更小的
w
w
w ,从而使网络更简单,根据奥卡姆剃刀原理,相同的结果下,简单的更好。
实现方法一:从零实现
# 构建损失
def MSEloss(y_hat, y):
return (y_hat - y.view(-1, 1)) ** 2 / 2
# 权值衰减
def weight_penalty(w):
return (w ** 2).sum() / 2
# 训练过程中的新 loss
l = MSEloss(y_hat, y) + lambda * weight_penalty(w)
实现方法二:函数调用
import torch.optim as optim
optimizer = optim.SGD(net.parameters(), lr=lr, weight_decay=wd)
Dropout 通过在神经网络中以概率 p 随机保留不同的节点(即以概率 1-p 丢弃)来解决过拟合问题。由于每次计算中部分节点不参与,因此网络整体没有对数据进行完全学习,从而防止了过拟合。
![过拟合](https://i-blog.csdnimg.cn/blog_migrate/23cd91a51f346f5bc818787e422dc9eb.png)
过拟合示例图
实现方法一:从零实现
- 我们所实现的 dropout 实际是 inverted dropout
- Dropout 只会在训练过程使用,测试时不使用。
- 因此在训练时经过 dropout 层的期望 E(x) = px + (1-p) * 0,测试阶段为 E(x)。
- 为了保持两者的输出期望一直,dropout 需要在测试时添加 output = dropout(x) * p 来对期望进行统一。
- 在训练阶段对结果 output = dropout(x) / p 同样能达到相同的效果,称为 inverted dropout
def dropout(X, drop_prob):
assert 0 <= drop_prob and drop_prob <= 1
X = X.float()
keep_prob = 1 - drop_prob
if keep_prob == 0:
return torch.zeros_like(X)
mask = (troch.randn(X.shape) <= keep_prob).float()
return mask * X / keep_prob
实现方法二:直接调用
- dropout 的参数为丢弃率,不是保留率
import torch.nn as nn
dropout = nn.dropout(drop_prob)