优化器整理

梯度下降优化算法

标准梯度下降法(GD)

在这里插入图片描述
在这里插入图片描述

标准梯度下降法主要有两个缺点:
  • 训练速度慢:每走一步都要要计算调整下一步的方向,下山的速度变慢。在应用于大型数据集中,每输入一个样本都要更新一次参数,且每次迭代都要遍历所有的样本。会使得训练过程及其缓慢,需要花费很长时间才能得到收敛解。
  • 容易陷入局部最优解:由于是在有限视距内寻找下山的反向。当陷入平坦的洼地,会误以为到达了山地的最低点,从而不会继续往下走。所谓的局部最优解就是鞍点。落入鞍点,梯度为0,使得模型参数不在继续更新。

批量梯度下降法(BGD)

在这里插入图片描述

梯度下降中的困难

小小批量梯度下降不能保证良好的收敛性,还存在一些其他的问题:

  • 很难选择一个合适的学习率,如果学习率太小,将会导致收敛非常缓慢;如果学习率太大,也会阻碍收敛,导致损失函数值在最小值附近波动甚至发散。
  • 上述问题可以通过提前定义一个学习速率表,当达到相应轮数或者阈值时根据表改变学习率,但是这样无法适应训练数据本身特征。
  • 对于所有参数我们使用同一个学习速率,如果我们的数据是稀疏的或者我们特征具有不同的频率,我们可能不希望将它们更新到同样的程度,并且我们希望对那些出现频率低的特征更新更快。
  • 在神经网络中,普遍是具有非凸的误差函数,这使得在优化网络过程中,很容易陷入无数的局部最优点,而且更大困难往往也不是陷入局部最优点,而是来自鞍点(也就是在一个维度上其梯度是递增,另一个维度其梯度是递减,而在鞍点处其梯度为0),这些鞍点附近往往被相同误差点所包围,且在任意维度梯度近似为0,所以随机梯度下降很难从这些鞍点逃出。
    在这里插入图片描述

梯度下降优化算法

用于解决上述困难的算法,这些算法有个共同之处,一般是求一阶动量(m)和二阶动量(V),然后利用一阶、二阶动量本身或者他们组合来优化梯度下降(其中一阶动量为与梯度相关函数,二阶动量为与梯度平方相关的函数)
在这里插入图片描述

动量(momentum)

随机梯度下降的方法很难通过峡谷区域(也就是在一个维度梯度变化很大,另一个维度变化较小),这个很好理解,因为梯度下降是梯度更新最大的反方向,如果这个时候一个维度梯度变化很大,那么就很容易在这个方向上振荡,另一个方向就更新很慢

  • 没有加动量
    在这里插入图片描述
    加了动量的方法
    在这里插入图片描述
    有动量可以在变化小的维度上加快更新,使得加快收敛。该方法是通过添加一个参数β构建一个一阶动量m
    在这里插入图片描述
    在这里插入图片描述
    “从本质上说,动量法,就像我们从山上推下一个球,球在滚下来的过程中累积动量,变得越来越快(直到达到终极速度,如果有空气阻力的存在,则γ<1)。同样的事情也发生在参数的更新过程中:对于在梯度点处具有相同的方向的维度,其动量项增大,对于在梯度点处改变方向的维度,其动量项减小。因此,我们可以得到更快的收敛速度,同时可以减少摇摆。”
    根据表达式2,梯度方向是一直向下的,自然参数更新幅度也就是一直累加的,也就变得越来越大;而当遇到山沟,越过山沟此时就在另一边山坡,这个时候梯度方向是跟之前相反的,此时由于之前梯度大小的累加,在两个山坡间的变化就会被互相抵消掉,也就不会一直在两个山坡振荡,容易朝山沟向下走,也就是减少摇摆了

NAG(Nesterov accelerated gradient)

在这里插入图片描述
在这里插入图片描述

Adagrad

用一批数据训练网络,这个数据中只有少部分数据含有某个特征,另一个特征几乎全部数据都具有,当这些数据通过训练时,对于不同特征我们假设对应于不同的神经元权重,对于都含有的特征,这些神经元对应参数更新很快,但是对于那些只有少部分数据含有的特征,对应神经元权重获得更新机会就少,但是由于学习率一样,这样可能导致神经网络训练的不充分。
  adagrad算法就是为了解决这个问题,让学习率学习数据的特征自动调整其大小,adagrad算法引入了二阶动量
在这里插入图片描述
但是adagrad同样也有问题,就是其分母随着训练数增加,也会跟着增加,这样会导致学习速率越来越小,最终变的无限小,从而无法有效更新参数

#Adagrad
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))

adadelta

在这里插入图片描述
对于adagrad算法带来的分母越来越大的问题就可以解决了,但是,此算法以及之前提到的算法(SGD、动量、adagrad)的参数之间单位并不匹配,而按理说参数更新应该具有与参数相同的单位。
对随机梯度下降算法(SGD)来进行参数之间单位关系讨论
SGD算法的参数更新方程式为
在这里插入图片描述

假设loss的单位为b,而参数的单位为c,学习率没有单位,设为1,这个时候我们就发现,上面的等式的单位运算为:c=c-1*(b/c),这明显单位不匹配
解决方法就是利用与二阶动量V(t)类似的运算对参数变化量deta(θ)做运算求它的二阶动量
在这里插入图片描述

RMSprop

在这里插入图片描述

#RMSProp
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))

Adam

Adam(Adaptive Moment Estimation)自适应矩估计,是另一种自适应学习率的算法,它是一种将动量和Adadelta或RMSprop结合起来的算法,也就引入了两个参数β1和β2,其一阶和二阶动量公式为:
在这里插入图片描述
发现一阶和二阶动量初始训练时很小,接近为0,因为β值很大,重新计算一个偏差来校正:
在这里插入图片描述
在这里插入图片描述

#Adam
m_w=0
m_b=0
v_w=0
v_b=0
beta1=0.9
beta2=0.999
delta_w=0
delta_b=0
global_step=0

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))

AdaMax

在这里插入图片描述

在这里插入图片描述

Nadam

Adam将RMSprop和动量结合起来,我们也可以看到NAG其实比动量表现更好。
Nadam(Nesterov-accelerated Adaptive
Moment Estimation),Nesterov加速的自适应矩估计,将adam和NAG结合起来,为了将NAG添加到Adam,我们需要对动量部分进行一些改变
将NAG梯度更新公式变为:
在这里插入图片描述
在这里插入图片描述

AMSGrad

随着自适应学习速率的方法成为训练神经网络的规范,研究者就发现,在一些情况下比如目标识别、机器翻译领域,自适应学习速率的方法无法收敛到最佳情况,并且弱于基于动量的随机梯度下降。
其梯度更新公式为:
在这里插入图片描述

梯度下降变形形式

批量归一化(BGD)

每次经过完整一轮训练后更新一次参数,这使得梯度下降过程变得比较慢,并且需要很大内存保存中间结果。

for i in range(nb_epochs):
  params_grad = evaluate_gradient(loss_function, data, params)
  params =params - learning_rate * params_grad

随机梯度下降(SGD)

随机梯度下降是对每个训练样本就更新一次网络参数,这样使得网络更新参数速度很快,但是问题就是由于训练数据多样,容易朝偏离网络最优点方向训练,网络训练不稳定。

for i in range(nb_epochs):
    np.random.shuffle(data)
    for example in data:
        params_grad= evaluate_gradient(loss_function, example, params)
        params =params - learning_rate * params_grad

在这里插入图片描述
在这里插入图片描述

优点
  • 虽然SGD需要走很多步的样子,但是对梯度的要求很低(计算梯度快)。而对于引入噪声,大量的理论和实践工作证明,只要噪声不是特别大,SGD都能很好地收敛。
  • 应用大型数据集时,训练速度很快。比如每次从百万数据样本中,取几百个数据点,算一个SGD梯度,更新一下模型参数。相比于标准梯度下降法的遍历全部样本,每输入一个样本更新一次参数,要快得多。
缺点
  • SGD在随机选择梯度的同时会引入噪声,使得权值更新的方向不一定正确。
  • SGD也没能单独克服局部最优解的问题。

SGDM

SGDM是在SGD的基础上增加了一阶动量,二阶动量仍为1
在这里插入图片描述

#SGDM
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)

小批量梯度下降(MBGD)

小批量梯度下降是批量梯度下降与随机梯度下降之间的一个折中,即经过一个小批量的训练数据更新一次参数,可以保证网络训练速度不太慢,也能使训练方向不至于偏离太多,具有一定稳定性。当使用小批量梯度下降时,通常也使用SGD这个术语。

for i in range(nb_epochs):
    np.random.shuffle(data)
    for batch in get_batches(data, batch_size=50):
        params_grad= evaluate_gradient(loss_function, batch, params)
        params =params - learning_rate * params_grad

应用于简单分类问题的比较

Tensorflow中封装了一系列的优化器
采用选取几种优化器应用于UCI数据集iris.data简单的分类问题

使用SGD优化器

train_step = tf.train.GradientDescentOptimizer(0.2).minimize(loss)
1个训练周期训练集的准确率为:33.3%,  测试集的准确率为:32.2%2个训练周期训练集的准确率为:33.3%,  测试集的准确率为:32.2%3个训练周期训练集的准确率为:38.9%,  测试集的准确率为:35.6%4个训练周期训练集的准确率为:62.2%,  测试集的准确率为:62.7%5个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%6个训练周期训练集的准确率为:66.7%,  测试集的准确率为:67.8%7个训练周期训练集的准确率为:66.7%,  测试集的准确率为:67.8%8个训练周期训练集的准确率为:67.8%,  测试集的准确率为:67.8%9个训练周期训练集的准确率为:67.8%,  测试集的准确率为:67.8%10个训练周期训练集的准确率为:67.8%,  测试集的准确率为:67.8%

使用AdaGrad优化器

train_step = tf.train.AdagradOptimizer(0.01).minimize(loss)
1个训练周期训练集的准确率为:33.3%,  测试集的准确率为:32.2%2个训练周期训练集的准确率为:35.6%,  测试集的准确率为:32.2%3个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%4个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%5个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%6个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%7个训练周期训练集的准确率为:66.7%,  测试集的准确率为:67.8%8个训练周期训练集的准确率为:66.7%,  测试集的准确率为:67.8%9个训练周期训练集的准确率为:67.8%,  测试集的准确率为:69.5%10个训练周期训练集的准确率为:68.9%,  测试集的准确率为:69.5%

从运行结果上可以看出使用AdaGrad优化器相比于SGD似乎没有较大的提升。

使用Momentum优化器

train_step = tf.train.MomentumOptimizer(learning_rate=0.01, momentum=0.9).minimize(loss)
1个训练周期训练集的准确率为:58.9%,  测试集的准确率为:61.0%2个训练周期训练集的准确率为:40.0%,  测试集的准确率为:42.4%3个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%4个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%5个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%6个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%7个训练周期训练集的准确率为:67.8%,  测试集的准确率为:67.8%8个训练周期训练集的准确率为:67.8%,  测试集的准确率为:67.8%9个训练周期训练集的准确率为:67.8%,  测试集的准确率为:69.5%10个训练周期训练集的准确率为:70.0%,  测试集的准确率为:67.8%

Momentum优化器略优于AdaGrad优化器和SGD,但收敛速度要比后两者快(第1-2个训练周期就可以达到60%的准确率)。

使用NAG优化器

train_step = tf.train.MomentumOptimizer(learning_rate=0.01, momentum=0.9, use_nesterov=True).minimize(loss)

1个训练周期训练集的准确率为:37.8%,  测试集的准确率为:39.0%2个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%3个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%4个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%5个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%6个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%7个训练周期训练集的准确率为:66.7%,  测试集的准确率为:67.8%8个训练周期训练集的准确率为:67.8%,  测试集的准确率为:69.5%9个训练周期训练集的准确率为:70.0%,  测试集的准确率为:69.5%10个训练周期训练集的准确率为:71.1%,  测试集的准确率为:69.5%

NAG和Momentum结果差不多,NAG好一点点

使用RMSProp优化器

train_step = tf.train.RMSPropOptimizer(0.01).minimize(loss)

(RMSProp运行结果不稳定,下面是出现比较多的相近结果)

1个训练周期训练集的准确率为:33.3%,  测试集的准确率为:32.2%2个训练周期训练集的准确率为:33.3%,  测试集的准确率为:32.2%3个训练周期训练集的准确率为:35.6%,  测试集的准确率为:35.6%4个训练周期训练集的准确率为:48.9%,  测试集的准确率为:49.2%5个训练周期训练集的准确率为:35.6%,  测试集的准确率为:35.6%6个训练周期训练集的准确率为:38.9%,  测试集的准确率为:42.4%7个训练周期训练集的准确率为:51.1%,  测试集的准确率为:50.8%8个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%9个训练周期训练集的准确率为:60.0%,  测试集的准确率为:62.7%10个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1% 

RMSProp优化器的效果不理想,而且不稳定

使用Adam优化器

train_step = tf.train.AdamOptimizer(0.001).minimize(loss)
1个训练周期训练集的准确率为:33.3%,  测试集的准确率为:33.9%2个训练周期训练集的准确率为:36.7%,  测试集的准确率为:37.3%3个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%4个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%5个训练周期训练集的准确率为:66.7%,  测试集的准确率为:67.8%6个训练周期训练集的准确率为:67.8%,  测试集的准确率为:67.8%7个训练周期训练集的准确率为:67.8%,  测试集的准确率为:67.8%8个训练周期训练集的准确率为:71.1%,  测试集的准确率为:67.8%9个训练周期训练集的准确率为:71.1%,  测试集的准确率为:69.5%10个训练周期训练集的准确率为:71.1%,  测试集的准确率为:69.5%

使用AdaDelta优化器

train_step = tf.train.AdadeltaOptimizer(1).minimize(loss)
1个训练周期训练集的准确率为:60.0%,  测试集的准确率为:64.4%2个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%3个训练周期训练集的准确率为:66.7%,  测试集的准确率为:66.1%4个训练周期训练集的准确率为:66.7%,  测试集的准确率为:67.8%5个训练周期训练集的准确率为:67.8%,  测试集的准确率为:69.5%6个训练周期训练集的准确率为:70.0%,  测试集的准确率为:69.5%7个训练周期训练集的准确率为:72.2%,  测试集的准确率为:71.2%8个训练周期训练集的准确率为:73.3%,  测试集的准确率为:76.3%9个训练周期训练集的准确率为:75.6%,  测试集的准确率为:84.7%10个训练周期训练集的准确率为:76.7%,  测试集的准确率为:88.1%

AdaDelta优化器效果很好

可视化比较

在这里插入图片描述
在这里插入图片描述
参考博客
https://blog.csdn.net/qq_42109740/article/details/105401197?utm_source=app&app_version=4.5.2

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值