2017年4月23日 星期日

TensorFlow & Linear Regression

TensorFlow最近很紅。是Google力推的人工智慧架構。缺點是無法在Windows下安裝,但這不成為拋棄它的理由。據我所知,類似框架很多種,選擇TensorFlow的好處是:

  1. Google的產品,業界普及率高
  2. 支持Python
  3. 支持CUDA 3.0

我最近將它安裝TensorFlow在HP Gen8。不過這台沒有NVIDIA顯卡,無法發揮CUDA的效能,但還是可以用。

TensorFlow安裝完成後,官網會教你寫一個Hello TensorFlow的Python程式,用來驗證是否安裝成功。個人覺得,應該要進一步學會寫一支TensorFlow Python程式,了解Machine Learning的最簡單的原理,這樣我們就很容易地跨過這一道心理門檻。

這支簡單的程式,就是Linear Regression。

這支程式官網有說明。
https://www.tensorflow.org/get_started/get_started

其實大家去看官網就能了解TensorFlow的使用了。個人習慣是自己動手作,而且喜歡將範例程式的變數名稱改一下,讓它們和之前寫的文章裡的符號一致,如此一來,前後對照容易,會有一種觸類旁通的感覺。

現在開始介紹這個範例程式:將TensorFlow用在Linear Regression上。這裡,我們採用的是暴力破解的方式。

問題描述如下圖,座標上有4個紅點,分別是
(1, 0), (2, -1), (3, -2), (4, -3)


要找一條線,可以代表這4個點。這就是Linear Regression問題。當然,大家很容易找到這條線,這是因為剛好這4個點是在同一條線上。實務上,我們面對的是,4個點不見得會在同一條線上,要如何畫出適當的線出來呢?

這條線是
y = w * x + b

一開始,我們指定
w = 0.3
b = -0.3

於是
y = 0.3 * x - 0.3

輸入
x = [1, 2, 3, 4]

輸出
y = [0, 0.3, 0.6, 0.9]

我們的目標(Target)是輸出
t = [0, -1, -2, -3]

如何得知y和t的差距(Error)?定義Error Function:
E = Sum ((t-y)^2)
E = 0^2 + 1.3^2 + 2.6^2 + 3.9^2 = 23.66

目標是,調整w和b的值,使得E為最小,這就是Linear Regression。

最直覺的方法,是暴力破解,就是去試每個可能的值。這有點像是破解密碼。講到這裡,我感覺Machine Learning和Cryptography有類似之處,將來深入了解後,再為各位道來。

暴力破解,就是嘗式w和b的各種組合。理論上,組合是無線多個。實務上,我們要去找或去猜,可以在我們計算能力範圍之內的,w-b組合。
w = [-0.4, -0.3, -0.2, -0.1, 0, 0.1, 0.2, 0.3, 0.4]
b = [-0.4, -0.3, -0.2, -0.1, 0, 0.1, 0.2, 0.3, 0.4]

這樣看來,w-b組合就有9 * 9 = 81,我們可以一個一個去試。

若運氣不好,無法在81種組合裡找到答案,這時候,就要根據之前的結果,去推論下一個w-b組合該是什麼樣子。這種推論的過程,我認為就是Machine Learning的演算法。

數學稍為好一點的人,會把這個問題,再做一個簡化。就是看看能否把w和b,削去其中一個,如此一來,就只要試9個就好了,如下圖。


國中數學教過的y = w * x + b,如果線是通過圓點,則b = 0,於是y = w * x。這樣一來,我們只要考慮w就好了。從y = w * x + b轉換成y = wx,就是座標轉換,亦即線性代數的Linear Transformation。

這就是所謂的降低問題的維度,我相信此類方法常用在Machine Learning上。不然面對10幾個以上的變數,就算有再好的公式,再快的電腦,答案可能在有生之年也求不到。

不過,本篇的重點是,暴力破解,而且用TensorFlow。我們開始Coding吧。

我們把上面的數學式子,集中起來,寫在一起。最後一行算出E的值,然後不斷調整w和b,直到找到最小的E。我們誇稱為Machine Learning的暴力演算法,用數學式子表示。


先猜出一條線

y = w * x + b
w = 0.3
b = -0.3

Python:

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


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

輸入
x = [1, 2, 3, 4]
得到
y = [0, 0.3, 0.6, 0.9]

Python:

res = sess.run (y, {x:[1, 2, 3, 4]})
print (res)

[ 0.          0.30000001  0.60000002  0.90000004]

輸入
t = [0, -1 -2, -3]
計算 
Error = Sum ((t-y)^2) = 23.66

Python:


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

res = sess.run (E, {x:[1, 2, 3, 4], t:[0, -1, -2, -3]})
print (res)
23.66

我們運氣很好,挑選
w = -1
b = 1
剛好
Error = 0

Python:


w1 = tf.assign (w, [-1])
b1 = tf.assign (b, [1])
sess.run ([w1, b1])
res = sess.run (E, {x:[1, 2, 3, 4], t:[0, -1, -2, -3]})
print (res)
0.0 

我想,這是一個,除了Hello TensorFlow之外,最簡單的一個TensorFlow的例子吧!

-Count

沒有留言:

張貼留言