Tensorflow的优化器
Tensorflow中包含如下几个优化器:
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.RMSPropOptimize
标准梯度下降法: 先计算所有的样本汇总误差,然后根据误差来更新权值
随机梯度下降法:随机抽取一个样本来计算,误差,然后更新权值。 但是容易跑错方向。
批量梯度下降法:这种的方法,从总样本中选取i个批次,让后计算这个批次的总误差,根据总误差来更新权值。
主要想解决的问题是:标准梯度下降法速度太慢的问题
SGD:
就是随机梯度下降法
Momentum:
当前权值的改变会受到上一次权值改变的影响,类似于小球向下滚动的时候带上了惯性。这样可以加快小球的向下的速度。 总结:动力项相当于惯性,训练的速度会很快,但是会走很多弯路。
NAG:
在TF中跟Momentum合并在同一个函数tf.train.MomentumOptimizer中,可以通过参数配置启用。在Momentun中小球会盲目地跟从下坡的梯度,容易发生错误,所以我们需要一个更聪明的小球,这个小球提前知道它要去哪里,它还要知道走到坡底的时候速度慢下来而不是又冲上另一个坡,知道下一个位置大概在哪里。从而我们可以提前计算下一个位置的梯度,然后使用到当前位置。
Adagrad:
它是基于SGD的一种算法,它的核心思想是对比较常见的数据给予它比较小的学习率去调整参数,对于比较罕见的数据给予它比较大的学习率去调整参数。它很适合应用于数据稀疏的数据集(比如一个图片数据集,有10000张狗的照片,10000张猫的照片,只有100张大象的照片)。Adagrad主要的优势在于不需要人为的调节学习率,它可以自动调节。它的缺点在于,随着迭代次数的增多,学习率也会越来越低,最终会趋向于0。
RMSprop:
借鉴了一些Adagrad的思想,不过这里RMSprop只用到了前t-1次梯度平方的平均值加上当前梯度的平方的和的开平方作为学习率的分母。这样RMSprop不会出现学习率越来越低的问题,而且也能自己调节学习率,并且可以有一个比较好的效果。
Adadelta:
我们甚至不需要设置一个默认学习率,在Adadelta不需要使用学习率也可以达到一个非常好的效果。
Adam:
像Adadelta和RMSprop一样,Adam会存储之前衰减的平方梯度,同时它也会保存之前衰减的梯度。经过一些处理之后再使用类似Adadelta和RMSprop的方式更新参数。
每一种优化器都有一种适用范围。
速度是模型收敛的速度。
我们比的不是速度,比的是准确率。
准确率越高,速度也要快,才是好的。
出论文,发结果,需要把所有的优化器都跑一遍。
优化器的使用
#二次代价函数
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y, logits=prediction)) #logits预测值
#交叉熵来定义交叉函数:加快模型的收敛速度,可以迭代比较少的周期,得到一个比较好的结果
#使用新的训练方式
train_step = tf.train.AdamOptimizer(1e-3).minimize(loss) # Adam中学习率一般调的比较小
import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)
batch_size = 100
n_batch = int(mnist.train.num_examples // batch_size)
x = tf.placeholder(tf.float32, [None, 784]) # None和批次有关系
y = tf.placeholder(tf.float32, [None, 10]) # label
keep_prob = tf.placeholder(tf.float32) #设置dropout
lr = tf.Variable(0.001, dtype=tf.float32) #x学习率
#创建一个简单的神经网络
W1 = tf.Variable(tf.truncated_normal([784,500],stddev=0.1))
b1 = tf.Variable(tf.zeros([500])+0.1)
L1 = tf.nn.tanh(tf.matmul(x,W1)+b1)
L1_drop = tf.nn.dropout(L1, keep_prob)
W2 = tf.Variable(tf.truncated_normal([500,300],stddev=0.1))
b2 = tf.Variable(tf.zeros([300])+0.1)
L2 = tf.nn.tanh(tf.matmul(L1_drop,W2)+b2)
L2_drop = tf.nn.dropout(L2, keep_prob)
W3 = tf.Variable(tf.truncated_normal([300,10],stddev=0.1))
b3 = tf.Variable(tf.zeros([10])+0.1)
prediction = tf.nn.softmax(tf.matmul(L2_drop, W3) + b3)
#二次代价函数
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y, logits=prediction)) #logits预测值
train_step = tf.train.AdamOptimizer(lr).minimize(loss)
corrent_prediction =tf.equal(tf.argmax(y,1), tf.argmax(prediction, 1))
accuracy = tf.reduce_mean(tf.cast(corrent_prediction, tf.float32))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for epoch in range(51):
#learnrate 给学习率重新赋值。类似小球震荡,渐渐达到最低点
sess.run(tf.assign(lr,0.001 * (0.95 ** epoch))) #0.95 的epoch的次方,开始学习率大,后来学习率越来越小
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, keep_prob:1.0})
test_acc = sess.run(accuracy, feed_dict={x:mnist.test.images, y:mnist.test.labels, keep_prob:1.0})
print('iter'+ str(epoch)+ ',Testing Accuracy' + str(test_acc),',Training Accuracy'+ str(train_acc))
iter0,Testing Accuracy0.9508 ,Training Accuracy0.95614547
iter1,Testing Accuracy0.9646 ,Training Accuracy0.97212726
iter2,Testing Accuracy0.9671 ,Training Accuracy0.9786182
iter3,Testing Accuracy0.9712 ,Training Accuracy0.9832909
iter4,Testing Accuracy0.9723 ,Training Accuracy0.985
iter5,Testing Accuracy0.9737 ,Training Accuracy0.98785454
iter6,Testing Accuracy0.9733 ,Training Accuracy0.9894
iter7,Testing Accuracy0.9743 ,Training Accuracy0.9905818
iter8,Testing Accuracy0.9757 ,Training Accuracy0.9906727
iter9,Testing Accuracy0.9775 ,Training Accuracy0.9926909
iter10,Testing Accuracy0.979 ,Training Accuracy0.99356365
iter11,Testing Accuracy0.9799 ,Training Accuracy0.9941818 其实这里是有问题的, 过拟合了