2017年4月24日 星期一

繼續對TensorFlow的Gradient Descent做逆向工程

上一篇,TensorFlow & Gradient Descent,我用一個簡單的例子
y = w * x

解釋了TensorFlow的Gradient Descent的運作原理,並且連數學公式都推導出來了。

本篇,承自上一篇,討探Gradient Descent如何處理更通用的直線方程式:
y = w * x + b

本篇標題,本來想取名為「TensorFlow & Gradient Descent Part 2」,後來決定把標題改成「…逆向工程」,這是因為後來發現,我做的事情,其實就是在對TensorFlow做逆向工程(Reverse Engineering)。當然,TensorFlow是Open Source,直接看程式碼不就好了,有必要做逆向工程嗎?原因是:樂趣。看程式碼比較無趣,我比較喜歡用數學的角度去推敲程式背後的原理,也順便加強一下自己數學的功力。

我喜歡畫一些圖,所以先將問題表達成下面這張x-y平面圖:


圖畫好了之後,開始用數學式子描述我們的問題:


我們希望調整w和b,直到找到最小的E為止。

下面的Python程式,呼叫TensorFlow的Gradient Descent,解這個問題:

import tensorflow as tf

w = tf.Variable ([0.3], tf.float32)
b = tf.Variable ([-0.3], tf.float32)
x = tf.placeholder (tf.float32)
y = w * x + b

t = tf.placeholder (tf.float32)
squared_deltas = tf.square (y-t)
E = tf.reduce_sum (squared_deltas)

optimizer = tf.train.GradientDescentOptimizer (0.01)
train = optimizer.minimize (E)

sess = tf.Session ()
init = tf.global_variables_initializer()
sess.run (init)

[[w_value], [b_value]] = sess.run ([w, b])
print ("w = %s, b = %s" % (w_value, b_value))

x_train = [1, 4]
t_train = [0, -3]

for i in range (10):
    sess.run (train, {x: x_train, t: t_train})
    [[w_value], [b_value]] = sess.run ([w, b])
    print ("w = %s, b = %s" % (w_value, b_value))

結果如下:


然後,根據這個結果,開始做逆向工程。先將此問題,轉換成一個Neural Node:


和上一篇不同的是,多一個b要考慮。這次,我們要根據E的值,調整w和b。

程序員在處理複雜問題,常採用各個擊破法。於以我們將此問題「根據E的值,調整w和b」拆解成兩個問題:「根據E的值,調整w」和「根據E的值,調整b」

問題一:根據E的值,調整w

和上一篇類似。調整w,找到最小的E為止。所以對E做w的微分:

求調整後的w,下面不解釋:
△w = -2 * (-3-0.9) * 4 = 31.2
△w = -L * △w
△w = -0.01 * 31.2 = -0.312
w = w + △w = 0.3 - 0.312 = -0.012 

問題二:根據E的值,調整b

調整b,找到最小的E為止。所以對E做b的微分:

求調整後的b,下面不解釋:
△b = -2 * (-3-0.9) * 1 = 7.8
△b = -L * △b
△b = -0.01 * 7.8 = -0.078
b = b + △b = -0.3 - 0.078 = -0.378 

結論

我們對E分別做w和b的微分,分別求得△w和△b的變化量,然後根據變化量,調整w和b,使得E的值變小。這就是在跑這支 TensorFlow Python 程式時,所看到第二行 w = -0.012, b = -0.378 的由來。

-Count


沒有留言:

張貼留言