在构建完模型后,通过一下几种步骤进行模型优化训练过程
优点:(1)每次只用一个样本更新模型参数,训练速度快(2)随机梯度下降所带来的波动有利于优化的方向从当前的局部极小值点跳到另一个更好的局部极小值点,这样对于非凸函数,最终收敛于一个较好的局部极值点,甚至全局极值点。
缺点:(1)当遇到局部最优点或鞍点时,梯度为0,无法继续更新参数(2)沿陡峭方向震荡,而沿平缓维度进展缓慢,难以迅速收敛。
带动量的SGD
m
t
=
β
1
?
m
t
?
1
+
(
1
?
β
1
)
?
g
t
w
t
+
1
=
w
t
?
α
?
m
t
=
w
t
?
α
?
(
β
1
?
m
t
?
1
+
(
1
?
β
1
)
?
g
t
)
m_t = \beta_1 *m_{t-1} +(1- \beta_1)*g_t \\ w_{t+1} = w_t - \alpha * m_t = w_t - \alpha *(\beta_1 *m_{t-1} +(1- \beta_1)*g_t)
mt?=β1??mt?1?+(1?β1?)?gt?wt+1?=wt??α?mt?=wt??α?(β1??mt?1?+(1?β1?)?gt?)
一阶动量是各个时刻梯度方向的指数移动平均值,也就是说, t t t 时刻的下降方向,不仅由当前点的梯度方向决定,而且由此前累积的下降方向决定。
二阶动量的出现,才意味着“自适应学习率”优化算法时代的到来。
二阶动量——该维度上,记录到目前为止所有梯度值的平方和。
V
t
=
∑
τ
=
1
t
g
τ
2
η
t
=
α
?
m
t
/
V
t
w
t
+
1
=
w
t
?
α
?
m
t
/
V
t
=
w
t
?
α
?
m
t
/
∑
τ
=
1
t
g
τ
2
V_t = \sum_{\tau = 1}^{t} g_{\tau}^2 \\ \eta_{t} = \alpha * m_{t} / \sqrt{V_t} \\ w_{t+1} = w_{t} - \alpha * m_{t} / \sqrt{V_t} = w_{t} - \alpha * m_{t} / \sqrt{\sum_{\tau = 1}^{t} g_{\tau}^2}
Vt?=τ=1∑t?gτ2?ηt?=α?mt?/Vt??wt+1?=wt??α?mt?/Vt??=wt??α?mt?/τ=1∑t?gτ2??
优点:(1)在稀疏数据场景下表现非常好(2)此前的SGD及其变体的优化器主要聚焦在优化梯度前进的方向上,而AdaGrad首次使用二阶动量来关注学习率(步长),开启了自适应学习率算法的里程。缺点:(1)因为
V
t
V_t
Vt? 是单调递增的,会使得学习率单调递减至0,可能会使得训练过程提前结束,即便后续还有数据也无法学到必要的知识。
由于AdaGrad单调递减的学习率变化过于激进,考虑一个改变二阶动量计算方法的策略:不累积全部历史梯度,而只关注过去一段时间窗口的下降梯度。修改的思路很简单。前面讲到,指数移动平均值大约就是过去一段时间的平均值,因此我们用这一方法来计算二阶累积动量:
V t = β ? V t ? 1 + ( 1 ? β ) ? g t 2 w t + 1 = w t ? α ? m t / V t = w t ? α ? m t / β ? V t ? 1 + ( 1 ? β ) ? g t 2 V_t = \beta*V_{t-1} + (1 - \beta)*g_t^2 \\ w_{t+1} = w_{t} - \alpha * m_{t} / \sqrt{V_t} = w_{t} - \alpha * m_{t} / \sqrt{\beta*V_{t-1} + (1 - \beta)*g_t^2} Vt?=β?Vt?1?+(1?β)?gt2?wt+1?=wt??α?mt?/Vt??=wt??α?mt?/β?Vt?1?+(1?β)?gt2??
优点:避免了二阶动量持续累积、导致训练过程提前结束的问题了
谈到这里,Adam和Nadam的出现就很自然而然了——它们是前述方法的集大成者。SGD-M在SGD基础上增加了一阶动量,AdaGrad和AdaDelta在SGD基础上增加了二阶动量。把一阶动量和二阶动量都用起来,就是Adam了——Adaptive + Momentum
SGD的一阶动量:
m
t
=
β
1
?
m
t
?
1
+
(
1
?
β
1
)
?
g
t
m_t = \beta_1 * m_{t-1} + (1 - \beta_1)*g_t
mt?=β1??mt?1?+(1?β1?)?gt?
加上AdaDelta的二阶动量:
V
t
=
β
2
?
V
t
?
1
+
(
1
?
β
2
)
?
g
t
2
V_t = \beta_2 *V_{t-1} + (1 - \beta_2)*g_t^2
Vt?=β2??Vt?1?+(1?β2?)?gt2?
Adam参数更新公式如下,其中
α
\alpha
α是学习率,
g
t
g_t
gt?是当前参数的梯度
w
t
+
1
=
w
t
?
α
?
m
t
/
V
t
=
w
t
?
α
?
(
β
1
?
m
t
?
1
+
(
1
?
β
1
)
?
g
t
)
/
β
2
?
V
t
?
1
+
(
1
?
β
2
)
?
g
t
2
w_{t+1} = w_{t} - \alpha * m_{t} / \sqrt{V_t} = w_{t} - \alpha *( \beta_1 * m_{t-1} + (1 - \beta_1)*g_t) / \sqrt{\beta_2 *V_{t-1} + (1 - \beta_2)*g_t^2}
wt+1?=wt??α?mt?/Vt??=wt??α?(β1??mt?1?+(1?β1?)?gt?)/β2??Vt?1?+(1?β2?)?gt2??
是结构化风险最小化策略的实现,是在经验风险上加一个正则化项(regularizer)或者惩罚项(penalty term)。换另一种话讲就是,用来防止过拟合。
主要使用:l1正则项 l2正则项
两个正则项区别在于:
(1)L1正则得到参数有很多0,适用于特征选择、特征之间有关联性的场景,L2正则适用于特征之间没有关联性的场景
(2)L2正则得到的参数比L1正则小
earlystop 提前停止模型训练,防止过拟合
随着模型不断训练,不断调整学习率,提升模型的训练效果
等间隔调整学习率,每次调整为 lr*gamma,调整间隔为step_size
torch.optim.lr_scheduler.StepLR(optimizer,step_size,gamma=0.1,last_epoch=-1,verbose=False)
当前epoch数满足设定值时,调整学习率。这个方法适合后期调试使用,观察loss曲线,为每个实验制定学习率调整时期
torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1, verbose=False)
按指数衰减调整学习率,调整公式:
l
r
=
l
r
?
γ
?
e
p
o
c
h
lr = lr*\gamma*epoch
lr=lr?γ?epoch
torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma, last_epoch=-1, verbose=False)
torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=False, threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)
给定一个metric,当metric停止优化时减小学习率, 调整公式:
l
r
=
l
r
?
f
a
c
t
o
r
lr = lr*factor
lr=lr?factor