深度学习的优化方法及tensorflow实现

深度学习的优化问题

深度学习的优化问题,主要是定义在训练集上的目标函数J(θ)最小,由于目标函数一般是非凸的,此处的最小一般是指一个相对最优的局部极小值。求解目标函数的最小值,可以通过梯度下降法更新模型的参数θ实现。梯度下降法有一个非常好懂的名字叫下山法,也就是在梯度的反方向(值下降的方向)更新参数。与梯度下降法密切相关的是学习率η,学习率决定了每一步沿梯度反方向更新的数值,学习率的选择不仅影响达到最小值的步数,还影响到能否达到最小值。

梯度优化的基础知识

Batch gradient descent

在整个数据集上计算梯度,(1)计算量大但没有得到与计算量成正比的回报。(根据误差传播规律,误差与采样的数量n的关系是,如10000个样本只比100个样本降低了10倍的误差)。(2)训练集是一般是冗余的,使用整个训练集进行梯度计算是没有必要的。

Stochastic gradient descent

随机梯度下降法,在每个批次的训练的过程中将数据集随机打乱,然后对每个样本进行梯度计算并更新参数。随机梯度下降法的优点,计算量小且是有机会跳到更优的位置(如下图所示),当学习率较小的时候其可定可以收敛到的局部或全局最小点。

在这里插入图片描述

Mini-batch gradient descent

大多数用于深度学习梯度优化方法介于批量和随机梯度(SGD)之间,使用一个以上却又不是全部样本,可称为随机小批量梯度下降或小批量梯度下降,其关键在于数据要随机打乱。其既有批量计算的稳定性,由于在小批量的计算过程中加入了一些噪声(梯度更新的时候使用的时小批量梯度的均值),其具有一定的正则性;小批量更能有效率利用计算资源,优于随机梯度和批量梯度法。

梯度优化问题的挑战

  • 1 如何选择合适的学习速率,既加快收敛又保证收敛;

  • 2 如何在训练中根据训练情况相应的调整学习速率;

  • 3 如何根据特征相应的改变学习速率,而不是所有的特征都使用同样的学习速率,如一些特征是低频的,则其对使用大的学习速率,则效果更好;

  • 4 如何避免陷于鞍点,而无法达到最小值;

  • 5 设计易于收敛的模型而不是复杂的优化算法。

梯度优化的基本算法

梯度优化算法的,主要集中在如何实现梯度更合理的更新上,从而提高收敛速度并保证最终优化结果是收敛的。

SGD

SGD第k次训练的迭代
Require:学习速率 εk、初始参数 θ
while 停止准则未满足 do:
 从训练集中采样m个样本{x1…xm}的minibatch,其中xi对应的目标为yi。
 计算梯度估计:  g k = + 1 m ∇ θ ∑ i L ( f ( x i , θ ) , y i ) g_{k}=+\frac{1}{m}\nabla_{\theta}\sum_{i}L(f(x_{i},\theta),y_{i}) gk=+m1θiL(f(xi,θ),yi)
 参数更新:  θ = θ − ϵ k g k \theta=\theta-\epsilon_{k}g_{k} θ=θϵkgk
end while

SGD算法的关键是学习速率,为保证在极小点位置收敛,需要使用较小的较小的学习速率,故需要使用一定的策略,随着迭代次数的增减进行学习速率的衰减。在TensorFlow中SGD可通过tf.train.GradientDescentOptimizer实现,其初始化的时候需要传递学习速率learning_rate,learning_rate可定义为tensor。在 eager execution 激活的情况下,learning_rate可以是一个不带参数的调用,并返回实际使用值(float),可用来进行学习速率的衰减。

#参考实现SGD学习速率的指数衰减:https://blog.csdn.net/leviopku/article/details/78508951
import tensorflow as tf
import numpy as np

x = tf.placeholder(tf.float32, shape=[None, 1], name='x')
y = tf.placeholder(tf.float32, shape=[None, 1], name='y')
w = tf.Variable(tf.constant(0.0))

global_steps = tf.Variable(0, trainable=False)
#学习率的指数衰减
learning_rate = tf.train.exponential_decay(0.1, global_steps, 10, 2, staircase=False)
loss = tf.pow(w*x-y, 2)

train_step= tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_steps)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(10):
        sess.run(train_step, feed_dict={x:np.linspace(1,2,10).reshape([10,1]),
            y:np.linspace(1,2,10).reshape([10,1])})
        print(sess.run(learning_rate))
        print(sess.run(global_steps))

Moment及Nesterov

Moment算法是SGD算法的加速算法加入了动量参数 α \alpha α,其主要思想可解释为如果总是观测到梯度g,那么它会在-g方向不停加速(通俗理解为小球沿着山坡向下滚的过程中速度会越来越快),直到达到最终速度,其最终步长大小为:
ϵ = ϵ ∣ ∣ g ∣ ∣ 1 − α \epsilon=\frac{\epsilon||g||}{1-\alpha} ϵ=1αϵg当动量参数α为0.9的时候,其对应着最大速度10倍于梯度下降法。

Moment第k次训练的迭代
Require:学习速率 ϵ k \epsilon_{k} ϵk、动量参数 α \alpha α
Require:初始参数 θ \theta θ、初始速度 v ( 0 ) v(0) v(0)
while 停止准则未满足 do:
 从训练集中采样m个样本{ x 1 x_{1} x1 x m x_{m} xm}的minibatch,其中 x i x_{i} xi对应的目标为 y i y_{i} yi
 计算梯度估计:  g k = + 1 m ∇ θ ∑ i L ( f ( x i , θ ) , y i ) g_{k}=+\frac{1}{m}\nabla_{\theta}\sum_{i}L(f(x_{i},\theta),y_{i}) gk=+m1θiL(f(xi,θ),yi)
 速度计算:  v = α v − g k v=\alpha{v}-g_{k} v=αvgk
 参数更新:  θ = θ + v \theta=\theta+v θ=θ+v
end while

Nesterov是Moment法的一个变种,二者的区别主要在与梯度的计算上,其可以理解为在标准的动量法中加了一个校正因子。

Nesterov第k次训练的迭代
Require:学习速率 ϵ k \epsilon_{k} ϵk、动量参数 α \alpha α
Require:初始参数 θ \theta θ、初始速度 v ( 0 ) v(0) v(0)
while 停止准则未满足 do:
 从训练集中采样m个样本{ x 1 x_{1} x1 x m x_{m} xm}的minibatch,其中 x i x_{i} xi对应的目标为 y i y_{i} yi
 参数临时更新:  θ ^ = θ + α v \hat{\theta}=\theta+\alpha{v} θ^=θ+αv
 计算梯度估计:  g k = + 1 m ∇ θ ∑ i L ( f ( x i , θ ^ ) , y i ) g_{k}=+\frac{1}{m}\nabla_{\theta}\sum_{i}L(f(x_{i},\hat{\theta}),y_{i}) gk=+m1θiL(f(xi,θ^),yi)
 速度计算:  v = α v − g k v=\alpha{v}-g_{k} v=αvgk
 参数更新:  θ = θ + v \theta=\theta+v θ=θ+v
end while

Moment和Nesterov的思想都是加速度的思想,其基础结构是一致的,故其在tensorflow中是通过tf.train.MomentumOptimizer实现的,默认use_nesterov=False为Moment方法,设置use_nesterov=True,则为Nesterov方法。get_slot函数可用来对动量法过程中新建立的速度进行跟踪。(Some Optimizer subclasses use additional variables. For example Momentum and Adagrad use variables to accumulate updates. This method gives access to these Variable objects if for some reason you need them.)动量法中,即使梯度为零,由于动量的存在其仍然可以进行参数更新。

AdaGrad

AdaGrad是一种自适应学习率的优化算法,其在更新梯度的时候将初始学习率梯度除以累计平方梯度,从而实现对不同参数的梯度调整,主要表现为:对于高频特征(累计平方梯度大),其更新较小;对于稀疏特征(累积平方梯度小),则其更新较大。然而,Goodfellow在深度学习一书中指出“经验上已经发现,对于训练深度神经网络而言,从训练开始累积平方梯度会导致有效学习率过快和过量的减小”。AdaGrad的计算量和存储空间比动量法大。

AdaGrad第k次训练的迭代
Require:全局学习速率 ϵ \epsilon ϵ
Require:初始参数 θ \theta θ
Require:小常数 δ \delta δ,为了数值稳定大约设为1e-7;初始化梯度累积变量r=0
while 停止准则未满足 do:
 从训练集中采样m个样本{ x 1 x_{1} x1 x m x_{m} xm}的minibatch,其中 x i x_{i} xi对应的目标为 y i y_{i} yi
 计算梯度估计:  g k = + 1 m ∇ θ ∑ i L ( f ( x i , θ ) , y i ) g_{k}=+\frac{1}{m}\nabla_{\theta}\sum_{i}L(f(x_{i},\theta),y_{i}) gk=+m1θiL(f(xi,θ),yi)
 累积平方梯度:  r = r + g k ⨀ g k r=r+g_{k}\bigodot{g_{k}} r=r+gkgk
 计算更新量:  Δ θ = − ϵ δ + r ⨀ g k \Delta\theta=-\frac{\epsilon}{\delta+\sqrt{r}}{\bigodot}g_{k} Δθ=δ+r ϵgk
 参数更新:  θ = θ + Δ θ \theta=\theta+\Delta\theta θ=θ+Δθ
end while

Tensorflow中AdaGrad方法的实现tf.train.AdagradOptimizer,初始化的时候需要传递学习率,累加器的默认初始值为0.1。

RMSProp

RMSProp算法修改AdaGrad算法可以在非凸设定下效果更好,其主要做法是改变梯度累积为指数加权平均移动。AdaGrad根据梯度平方的整个历史收缩学习率,可能使得学习率过快、过早的减小。RMSProp算法使用指数衰减p舍弃早期的梯度(早期梯度贡献为 p k p^{k} pk,默认为0.9),使得学习速率不会过快减小,从而能在极小值处快速收敛。

RMSPropd第k次训练的迭代
Require:全局学习速率 ϵ \epsilon ϵ,衰减率 ρ \rho ρ
Require:初始参数 θ \theta θ
Require:小常数 δ \delta δ,为了数值稳定大约设为1e-7;初始化梯度累积变量r=0
while 停止准则未满足 do:
 从训练集中采样m个样本{ x 1 x_{1} x1 x m x_{m} xm}的minibatch,其中 x i x_{i} xi对应的目标为 y i y_{i} yi
 计算梯度估计:  g k = + 1 m ∇ θ ∑ i L ( f ( x i , θ ) , y i ) g_{k}=+\frac{1}{m}\nabla_{\theta}\sum_{i}L(f(x_{i},\theta),y_{i}) gk=+m1θiL(f(xi,θ),yi)
 累积平方梯度:  r = ρ r + ( 1 − ρ ) g k ⨀ g k r=\rho{r}+(1-\rho)g_{k}\bigodot{g_{k}} r=ρr+(1ρ)gkgk
 计算更新量:  Δ θ = − ϵ δ + r ⨀ g k \Delta\theta=-\frac{\epsilon}{\delta+\sqrt{r}}{\bigodot}g_{k} Δθ=δ+r ϵgk
 参数更新:  θ = θ + Δ θ \theta=\theta+\Delta\theta θ=θ+Δθ
end while

Tensorflow中的RMSProp算法与上面描述的略有不同,其增加了动量项(非Nesterov),可以在梯度为零的情况下实现对参数的更新。Tensorflow中通过tf.train.RMSPropOptimizer实现,默认的decay=0.9,momentmun=0.0。

Adam

Adam修正了从原点开始的一阶矩(动量)和(非中心)二阶矩的估计,Adam对超参数的选择相当鲁棒。

Adam第k次训练的迭代
Require:全局学习速率 ϵ \epsilon ϵ(默认为0.001,常需要修改变小)
Require:初始参数 θ \theta θ
Require:小常数 δ \delta δ,为了数值稳定大约设为1e-8;
Require:矩估计衰减率, ρ 1 、 ρ 2 \rho_{1}、\rho_{2} ρ1ρ2,在区间[0,1),默认为0.9, 0.999
初始化一阶矩、二阶矩变量s=0,r=0,初始化时间步t=0
while 停止准则未满足 do:
 从训练集中采样m个样本{ x 1 x_{1} x1 x m x_{m} xm}的minibatch,其中 x i x_{i} xi对应的目标为 y i y_{i} yi
 计算梯度估计:  g k = + 1 m ∇ θ ∑ i L ( f ( x i , θ ) , y i ) g_{k}=+\frac{1}{m}\nabla_{\theta}\sum_{i}L(f(x_{i},\theta),y_{i}) gk=+m1θiL(f(xi,θ),yi)
         t = t + 1 t=t+1 t=t+1
 更新有偏一阶估计: s = ρ 1 s + ( 1 − ρ 1 ) g k s=\rho_{1}s+(1-\rho_{1})g_{k} s=ρ1s+(1ρ1)gk
 更新有偏二阶估计: r = ρ 2 r + ( 1 − ρ 2 ) g k ⨀ g k r=\rho_{2}{r}+(1-\rho_{2})g_{k}\bigodot{g_{k}} r=ρ2r+(1ρ2)gkgk
 修正一阶矩的偏差: s = s 1 − ρ 1 t s=\frac{s}{1-{\rho_{1}}^{t}} s=1ρ1ts
 修正二阶矩的偏差: r = r 1 − ρ 2 t r=\frac{r}{1-{\rho_{2}}^{t}} r=1ρ2tr
 计算更新量:  Δ θ = − ϵ s δ + r \Delta\theta=-\epsilon\frac{s}{\delta+\sqrt{r}} Δθ=ϵδ+r s
 参数更新:  θ = θ + Δ θ \theta=\theta+\Delta\theta θ=θ+Δθ
end while

总结

下图所示为各种梯度优化算法的可视化,从效果来看SGD(较小的学习率)、Adadelta、Rmsprop比较稳定,收敛速度自适应学习率算法比较接近。Goodfellow在《深度学习》一书中也指出优化算法的选择没有明确的指标可以衡量,选择算法似乎主要取决于使用者对算法的熟悉度。


优化算法的可视化
图片引自http://ruder.io/optimizing-gradient-descent/

参考

(1)http://ruder.io/optimizing-gradient-descent/
(2)http://ruder.io/deep-learning-optimization-2017/
(3)深度学习[M]-第8章深度学习中的优化

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TensorFlow 2是一个用于构建和训练机器学习模型的开源库,它提供了许多功能和工具,可以方便地实现图像分类任务。 首先,我们需要安装TensorFlow 2库。可以通过以下命令在Python环境中安装TensorFlow 2: ```python !pip install tensorflow ``` 完成安装后,我们可以导入TensorFlow库并加载数据集。在图像分类任务中,通常使用的是包含图像和对应标签的数据集。可以使用TensorFlow内置的数据集加载器加载常见的图像数据集,例如MNIST、CIFAR-10等。 接下来,我们需要构建模型架构。TensorFlow提供了多种建模API,其中最常用的是Keras API。可以使用Keras提供的各种层来构建模型,如卷积层、池化层、全连接层等。 在构建模型架构后,我们需要选择适当的优化算法和损失函数。优化算法用于更新模型的权重以最小化损失,损失函数用于衡量模型输出与真实标签之间的差距。TensorFlow提供了许多常见的优化算法和损失函数供选择,例如梯度下降、Adam优化器和交叉熵损失函数。 进行模型训练前,我们需要对数据进行预处理。预处理的步骤可能包括调整图像大小、归一化像素值、数据增强等。可以使用TensorFlow提供的图像处理工具来完成这些预处理步骤。 最后,我们可以使用训练集对模型进行训练,并使用验证集对模型进行评估。可以使用TensorFlow提供的训练循环API进行模型的训练和评估,如fit()和evaluate()。 通过上述步骤,我们可以在TensorFlow 2中实现图像分类任务。具体代码实现可能因数据集、模型结构和训练需求的不同而有所差异,但总体流程大致相似。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值