TFLearn初探之optimizers、losses和learning_rate

# optimizers优化器

[optimizers源码] (https://github.com/tflearn/tflearn/blob/5a674b7f7d70064c811cbd98c4a41a17893d44ee/tflearn/optimizers.py)

[optimizers定义](http://tflearn.org/optimizers/#base-optimizer-class)

Base Optimizer class
tflearn.optimizers.Optimizer (learning_rate, use_locking, name)

A basic class to create optimizers to be used with TFLearn estimators. First, The Optimizer class is initialized with given parameters, but no Tensor is created. In a second step, invoking get_tensor method will actually build the Tensorflow Optimizer Tensor, and return it.

This way, a user can easily specifies an optimizer with non default parameters and learning rate decay, while TFLearn estimators will build the optimizer and a step tensor by itself.

Arguments
learning_rate: float. Learning rate.
use_locking: bool. If True use locks for update operation.
name: str. The optimizer name.
Attributes
tensor: Optimizer. The optimizer tensor.
has_decay: bool. True if optimizer has a learning rate decay.
Methods
build (step_tensor=None)

This method creates the optimizer with specified parameters. It must be implemented for every Optimizer.

Arguments
step_tensor: tf.Tensor. A variable holding the training step. Only necessary when optimizer has a learning rate decay.
get_tensor (self)

A method to retrieve the optimizer tensor.

Returns
The Optimizer.

**optimizers派生类**

tf.train.Optimizer
tf.train.GradientDescentOptimizer
tf.train.AdadeltaOptimizer
tf.train.AdagradOptimizer
tf.train.AdagradDAOptimizer
tf.train.MomentumOptimizer
tf.train.AdamOptimizer
tf.train.FtrlOptimizer
tf.train.ProximalGradientDescentOptimizer
tf.train.ProximalAdagradOptimizer
tf.train.RMSPropOptimizer

## Optimizers解读

[Optimizer相关的函数与功能介绍](https://blog.csdn.net/shenxiaoming77/article/details/77169756

optimizers优化器:通常与TFLearn的estimators一起使用。TFLearn中提供了各种优化类,用于损失函数计算梯度的方法,其中包含比较经典的优化算法。其实现原理见下表。

class tf.train.Optimizer

操作 描述
class tf.train.Optimizer 基本的优化类,该类不常常被直接调用,而较多使用其子类,
比如GradientDescentOptimizer, AdagradOptimizer
或者MomentumOptimizer
tf.train.Optimizer.__init__(use_locking, name) 创建一个新的优化器,
该优化器必须被其子类(subclasses)的构造函数调用
tf.train.Optimizer.minimize(loss, global_step=None, 
var_list=None, gate_gradients=1, 
aggregation_method=None, colocate_gradients_with_ops=False, 
name=None, grad_loss=None)
添加操作节点,用于最小化loss,并更新var_list
该函数是简单的合并了compute_gradients()与apply_gradients()函数
返回为一个优化更新后的var_list,如果global_step非None,该操作还会为global_step做自增操作
tf.train.Optimizer.compute_gradients(loss,var_list=None, gate_gradients=1,
aggregation_method=None, 
colocate_gradients_with_ops=False, grad_loss=None)
对var_list中的变量计算loss的梯度
该函数为函数minimize()的第一部分,返回一个以元组(gradient, variable)组成的列表
tf.train.Optimizer.apply_gradients(grads_and_vars, global_step=None, name=None) 将计算出的梯度应用到变量上,是函数minimize()的第二部分,返回一个应用指定的梯度的操作Operation,对global_step做自增操作
tf.train.Optimizer.get_name() 获取名称

### Optimizers的作用

在训练阶段, 每一次训练,神经网络参数都将得到一次拟合,达到一定次数后,才会收敛。而每次收敛的调整节奏,则取决于优化器,而优化器中的常用算法分为(

(1)朴素梯度下降

- 批量梯度下降法(Batch Gradient Descent )

- 随机梯度下降法(Stochastic Gradient Descent)

- 小批量随机梯度下降(Mini-Batch Gradient Descent)

- 带有动量的随机梯度下降(SGD with momentum)

(2) 自适应梯度下降

-  Adagrad (Adaptive gradient algorithm)

-  Adadelta/RMSProp

-  Adam(Adaptive Moment Estimation)

- NAdam 

## 各种优化器

[深度学习相关优化器以及在tensorflow的使用](https://blog.csdn.net/winycg/article/details/79363169

### 朴素优化器(Vanilla Optimizers)

朴素梯度下降最为简单,没有动量的概念,即: 
所以更新步骤为: 
首先为梯度下降最常见的三种变形BGD,SGD,MBGD,这三种优化器的区别为用多少数据计算目标函数的梯度

1. 批量梯度下降法(Batch gradient descent

更新规则:采用整个训练集的数据来计算loss函数对参数的梯度: 

算法: 


for i in range ( nb_epochs ): 
 params_grad = evaluate_gradient ( loss_function , data , params ) 
 params = params - learning_rate * params_grad 
优点:对于凸函数可以收敛到全局极小值,对于非凸函数可以收敛到局部极小值 
缺点:在一次更新中,对整个数据集计算梯度,计算速度很慢;如果数据集过大,则内存无法容纳;在模型训练过程中,无法使用新的数据更新模型。

2.随机梯度下降Stochastic gradient descent

更新规则: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 
优点:对于很大的数据集来说,可能有很相似的样本,导致BGD在计算梯度时会出现冗余,而SGD一次只进行单样本更新,所以针对一次更新来说没有冗余,而且速度快 
缺点:更新频繁,造成loss函数严重震荡。 

BGD可以收敛到局部最小值,SGD的震荡也可能跳到更优的局部最小值。稍微减少learning rate,SGD和BGD收敛性一致,对凸函数和非凸函数能分别收敛到全局最优和局部最优。

3.小批量梯度下降Mini-batch Stochastic gradient descent

梯度更新规则:每一次更新使用一小批样本进行更新

和 SGD 的区别是每一次循环不是作用于每个样本,而是具有 n 个样本的批次。

 
超参数:一般取值为50~256,取决于不同的应用 
优点:降低参数更新时的方差,收敛更稳定;可利用深度学习库中高度优化的矩阵操作来更有效的梯度计算 
**缺点:****MBSGD不能保证很好的收敛性,提供了一系列的挑战需要去解决: 
1.选择合适的learning rate十分困难。如果选择的太小,收敛速度太慢;如果太大,loss函数会在极小值出震荡甚至发散。 
2.学习率在训练过程中退火调整,学习率的减少根据提前确定好的计划或者当目标在两个轮次之间的变化低于一个阈值,计划和阈值必须要提前确定,因此不能适应数据集的特征。 
3.对所有参数更新时应用同样的learning rate,如果数据是稀疏的,更希望对出现频率低的特征进行大一点的更新。 
4.对于非凸的误差函数,要避免陷入局部极小值以及鞍点处。鞍点周围的梯度都一样并且趋近于0,SGD不容易突破。

 

4.含有动量的随机梯度下降法SGD with momentum

SGD在山谷的情况下不容易导向,会多走一些弯路,山谷的曲面在某一个参数维度会比另外一个参数维度更陡峭,这种情况在局部最优解附近很常见。在这种场景下,SGD穿过山谷的斜坡时会震荡。 
这里写图片描述
momentum能帮助加速SGD在确定方向的下降并且抑制震荡。 
超参数一般设为0.9左右,意味着参数更新方向不仅由当前梯度决定,也与此前累计的下降方向有关,这使得momentum会增加更新某个维度下降方向不变的梯度,减少更新某个维度下降方向改变的梯度。因此获得了更快的收敛性和减少了震荡。

 

### 自适应优化器(含动量)

1.AdaGrad

针对SGD及Momentum存在的问题,2011年John Duchi等发布了AdaGrad(Adaptive Gradient,自适应梯度)优化算法,能够对每个不同参数调整不同的学习率,对频繁变化的参数以更小的步长进行更新,而稀疏的参数以更大的步长更新。对稀疏的数据表现很好,提高了SGD的鲁棒性。(典型例子:更新word embedding中的低频词,单次步长更大,多学习一些知识;多频词,步长较小,使得学习到的参数更稳定,不至于单个样本影响太多) 
在AdaGrad中,参数会根据之前的梯度修改学习率,引入二阶动量,梯度更新规则:

 
是对角矩阵,其对角元素为参数从初始步到第步的梯度平方和,即。与SGD相比,此时学习率等效为,多加了梯度平方累计和的平方根,使得频繁更新的梯度,则累计的分母项逐渐变大,则更新的步长变小;稀疏的梯度,更新的步长会变大。 
优点:能够为不同参数应不同的学习率,大多数学习率(η)使用0.01为默认值可实现较好的效果。 
缺点:分母项对梯度平方进行不断的累加,分母项越来越大,最终学习率收缩到无穷小使得无法进行有效更新。

2.Adadelta/RMSProp

为了解决AdaGrad单调递减的学习率急速下降的问题,考虑一个改变二阶动量计算方法的策略:不累积全部梯度,而只关注过去一段时间窗口的下降梯度,这就是delta中的来历。 
采用计算梯度的指数移动平均数(Exponential Moving Average) 

这个算法是对 Adagrad 的改进,

和 Adagrad 相比,就是分母的 G 换成了过去的梯度平方的衰减平均值,指数衰减平均值

这个分母相当于梯度的均方根 root mean squared (RMS),在数据统计分析中,将所有值平方求和,求其均值,再开平方,就得到均方根值 ,所以可以用 RMS 简写:

其中 E 的计算公式如下,t 时刻的依赖于前一时刻的平均和当前的梯度:

梯度更新规则:

此外,还将学习率 η 换成了 RMS[Δθ],这样的话,我们甚至都不需要提前设定学习率了:

超参数设定值:  γ 一般设定为 0.9, 学习率为0.001

这样可以避免二阶动量持续累积,导致训练过程提前结束的问题。

3.Adam

可以认为是RMSprop和Momentum的结合。对一阶动量和二阶动量都采用指数移动平均计算。 
默认为0.9,默认为0,999。初始值为 在迭代初始阶段,和有一个向初值的偏移(过多偏向0),因此需要对一阶和二阶动量进行偏置校正(bias correction) 

迭代式为: 

梯度更新规则:

超参数设定值:
建议 β1 = 0.9,β2 = 0.999,ϵ = 10e−8

实践证明,Adam比其他适应性学习方法要好

4.NAdam

在Adam上融入了NAG思想。NAG核心在于计算梯度时使用了未来位置。NAdam提出一种公式变形思路:在计算梯度时,可以仍然使用原始公式,但在前一次迭代计算时,就使用了未来时刻动量,即,理论上达到的效果类似。 
理论上,,在假定梯度连续变化不大的情况下,即,,此时,即可用近似表示未来动量。 
 

## 优化器的选择

(1)如果数据是稀疏的,使用自适应学习方法。 即 Adagrad, Adadelta, RMSprop, Adam。
(2)RMSprop,Adadelta,Adam是非常相似的优化算法,Adam的bias-correction帮助其在最后优化期间梯度变稀疏的情况下略微战胜了RMSprop。整体来讲,Adam是最好的选择。 
(3)很多论文中使用vanilla SGD without momentum。SGD通常能找到最小值,但是依赖健壮的初始化,并且容易陷入鞍点。因此,如果要获得更快的收敛速度和训练更深更复杂的神经网络,需要选择自适应学习方法。

多采用几个优化器进行测试,然后选择效果最好的优化器。

SGD optimization on saddle point上面两种情况都可以看出,Adagrad, Adadelta, RMSprop 几乎很快就找到了正确的方向并前进,收敛速度也相当快,而其它方法要么很慢,要么走了很多弯路才找到。

## 优化器的使用

TFLearn中使用优化器十分简便,可直接指定官方的优化器即可。

net = tflearn.input_data(shape=[None, 8192])
net = tflearn.fully_connected(net, 64)
net = tflearn.dropout(net, 0.5)
net = tflearn.fully_connected(net, number_classes, activation='softmax')
net = tflearn.regression(net, optimizer='adam', loss='categorical_crossentropy')

参考:[深度学习优化器算法Optimizer详解](https://www.cnblogs.com/guoyaohua/p/8542554.html)

          [关于深度学习优化器 optimizer 的选择](https://blog.csdn.net/g11d111/article/details/76639460)

# losses损失函数

[losses解释](http://tflearn.org/losses/)

## 损失函数的解释

损失函数定义了我们想要最小化的数量。 对于分类问题,这通常是跨分类的真实分布和预测概率分布之间的交叉熵。 对于回归问题,这通常是预测值和真值之间的平方和差异。
某些模型(如多任务学习模型)需要同时使用多个损失函数。 换句话说,最终被最小化的损失函数是各种其他损失函数的总和。 例如,考虑预测图像中的场景类型以及每个像素的相机深度的模型。 这个模型的损失函数将是分类损失和深度预测损失的总和。

[tensorflow学习之损失函数设置和参数优化](https://blog.csdn.net/u011012422/article/details/72808898?utm_source=itdadao&utm_medium=referral)

关于损失函数,先看神经网络问题的类别 :

### 分类问题:

#### 交叉熵(crossentropy)

分类问题中,因为是将数据分成有限类,因此自然而然想到的就是通过概率来判断属于哪一类,概率最大的就是结果。针对概率,一般是用交叉熵来作损失函数,交叉熵刻画的是两个概率分布之间的距离。其方程如下:

其中y为真实数据的概率分布(如[1,0,0]表示三分类中的第一类,可看成概率分布),pred为神经网络输出的概率分布。

然而全连接神经网络的输出并非是一个概率分布,因此需要人为的对输出进行进一步的处理,即所谓的softmax层。他的作用是将网络的输出全部压缩至0-1之间,并且和为1,因此可以将其输出看做概率分布。其公式如下:

### 回归问题:

回归问题是对具体数值的预测,即预测的是任意实数。

示例代码如下:

#### 均方误差

均方误差(MSE,mean squared error)其定义为:

均方误差亦可用于分类问题。

## loss的运用

例如在线性回归中,我们使用 均方差。‘mean_square’

# regression
input_ = tflearn.input_data(shape=[None])
linear = tflearn.single_unit(input_)
regression = tflearn.regression(linear, optimizer='sgd', loss='mean_square', metric='R2', learning_rate=0.01)

# learning_rate学习率

属于网络优化的范畴,学习率(learning_rate)可理解为每一次梯度下降的步长,一般设置学习率小于0.1,具体多少其实算是一门玄学,全靠经验。当学习率过大时,可能导致参数在最低点附近来回震荡,始终到达不了最优点;当学习率过小时,前期梯度下降的速度极其慢,浪费时间。所以最优的方法是前期学习率设置大点,让梯度迅速下降,随后慢慢将学习率减小,以求达到最优点。

其中0.01为初始学习率;表示步长为0.01,每次调整的单位为0.01。

# regression
input_ = tflearn.input_data(shape=[None])
linear = tflearn.single_unit(input_)
regression = tflearn.regression(linear, optimizer='sgd', loss='mean_square', metric='R2', learning_rate=0.01)

猜你喜欢

转载自blog.csdn.net/ajian0051/article/details/82557017
今日推荐