深度学习实践技巧

学习率的选择与切换:

  1. 初期Adam,后期SGD,切换方法参考:Improving Generalization Performance by Switching from Adam to SGD
  2. 首先来看第1个问题,切换之后用什么样的学习率。
    Adam的下降方向是
    n t A d a m = ( α / V t ) ∗ m t n^{Adam}_t = (\alpha/\sqrt{V_t})*m_t ntAdam=(α/Vt )mt
    而SGD的下降方向是.
    n t S G D = α S G D ⋅ g t n^{SGD}_t = \alpha^{SGD}\cdot g_t ntSGD=αSGDgt
    , n t S G D n^{SGD}_t ntSGD必定可以分解为 n t A d a m n^{Adam}_t ntAdam 所在方向及其正交方向上的两个方向之和,那么其在 n t A d a m n^{Adam}_t ntAdam 方向上的投影就意味着SGD在Adam算法决定的下降方向上前进的距离,而在 n t A d a m n^{Adam}_t ntAdam 的正交方向上的投影是 SGD 在自己选择的修正方向上前进的距离。
    在这里插入图片描述

图片来自原文,这里p为Adam下降方向,g为梯度方向,r为SGD的学习率。如果SGD要走完Adam未走完的路,那就首先要接过Adam的大旗——沿着 n t A d a m n^{Adam}_t ntAdam 方向走一步,而后在沿着其正交方向走相应的一步。这样我们就知道该如何确定SGD的步长(学习率)了——SGD在Adam下降方向上的正交投影,应该正好等于Adam的下降方向(含步长)。也即:
p r o j n t S G D = n t A d a m proj_{n^{SGD}_t} =n^{Adam}_t projntSGD=ntAdam
解这个方程,我们就可以得到接续进行SGD的学习率:
α t S G D = ( ( n t A d a m ) T n t A d a m ) / ( ( n t A d a m ) T g t ) \alpha_t^{SGD}=((n_t^{Adam})^Tn_t^{Adam})/((n_t^{Adam})^Tg_t) αtSGD=((ntAdam)TntAdam)/((ntAdam)Tgt)为了减少噪声影响,作者使用移动平均值来修正对学习率的估计:
λ t S G D = β 2 ⋅ λ t − 1 S G D + ( 1 − β 2 ) α t S G D \lambda_t^{SGD}=\beta_2\cdot\lambda_{t-1}^{SGD}+(1-\beta_2)\alpha_t^{SGD} λtSGD=β2λt1SGD+(1β2)αtSGD
λ ~ t S G D = λ t S G D / ( 1 − β 2 t ) \tilde{\lambda}^{SGD}_t =\lambda_t^{SGD}/(1-\beta_2^t) λ~tSGD=λtSGD/(1β2t)这里直接复用了Adam的 β 2 \beta_2 β2参数。然后来看第一个问题,何时进行算法的切换。作者的回答也很简单,那就是当 SGD的相应学习率的移动平均值基本不变的时候,即: ∣ λ ~ t S G D − α t S G D ∣ < ϵ |\tilde{\lambda}^{SGD}_t-\alpha_t^{SGD}|<\epsilon λ~tSGDαtSGD<ϵ
每次迭代玩都计算一下SGD接班人的相应学习率,如果发现基本稳定了,那就SGD以 λ ~ t S G D \tilde{\lambda}^{SGD}_t λ~tSGD 为学习率接班前进。

使用方法

pip install pytorch-swats

import swats

optimizer = swats.SWATS(model.parameters())
data_loader = torch.utils.data.DataLoader(...)

for epoch in range(10):
    for inputs, targets in data_loader:
        # deleting the stored grad values
        optimizer.zero_grad()

        outputs = model(inputs)
        loss = loss_fn(outputs, targets)
        loss.backward()

        # performing parameter update
        optimizer.step()

其他小技巧

  1. 先用小数据集进行实验。
  2. 数据集一定要充分的打散(shuffle)。 这样在使用自适应学习率算法的时候,可以避免某些特征集中出现,而导致的有时学习过度、有时学习不足,使得下降方向出现偏差的问题。
  3. 在语义分割任务时可使用lovasa-loss
    lovasa-loss
  4. 如果上述学习率效果差,可考虑换为warm restart 学习率:
    Cosine Annealing w. Snapshot Ensemble
CYCLE=8000
LR_INIT=0.
1LR_MIN=0.001
scheduler = lambda x: ((LR_INIT-LR_MIN)/2)*(np.cos(PI*(np.mod(x-1,CYCLE)/(CYCLE)))+1)+LR_MIN
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值