神经网络参数优化
神经网络中,很多的超参数难以设置,我们可以引入动量(momentum),通过算法来达到优化时间和准确率。
1. 动量(momentum)
常用的动量有一阶动量和二阶动量:
一阶动量m:与梯度相关的函数
二阶动量v:与梯度平方相关的函数
w为参数,损失函数loss,dw为损失函数对w的倒数,学习率lr。其优化公式为:
w
=
w
−
l
r
∗
m
/
v
{\rm{w = w - lr*m/}}\sqrt {\rm{v}}
w=w−lr∗m/v
2. 随机梯度下降法(SGD)
随机梯度下降法就是一般的梯度下降方法,其中m = dw,v=1公式为:
w
=
w
−
l
r
∗
d
w
{\rm{w = w - lr*dw}}
w=w−lr∗dw
其代码如下:
w1.assign_sub(lr * grads[0]) # 参数w1自更新
b1.assign_sub(lr * grads[1]) # 参数b自更新
3. 含有动量的随机梯度算法(SGDM)
SGDM是在SGD的基础上增加了一阶动量,其中m = βm + (1 - β)dw,β的经验值为0.9,v=1公式为:
w = w − l r ∗ ( β ∗ m + ( 1 − β ) ∗ d w ) {\rm{w = w - lr*(}}\beta* {\rm{m + (1 - }}\beta {\rm{)*dw)}} w=w−lr∗(β∗m+(1−β)∗dw)
其实现代码如下:
# m_w,m_b初始值为0
# beta初始值为0.9
m_w = beta * m_w + (1 - beta) * grads[0]
m_b = beta * m_b + (1 - beta) * grads[1]
w1.assign_sub(lr * m_w)
b1.assign_sub(lr * m_b)
4.AdaGrad算法
AdaGrad算法是自适应学习率算法的一种,独立的适应于所有模型参数的学习率。其中具有较大偏导数的参数相应的有一个快速下降的学习率,而具有较小偏导的参数在学习率上有相对较小的下降。
在凸优化背景中,AdaGrad算法具有令人满意的成绩。但是AdaGrad算法可能会导致过早或过量的减少学习率。
Adagrad是在SGD的基础上增加了二阶动量,其中,m = dw,v = ∑dw,所以有公式:
w
=
w
−
l
r
∗
d
w
/
(
∑
d
w
)
{\rm{w = w - lr}}*{\rm{dw/(}}\sum {{\rm{dw}}} {\rm{)}}
w=w−lr∗dw/(∑dw)
其实现代码如下:
# 其中二阶动量的初始值为0
v_w += tf.square(grads[0])
v_b += tf.square(grads[1])
w1.assign_sub(lr * grads[0] / tf.sqrt(v_w))
b1.assign_sub(lr * grads[1] / tf.sqrt(v_b))
5. RMSProp算法
RMSProp算法是修改AdaGrad以在非凸设定下效果更好,经验上,RMSProp已被证明是一种有效且实用的深度神经网络优化算法,目前它是深度学习经常采用的优化方法之一。
RMSProp也是在SGD的基础上增加二阶动量所得,其中 m = dw,v = βv - (1 - β)dw**2,其公式为:
w
=
w
−
l
r
∗
d
w
/
β
∗
v
+
(
1
−
β
)
∗
d
w
2
{\rm{w = w - lr*dw/}}\sqrt {\beta *{\rm{v + (1 - }}\beta {\rm{)*d}}{{\rm{w}}^2}}
w=w−lr∗dw/β∗v+(1−β)∗dw2
其实现代码如下:
# 其中二阶动量的初始值为0,β=0.9
v_w = beta * v_w + (1 - beta) * tf.square(grads[0])
v_b = beta * v_b + (1 - beta) * tf.square(grads[1])
w1.assign_sub(lr * grads[0] / tf.sqrt(v_w))
b1.assign_sub(lr * grads[1] / tf.sqrt(v_b))
6. Adam算法
Adam算法同时结合了RMSProp的二阶动量和SGDM一阶动量。其中m = β1m + (1 - β1)dw,v = β2v - (1 - β2)dw**2,其中修正一阶动量偏差,其中t表示第几次。
m
^
t
=
m
t
1
−
β
1
t
{{\rm{\hat m}}_{\rm{t}}}{\rm{ = }}{{{{\rm{m}}_{\rm{t}}}} \over {{\rm{1 - }}{{\rm{\beta }}_1}^{\rm{t}}}}
m^t=1−β1tmt
修正二阶动量偏差:
v
^
t
=
v
t
1
−
β
2
t
{{\rm{\hat v}}_{\rm{t}}}{\rm{ = }}{{{{\rm{v}}_{\rm{t}}}} \over {{\rm{1 - }}{{\rm{\beta }}_2}^{\rm{t}}}}
v^t=1−β2tvt
所以,其计算公式为:
w
t
+
1
=
w
t
−
l
r
∗
m
t
1
−
β
1
2
/
v
t
1
−
β
2
2
{{\rm{w}}_{{\rm{t + 1}}}}{\rm{ = }}{{\rm{w}}_{\rm{t}}}{\rm{ - lr*}}{{{{\rm{m}}_{\rm{t}}}} \over {{\rm{1 - }}{{\rm{\beta }}_{\rm{1}}}^{\rm{2}}}}{\rm{/}}\sqrt {{{{{\rm{v}}_{\rm{t}}}} \over {{\rm{1 - }}{{\rm{\beta }}_{\rm{2}}}^{\rm{2}}}}}
wt+1=wt−lr∗1−β12mt/1−β22vt
其实现代码如下:
# 其中一阶二阶动量初始值为0,其中beta1 = 0.9,beta2 = 0.99(取经验值)
m_w = beta1 * m_w + (1 - beta1) * grads[0]
m_b = beta1 * m_b + (1 - beta1) * grads[1]
v_w = beta2 * v_w + (1 - beta2) * tf.square(grads[0])
v_b = beta2 * v_b + (1 - beta2) * tf.square(grads[1])
m_w_correction = m_w / (1 - tf.pow(beta1, int(global_step)))
m_b_correction = m_b / (1 - tf.pow(beta1, int(global_step)))
v_w_correction = v_w / (1 - tf.pow(beta2, int(global_step)))
v_b_correction = v_b / (1 - tf.pow(beta2, int(global_step)))
w1.assign_sub(lr * m_w_correction / tf.sqrt(v_w_correction))
b1.assign_sub(lr * m_b_correction / tf.sqrt(v_b_correction))