Tensorflow1.0 第四集:优化器
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
各种优化器对比:
标准梯度下降法(BGD): 标准梯度下降先计算所有样本汇总误差,然后根据总误差来更新权值。时间可能会比较长。
随机梯度下降法(SGD): 随机梯度下降随机抽取一个样本来计算误差,然后更新权值。可能会引入很多噪声,某次权值更新的方向可能是错误的方向。
批量梯度下降法: 批量梯度下降算是一种折中的方案,从总样本中选取一个批次(比如一共有10000个样本,随 机选取100个样本作为一个batch),然后计算这个batch的总误差,根据总误差来更新权值。更新时间不算太长,准确度也还可以。一般用这个。
W
W
W:要训练的参数
J
(
W
)
J(W)
J(W):代价函数
∇
W
J
(
W
)
\nabla_{W} J(W)
∇WJ(W):代价函数的梯度
η
\eta
η:学习率
SGD:随机梯度下降
更新过程:
W
=
W
−
η
∇
W
J
(
W
;
x
(
i
)
,
y
(
i
)
)
W = W - \eta \nabla_{W} J(W; x^{(i)}, y^{(i)})
W=W−η∇WJ(W;x(i),y(i))
Momentum:
SGD每次都会在当前位置上沿着负梯度方向更新(下降,沿着正梯度则为上升),并不考虑之前的方向梯度大小等等。而动量(moment)通过引入一个新的变量 γ \gamma γ去积累之前的梯度,得到加速学习过程的目的。
更新过程:
γ
\gamma
γ:动力,通常设为0.9
v
t
=
γ
v
t
−
1
+
η
∇
W
J
(
W
)
v_{t} = \gamma v_{t-1} + \eta \nabla_{W} J(W)
vt=γvt−1+η∇WJ(W)
W
=
W
−
v
t
W = W- v_{t}
W=W−vt
当前权值的改变会受到上一次权值改变的影响,类似于小球向下滚动的时候带上了惯性。这样可以加快小球的向下的速度。
NAG: Nesterov accelerated gradient
在Momentun中小球会盲目地跟从下坡的梯度,容易发生错误,所以我们需要一个更聪明的 小球,这个小球提前知道它要去哪里,它还要知道走到坡底的时候速度慢下来而不是又冲上另 一个坡。
γ v t − 1 \gamma v_{t-1} γvt−1会用来修改W的值,计算 W − γ v t − 1 W - \gamma v_{t-1} W−γvt−1可以表示小球下一个位置大概在哪里。从 而我们可以提前计算下一个位置的梯度,然后使用到当前位置。
更新过程:
v
t
=
γ
v
t
−
1
+
η
∇
W
J
(
W
−
γ
v
t
−
1
)
v_{t} = \gamma v_{t-1} + \eta \nabla_{W}J(W-\gamma v_{t-1})
vt=γvt−1+η∇WJ(W−γvt−1)
W
=
W
−
v
t
W = W - v_{t}
W=W−vt
Adagrad:
它是基于SGD的一种算法,核心思想是对比较常见的数据给予它比较小的学习率去调整参数,对于比较罕见的数据给予它比较大的学习率去调整参数。
适合应用于数据稀疏的数据集(比如一个图片数据集,有10000张狗的照片,10000张猫的照片,只有100张大象的照 片)。 Adagrad主要的优势在于不需要人为的调节学习率,它可以自动调节。
缺点在于随着迭代次数的增多,学习率也会越来越低,最终会趋向于0。
i
i
i:代表第i个分类
t
t
t:代表出现次数
ϵ
\epsilon
ϵ:作用是避免分母为0,取值一般为1e-8
η
\eta
η:取值一般为0.01
g
t
,
i
=
∇
W
J
(
W
i
)
g_{t,i} = \nabla_{W} J(W_{i})
gt,i=∇WJ(Wi)
W
t
+
1
=
W
t
−
η
∑
t
′
=
1
t
g
(
t
′
,
i
)
2
+
ϵ
g
t
W_{t+1} = W_{t} - \frac{\eta}{\sqrt{\sum_{t'=1}^{t} g(t', i)^{2} + \epsilon}} g_{t}
Wt+1=Wt−∑t′=1tg(t′,i)2+ϵηgt
RMSprop:
RMS(Root Mean Square)是均方根的缩写。RMSprop借鉴了一些Adagrad的思想,不过这里RMSprop只用到了前t-1次梯度平方的平均值加上当前梯度的平方的和的开平方作为学习率的分母。这样RMSprop不会出现学习率越来 越低的问题,而且也能自己调节学习率,并且可以有一个比较好的效果。
γ
\gamma
γ:动力,通常设为0.9
η
\eta
η:取值一般为0.001
E
[
g
2
]
t
E[g^{2}]_{t}
E[g2]t:表示前t次的梯度平方的平均值
g
t
=
∇
W
J
(
W
)
g_{t} = \nabla_{W}J(W)
gt=∇WJ(W)
E
[
g
2
]
t
=
γ
E
[
g
2
]
t
−
1
+
(
1
−
γ
)
g
t
2
E[g^{2}]_{t} = \gamma E[g^{2}]_{t-1} + (1-\gamma)g^{2}_{t}
E[g2]t=γE[g2]t−1+(1−γ)gt2
W
t
+
1
=
W
t
−
η
E
[
g
2
]
t
+
ϵ
g
t
W_{t+1} = W_{t} - \frac{\eta}{\sqrt{E[g^{2}]_{t} + \epsilon}} g_{t}
Wt+1=Wt−E[g2]t+ϵηgt
AdaDelta:
使用AdaDelta我们甚至不需要设置一个默认学习率,在AdaDelta不需要使用学习率也可以达到一个非常好的效果。
g
t
=
∇
W
J
(
W
)
g_{t} = \nabla_{W}J(W)
gt=∇WJ(W)
Δ
W
t
=
−
η
E
[
g
2
]
t
+
ϵ
g
t
\Delta W_{t} = - \frac{\eta}{\sqrt{E[g^{2}]_{t} + \epsilon}} g_{t}
ΔWt=−E[g2]t+ϵηgt
Δ
W
t
=
−
η
R
M
S
[
g
]
t
g
t
\Delta W_{t} = - \frac{\eta}{RMS[g]_{t}} g_{t}
ΔWt=−RMS[g]tηgt
W
t
+
1
=
W
t
−
R
M
S
[
Δ
W
]
t
−
1
R
M
S
[
g
]
t
W_{t+1} = W_{t} - \frac{RMS[\Delta W]_{t-1}}{RMS[g]_{t}}
Wt+1=Wt−RMS[g]tRMS[ΔW]t−1
Adam:
就像AdaDelta和RMSprop一样,Adam会存储之前衰减的平方梯度,同时它也会保存之前衰减 的梯度。经过一些处理之后再使用类似Adadelta和RMSprop的方式更新参数。
β
1
\beta_{1}
β1:一般取0.9
β
2
\beta_{2}
β2:一般取0.999
ϵ
\epsilon
ϵ:作用是避免分母为0,取值一般为1e-8
m
t
=
β
1
m
t
−
1
+
(
1
−
β
1
)
g
t
m_{t} = \beta_{1} m_{t-1} + (1-\beta_{1})g_{t}
mt=β1mt−1+(1−β1)gt
v
t
=
β
2
v
t
−
1
+
(
1
−
β
2
)
g
t
2
v_{t} = \beta_{2}v_{t-1} + (1-\beta_{2})g^{2}_{t}
vt=β2vt−1+(1−β2)gt2
m
^
t
=
m
t
1
−
β
1
t
\hat{m}_{t} = \frac{m_{t}}{1-\beta_{1}^{t}}
m^t=1−β1tmt
v
^
t
=
v
t
1
−
β
2
t
\hat{v}_{t} = \frac{v_{t}}{1-\beta_{2}^{t}}
v^t=1−β2tvt
W
t
+
1
=
W
t
−
η
v
^
t
+
ϵ
m
^
t
W_{t+1} = W_{t} - \frac{\eta}{\sqrt{\hat{v}_{t} + \epsilon}} \hat{m}_{t}
Wt+1=Wt−v^t+ϵηm^t
对不起俺开始摸鱼了,这玩意回头用的时候再仔细推吧… 根本记不住…
实现的时候就是选想要的优化器然后替换代码
# 手写数字集
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 = 50
# 计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_size
x = tf.placeholder(tf.float32, [None, 784]) #每张图像有784个像素块 28*28的
y = tf.placeholder(tf.float32, [None, 10])
# 一个简单的神经网络
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([1, 10]))
# L = tf.nn.tanh(tf.matmul(x, W) + b)
# W1 = tf.Variable(tf.random_normal([100, 10]))
# b1 = tf.Variable(tf.zeros([1, 10]))
prediction = tf.nn.softmax(tf.nn.tanh(tf.matmul(x, W) + b))
# loss = tf.reduce_mean(tf.square(prediction - y))
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=prediction))
# 改不一样的优化器试试
# train_step = tf.train.GradientDescentOptimizer(learning_rate=0.2).minimize(loss) ## 梯度下降
# train_step = tf.train.AdamOptimizer(learning_rate=1e-2).minimize(loss) ## Adam
train_step = tf.train.AdadeltaOptimizer(learning_rate=1e-2).minimize(loss) ## Adadelta
# 等等等等优化器,用哪个就换哪个
init = tf.global_variables_initializer()
# 求准确率
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1)) #布尔型列表
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) #tf.cast 把布尔型转换为浮点型
with tf.Session() as sess:
sess.run(init)
for epoch in range(30):
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))