TensorFlow学习DAY4优化器

优化器

各种优化器对比

  • 标准梯度下降法:先计算所有样本汇总误差,然后根据总误差来更新权值。
  • 随机梯度下降法:随机抽取一个样本来计算误差,然后更新权值
  • 批量梯度下降法:算是一种折中的方案,从总样本选取一个批次(比如一共有10000个样本,随机选取100个样本作为一个batch),然后计算这个batch的总误差,根据总误差来更新权值。

下图为梯度下降法的运行方式

TensorFlow学习DAY4优化器_第1张图片

W:要训练的参数

J(W):代价函数

\bigtriangledown _{w}J(W):代价函数的梯度

\eta:学习率

SGD:

W = W - \eta*\bigtriangledown _{w}J(W;x^{^{(i)}};y^{^{(i)}})


Momentum:

\gamma:动力,通常设置为0.9

v_{t} = \gammav_{t-1} + \eta\bigtriangledown _{w}J(W) 

W = W - v_{t}

当前权值的改变会受到上一次权值改变的影响,类似于小球向下滚动的时候带上了惯性。这样可以加快小球的向下的速度。


NAG(Nesterov accelerated gradient):

v_{t} = \gammav_{t-1} + \eta\bigtriangledown _{w}J(W-\gammav_{t-1} )     

W = W - v_{t}

NAG在TF中跟Momentum合并在同一个函数tf.train.MomenrumOptimizer中,可以通过参数配置启用。在Momenrum中小球会盲目地跟从下坡的梯度,容易发生错误,所以我们需要一个更聪明的小球,这个小球提前知道它要去哪里,它还要知道走到坡底的时候速度慢下来而不是又冲上另一个坡。\gammav_{t-1} 会用来修改W的值,计算W-\gammav_{t-1} 可以表示小球的下一个位置大概在哪里。从而我们可以提前计算下一个位置的梯度,然后使用到当前位置。


Adagrad:

i:代表第i个分类

t:代表出现次数

\varepsilon:作用是避免分母为0,取值一般为1e-8

\eta:取值一般为0.01

g_{t,i}  = \bigtriangledown _{w}J(W) :第i个分类代价函数的梯度

公式:

它是基于SGD的一种算法,它的核心思想是对比较常见的数据给予它比较小的学习率去调整参数,对于比较罕见的数给予它比较大的学习率去调节参数。它很适合应用于数据稀疏的数据集(比如一个图片数据集,有10000张狗的照片。10000张猫的照片,只有100张大象的照片)。

Adagrad主要的优势在于不需要人为的调节学习率,它可以自动调节。它的缺点在于,随着迭代次数的增多,学习率也会越来越低,最终会趋向于0。


RMSprop:

RMS(Root  Mean Square)是均方根的缩写。

\gamma:动力,通常设置为0.9

\eta:取值一般为0.001

E[g^{2}]_{t}:表示前t次的梯度平方的平均值

g_{t} = \bigtriangledown _{w}J(W)

E[g^{2}]_{t} = \gamma E[g^{2}]_{t-1} + (1-\gamma )g^{2}_{t}:t-1次梯度平方的平均值加上当前梯度的平方

公式:

RMSprop借鉴了一些Adagrad的思想,不过这里RMSprop只用了前t-1次梯度平方的平均值加上当前梯度的平方的和的开平方作为学习率的分母。这样RMSprop不会出现学习率越来越低的问题,而且也能自己调节学习率,并且可以有一个比较好的结果。


Adadelta

g_{t} = \bigtriangledown _{w}J(W)

TensorFlow学习DAY4优化器_第2张图片

最下面的式子:分子是对上一次的\bigtriangledown _{w}求均方根,分母是对当前的梯度求均分根

使用Adadelta我们甚至不需要设置一个默认学习率,在Adadelta不需要使用学习率也可以达到一个非常好的效果。


Adam:

\beta _{1}:一般取值为0.9

\beta _{2}:一般取值为0.999

\varepsilon:作用是避免分母为0,取值一般为10^{-8}

m_{t} = \beta_{1}m_{t-1} +(1-\beta_{1})g_{t}

v_{t} = \beta_{2}v_{t-1} +(1-\beta_{2})g^{2}_{t}

\widehat{m}_{t} = \frac{m_{t}}{1-\beta^{t}_{1}}

\widehat{v}_{t} = \frac{v_{t}}{1-\beta^{t}_{2}}

就像Adadelta和RMSprop一样Adam会存储之前衰减的平方梯度,同时它也会保存之前衰减的梯度。经过一些处理之后再使用类似Adadelta和RMSprop的方式更新参数。

选优化方法要视情况而定。虽然有可能SGD速度非常慢,但是最后得到的结果准确率有可能是最高的。

代码如下:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("MNIST_data",one_hot=True)

#每个批次的大小
batch_size = 100
#计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_size

#定义两个placeholder
x = tf.placeholder(tf.float32,[None,784])
y = tf.placeholder(tf.float32,[None,10])

#创建一个简单的神经网络
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
prediction = tf.nn.softmax(tf.matmul(x,W)+b)

#二次代价函数
# loss = tf.reduce_mean(tf.square(y-prediction))
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction))
#使用梯度下降法
# train_step = tf.train.GradientDescentOptimizer(0.2).minimize(loss)
train_step = tf.train.AdamOptimizer(1e-2).minimize(loss)

#初始化变量
init = tf.global_variables_initializer()

#结果存放在一个布尔型列表中
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))#argmax返回一维张量中最大的值所在的位置
#求准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

with tf.Session() as sess:
    sess.run(init)
    for epoch in range(21):
        for batch in range(n_batch):
            batch_xs,batch_ys =  mnist.train.next_batch(batch_size)
            sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys})
        
        acc = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
        print("Iter " + str(epoch) + ",Testing Accuracy " + str(acc))

输出结果如下:

TensorFlow学习DAY4优化器_第3张图片

可见效果还是可以的。

你可能感兴趣的:(tensorflow,深度学习)