pytorch_22_防止过拟合的方法
简单阐述防止过拟合的方法
正则化
L2 Regularization
只要直接在 训练前 为optimizer设置正则化项的$\lambda$参数(这里不叫Regularization而是用了Weight Decay这个叫法):
1 |
optimizer = optim.SGD(net.parameters(), lr=learning_rate, weight_decay=0.01) |
正则化项目是用来克服over-fitting的,如果网络本身就没有发生over-fitting,那么设置了正则化项势必会导致网络的表达能力不足,引起网络的performance变差。
L1 Regularization
若使用$L1$正则化项,即对所有参数绝对值求和再乘以一个系数:
在PyTorch中还没有直接设置$L1$范数的方法,可以
在训练时Loss做BP之前
(也就是
.backward()
之前)手动为$Loss$加上$L1$范数:
1 |
# 为Loss添加L1正则化项 |
用上节的代码试了一下,使用L 1 L1L1正则化项时如果指定和使用$L2$正则化项时相同的$\lambda=0.01$会发生under-fitting,似乎如果要用$L1$正则化的话要把其系数设置的小一点,所以这里用了0.001。
转自: 【PyTorch学习笔记】14:划分训练-验证-测试集,使用正则化项
动量
其中$ \alpha$是学习率。
来代替。即相当于原式子又减去了一个$\alpha \cdot \beta \cdot z_k$
这一项。其中$z$表征了上次更新的方向和大小,而$\nabla f(w)$则是梯度,所以新的式子综合考虑了梯度下降的方向和上次更新的方向,用$\beta$来决定了惯性的大小。
优点
使用
1 |
optimizer = optim.SGD(net.parameters(), lr=learning_rate, momentum=0.78) |
这里试了一下,仅添加了这个动量的参数,没加正则化项
转自: 【PyTorch学习笔记】15:动量(momentum),学习率衰减
学习率衰减
在使用梯度更新参数时,学习率如果选取太小的话,学习过 程会很慢;如果学习率选取太大,那么很可能会出现来回抖动的情况,这时最终的模型可能很难收敛,而且看起来和”梯度弥散”的情况也很像(但其实不是)。
选取合适的固定的学习率是很难的, 可以在训练的一开始选取比较大的学习率加快训练过程,然后逐渐让其衰减到比较小的值,最终让模型收敛。
Reduce LR On Plateau
Plateau是平原的意思,这个类即用来监控某个量,当其在训练过程中多次没有发生下降(或上升,取决于
mode
参数)时,就减少学习率。首先,在定义优化器时:
1 |
from torch.optim.lr_scheduler import ReduceLROnPlateau |
在每次训练时,改用这个
scheduler
来执行
.step()
方法,并传入要监控的量,这里即是传入计算出的loss:
1 |
optimizer.step() |
在前面(带动量)的基础上运行了一下
StepLR
这个就和监控量没关系了,是固定的每执行
step_size
个
.step()
方法,就把学习率乘以
gamma
即可。
定义优化器时:
1 |
from torch.optim.lr_scheduler import StepLR |
训练时(注意不用传监控量进去了):
1 |
optimizer.step() |
转自: 【PyTorch学习笔记】15:动量(momentum),学习率衰减
Early Stop
如果一直训练,训练集上的性能可以一直上升,但验证集上的性能在经过某个点之后就可能开始下降,这时就是模型出现了over-fitting,提前停止就是用来克服over-fitting的。
但是没训练完怎么知道哪个点是最大值点呢?可以用经验来判断,比如当连续多个epoch上的验证集Acc.在下降时就停止训练。
Dropout
使用:在PyTorch中直接在要加的有连接的相邻两层之间插入Dropout层:
1 |
self.model = nn.Sequential( |
在train时,模型使用前指明模式:
1 |
# 指明使用"训练用"的网络模式,这里的目的是开启使用 |
在validation或者test时,模型使用前指明模式:
1 |
# 在验证集上需要把Dropout去掉,只在训练的时候使用!这里是切换一下模式 |
注意,如上面这样的定义方式是在logit和非线性激活的直连上做了Dropout,而不是在线性模型层内部做了Dropout。
注意,PyTorch中
torch.nn.Dropout()
传入的参数是断开的概率,而TensorFlow中
tf.nn.dropout()
传入的参数是保持连接的概率,即1-断开的概率。
Stochastic Gradient Descent
使用SGD的原因是训练集样本可能非常多,一方面显存不够把所有样本读进来,另一方面对所有样本计算梯度速度可能太慢了。所以在实际用的时候都不用原始的GD,而是用SGD来做的: