PyTorch入门实战教程笔记(十八):过拟合2(训练小技巧)
动量和学习率衰减
- 动量(momentum)
我们先来回顾一下梯度更新的公式:wk+1 = wk - α▽f(wk),而动量再次基础上增加了一个zk参数(多减去一个β倍的zk),我们知道,当它减去梯度的时候,是往梯度方向走,当它减去zk,是不是就是往zk方向走,那么zk是什么呢? zk+1 = βzk - ▽f(wk),所以zk 是某一种算子,它是上一次梯度的方向。所以,对于当前w的更新,就应该是这一次梯度方向和上一次梯度方向的向量加权和的方向。而α和β用于调整当前和上一次梯度方向的大小,以决定这次更新w方向超哪里更新,会产生不同的效应。
下面我们对比一下加和不加动量的区别,下图图1是不加动量的效果,可以发现,更新梯度方向震动较大,并且也没有到达全局最优解。而我们加过动量之后,下图图2是加动量的效果,可以看到,更新梯度震动减缓,且越过了局部最优解,能够达到全局最优解,实现了良好的效果。
在pythorch中,对momentum支持非常方便,在SGD里面我们只需要设置参数momentum即可,
- 学习率衰减(learning rate decay)
首先,我们来看一下learning rate的大小对更新效果的影响,如下图所示:太小收敛太慢,太大会在最优解附近徘徊,理想情况是中间的一幅图。
如上图中间图,我们希望梯度更新,先下降快,后下降慢(避免出现上图最右图的情况),所以需要来调节学习率,让学习率先大后小,实现learning rate微调,达到我们的目的。
两种比较常见的learning rate decay的方案:
- 我们观测loss,比如loss先下降然后一直不动,也就是很难找到一个更细化的解的情况,那应该把learning rate设置的小一点了。使用pytorch中的函数ReduceLROnPlateau函数,设置一个参数,在我们监听loss时,发现经过连续几个patience(耐性值),比如是10次,连续十次调用这个函数,监听这个loss,发现连续10次没有减少,然后就把learning rate就行减少,使用optimizer参数,使得learning rate交给它管理,使用’min’参数监听loss,如果连续8个或10个左右epochs,发现loss已经到达饱和期的时候,这个函数就会产生新的作用,因此scheduler.step(loss_val),每调用一次,就会监听一次loss,如果达到饱和,就按照自己设置的规则减小learning rate。
- 第二种 方法就比较简单粗暴了,就是自己设置,每经过多少个epoch,就较少一次learning rate,调用StepLR,帮助步进,比如,每30个epoch,就步进原来的学习率的0.1倍,让学习率衰减。
Early Stopping
我们 在训练模型的时候,training set accuracy 在一直上升,但是test set accuracy会上升后下降,即出现过拟合,所以,我们通过监督test set accuracy(实际为验证集)的精度,当它达到最高值的时候,就停止训练,即提前停止。
具体流程:
Dropout
dropout 是指在深度学习网络的训练过程中,按照一定的概率将一部分神经网络单元暂时从网络中丢弃,相当于从原始的网络中找到一个更瘦的网络。 是一个减少overfitting的一个有效的方法。
在pytorch中加Dropout,直接调用torch.nn.Dropout(0.5),(注:pytorch和tensorflow这里是不同的,pytorch的参数是真正的dropout的概率,值越小,断的概率越小,而tensorflow是keep_prob,值越小,断的概率越大),即可。这种相当于在两层Linear之间的直连,会有一个随机丢失的效果,加之前是直连,加之后随机丢弃。而不是将Linear的全连接给Dropout(当然,这种也有相应的函数)。另外,在训练和测试时,dropout行为是不一样,在训练时随机丢失,但在测试时是全连接的,所以在验证时,应该把状态切换回来,net_dropped.eval(),我们约定在做test时,要把所有的连接都用上,能够提高test的表现。
Stochastic Gradient Descent
随机梯度下降,什么意思呢,对于最原始的梯度,我们是计算出来所有的比如60k图片的梯度累加求平均,但是对于想image_net这些数据集,样本量很大,所以我们要stochastic随机取一个batch的所有梯度累加在求平均。最大的原因是现在的硬件设备内存不够,不可能一次用所有的数据集计算,而是取batch来计算。