
上一篇 6 解鎖梯度下降算法解釋清楚了學習率(learning rate)。本篇基于對梯度下降算法和學習率的理解,去填下之前在線性回歸中發(fā)現(xiàn)的一個坑。
在5 TF輕松搞定線性回歸中提到,只要把TF官方Get Started中線性回歸例子中的訓練數(shù)據(jù)換一下,就會出現(xiàn)越訓練“損失”越大,直到模型參數(shù)都stackoverflow的情況。然而更換訓練數(shù)據(jù)是我們學習代碼的過程中再普通不過的行為,從stackoverflow.com上也能搜到很多人做了類似的嘗試而遇到了這個問題。到底為什么這么經(jīng)不住折騰?馬上攤開看。
更換訓練數(shù)據(jù)如下:
- 參數(shù)初始值a=-1,b=50;
- 訓練數(shù)據(jù)x_train = [22, 25];
- 訓練數(shù)據(jù)y_train = [18, 15]。
先亮個底:給出的訓練數(shù)據(jù)只有兩組但足夠了,兩點成一線,要擬合的直線心算下就能得出是y=-x+40,a是-1,b是40。
運行使用新數(shù)據(jù)的代碼:
import tensorflow as tf
# model parameters
a = tf.Variable([-1.], tf.float32)
b = tf.Variable([50.], tf.float32)
# model input and output
x = tf.placeholder(tf.float32)
linear_model = a * x + b
y = tf.placeholder(tf.float32)
# loss
loss = tf.reduce_sum(tf.square(linear_model - y)) / 4 # sum of the squares
# training data
x_train = [22, 25]
y_train = [18, 15]
# optimizer
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
for i in range(10):
sess.run(train, {x: x_train, y: y_train})
curr_a, curr_b, curr_loss = sess.run([a, b, loss], {x: x_train, y: y_train})
print("a: %s b: %s loss: %s" % (curr_a, curr_b, curr_loss))
# evaluate training accuracy
curr_a, curr_b, curr_loss = sess.run([a, b, loss], {x: x_train, y: y_train})
print("a: %s b: %s loss: %s" % (curr_a, curr_b, curr_loss))
為了方便觀察,讓程序訓練了10次,輸出是:
a: [-3.3499999] b: [ 49.90000153] loss: 1033.39
a: [ 7.35424948] b: [ 50.35325241] loss: 21436.4
a: [-41.40307999] b: [ 48.28647232] loss: 444752.0
a: [ 180.68467712] b: [ 57.69832993] loss: 9.22756e+06
a: [-830.91589355] b: [ 14.8254509] loss: 1.9145e+08
a: [ 3776.88330078] b: [ 210.10742188] loss: 3.97214e+09
a: [-17211.45703125] b: [-679.39624023] loss: 8.24126e+10
a: [ 78389.59375] b: [ 3372.25512695] loss: 1.70987e+12
a: [-357069.3125] b: [-15082.85644531] loss: 3.54758e+13
a: [ 1626428.5] b: [ 68979.421875] loss: 7.36039e+14
a: [ 1626428.5] b: [ 68979.421875] loss: 7.36039e+14
參數(shù)越練損失越大的趨勢果然重現(xiàn)了。
現(xiàn)在我們已經(jīng)掌握了梯度下降大法,就來看看每次訓練的結(jié)果到底是怎么產(chǎn)生的。
手工計算了兩次迭代,和程序輸出一致。
圖中顯示,訓練樣本(已紅色標出)的值對梯度值的貢獻很大,而此時沿用之前的學習率η=0.01就顯得不夠小了。訓練樣本既然不可調(diào),那么顯然只能調(diào)小學習率了。隨之而來的副作用就是會導致學習緩慢,所以還得增加訓練的次數(shù)。這就是之前的例子中最終調(diào)整為η=0.0028,epoch=70000的原因了。
如此看來,這的確不是TF的bug。再一次體會:訓練是一門藝術。
共享協(xié)議:署名-非商業(yè)性使用-禁止演繹(CC BY-NC-ND 3.0 CN)
轉(zhuǎn)載請注明:作者黑猿大叔(簡書)