2017年5月21日 星期日

AI時代,人類該如何學習?格物致知

在看完,李開復寫的「人工智能」後,我認為,之前花一些時間,去了解Neural Network的背後的數學原理,是值得的。除了本人喜歡探究事物的本質之外,還有現實的考量。

對AI有興趣的人,強力推薦李開復的「人工智能」(非廣告)


據我所知,目前AI的發展,不管是Machine Learning也好,Deep Learning也好,其所表現出來的,都是「知其然,不知其所以然」。也就是經由大數據、平行運算、以及最佳算法,訓練出來的電腦,在很多領域,效果顯著,如語音識別。於是人類會擔心,將來許多工作是否會被AI取代?就像之前電腦取代許多人的工作一樣。

我認為,如果目前學校,還是以填鴨方式教導學生,而不去培養學生獨立思考、抽象思考、以及追根究底的精神,這樣下來,16年後,出了社會,會過得很辛苦。那還不如學生時代,整天玩樂的,出了社會,說不定過得還比較好。為何填鴨教學法,對將來用處有限呢?這是因為Deep Learning的學習方法,就是填鴨,而且電腦比人類,更擅長此法。

李開復的「人工智能」這本書裡,提到一個例子。讓電腦觀察,從相同高度落下的,不同重量的兩顆球,觀察100次之後,電腦的Deep Learning「學」會了一個結論,就是「高度一樣,不同重量的物體,到達地面的時間是一樣的」。可是電腦知道背後的力學原理嗎?當然不知道。我們會相信Deep Learning能推論背後的力學原理嗎?當然不相信。

學校教我們「高度一樣,不同重量的物體,到達地面的時間是一樣的」。這個結論,我們記了一輩子。但能想起背後的力學原理嗎?大部份的人不能,我也不行。這樣看起來,大部份的人,很容易被Deep Learning的AI取代。

所以,為了將來不被AI取代,人類的學習方式,光靠填鴨是不夠的。還得習慣獨立思考、抽象思考、以及追根究底的精神。簡單一句話,就是「格物致知」。

這也就是為何,我最近花了一些時間,了解Neural Network數學原理的原因之一。因為對我來說,用填鴨法學習Neural Network,是不夠的。這和Deep Learning沒兩樣。AI時代,學任何東西,不求快,因為Deep Learning比你快,要求質,要「格物致知」,因為Deep Learing做不到此點。

-Count


2017年5月7日 星期日

如何寫出3-Layer Neural Network程式?

這裡總結一下,我閱讀完「Making Your Neural Network」Part 1 後的心得。此書共有3個Part:Part 1講Neural Network的原理,Part 2講用Python實作Neural Network,Part 3講Neural Network的應用。

個人認為,只要有足夠的程式設計基礎,並且徹底了解Part 1,那就夠了。至於Part 2和Part 3,有空再看。換言之,若沒有了解Part 1基礎原理,寫再多的Neural Network程式,對知識的長進,沒有多大幫助。

如何確定是否真的搞懂Part 1?一個方法就是,用數學公式當作程式語言,將3-Layer Neural Network重新推導一遍。

下圖是我們建立的,3-Layer Neural Network:

注意,我用程序員最常用的迴圈符號i, j, k,來表達第1層、第2層、第3層的Node、Input、Output、Training Data和Weight。有i, j, k符號做為結尾的,大部份是Matrix,如xi, wij, yk。

First Layer Node: ni
  Input: xi
  Output: xi
  Function: f(x) = x

Second Layer Node: nj
  Input: xi
  Output: xj
  Weight: wij
  Function: f(x) = Sigmoid (x)

Third Layer Node: nk 
  Input: xj
  Output: yk 
  Weight: wjk
  Function: f(x) = Sigmoid (x)

Training Data: tk

將第3層Node的Error,套在Gradient Descent,算出第2層到第3層的weight的微調量:
此公式的推導過程,請參考:
為何Neural Network要用到線性代數?

將此微調量,套在Back-Propagating Errors,算出第2層的Error:

將第2層Node的Error,套在Gradient Descent,算出第1層到第2層的weight的微調量:

有了,這些weight的微調量,就可以更新2層到第3層和第1層到第2層的weight了:

反復執行,直到找到Error Function,E = Sum ((tk-yk)^2),輸出最小的值為止。

-Count


2017年5月6日 星期六

為何Neural Network要用到線性代數?

Neural Network用到許多基礎數學:線性代數和微積分。用微積分的原因,之前講過了:
為何Neural Network要用到微積分?

但為何會用到線性代數?是為了讓程式比較好寫。並且,只有一個Node不需要線性代數,多個Node才需要。

我們先考慮一個Node的情況:



為了要調整Weight,去找Error Function的最小值,我們用w對E做微分:

這個公式的由來,請參考此篇:
如何計算Neural Network的Error Function的斜率?

接下來,用Gradient Descent方法,調整weight,程式會這樣寫。

w = w + △w 

每次微調weight的量為:

為何weight的微調量會是負的?以及Learning Rate的作用為何?請參考:
Learning Rate在Neural Network的作用

前面說過,只有一個Node是不需要線性代數,所以先從簡單的2*2 Node開始,將線性代數拉進來:


上圖,我們觀察到,2*2 Node之間,穿插了4個△w ,套用上面的公式,這4個△w 用下面4條式子表示:

可以用Matrix表達這4條式子。對Matrix的基本運算不熟的人,可以上網去搜,去堆敲,可以發現,其實沒什麼大不了的。不過就是將4條式子,改用簡精的1條式子表達而己,其運算方式,和運算量,都沒變:


再整理一下:

這樣是否更精簡了?x頭上的那個T是Transposing的意思,這裡就不多解釋了。大家可以上網去搜,自己推敲一下。

再強調一次,這裡的e和E,雖然都叫Error,卻是完全不同的功能。前篇有提醒過大家:
Back-Propagating Errors

將來,我會把Back-Propagating Error加進來,去推導完整的3-Layer Neural Network公式。這樣,大家用這些公式,應該就知道如何Coding了。

當然,這些公式,不是我發明的。只是從程序員的角度,改一下書中的符號,除了能幫助理解,也為了將來Coding方便。因為有時候,書中的符號會讓人混淆,如將e和E混合使用,造成理解錯誤。所以自己定義符號,然後再重新推導公式一遍,就像Coding要遵循Coding Standard一樣,這樣一來,有了推導的過程,就能清楚了解事物的原理。這一段是題外話。

-Count

2017年5月3日 星期三

Back-Propagating Errors

什麼情況下Neural Network需要做Back-Propagating Errors?答案是3層以上的Neural Network才需要做。為何?

先看2 Layer Neural Network。

我們將training data餵給第2層的目的是調整第1層和第2層的weight。而對於第1層來說,前面沒有weight,就不用做調整weight的事情,就不用BPE (Back-Propagating Errors)。

再來看3 Layer Neural Network。

第1層前面沒有weight,可是在第1層和第2層之前有weight。有weight,就需要調整。問題是,我們的training data是餵給第3層,產生的error,是用來調整第2層和第3層之間的weight。如果我們要調整第1層和第2層的weight,就需要error。

問題是error從那裡來?error可以從第3層傳給第2層。

如何將error合理地分配給第2層的每個節點?依weight比例分配。

下面考慮這種情況。

我習慣先將複雜問題簡化,畫成下圖為3層Neural Network,這是因為探討BPE,至少要3層才有意思。



第1層node及其weight用灰色來表示,因為前面談過,第1層不需要BE,因為前面沒有weight。此圖還標明了e != E,都叫error,意思不同:

E是Error Function,E = Sum ((t - y) ^ 2),這是將來用Gradient Descent,取最小Error用的。

e是針對單一個Node而言的error,是用來做Back-Propagating Error用的。

為了區分它們的不同,這裡用小寫的e做為Back-Propagating Error,以區別大寫E。區分這兩種Error,非常重要,相信很多人以為e = E,而卡在這一關,

我可以把這張圖畫得更細緻一些。



希望能表達出,第3層node的error,如何按比例分配給第2層的每個node,公式如下。



我們可以把1/(w1+w2)去掉,這樣公式看起來會比較清爽。為何可以這麼做?還記得我們有learning rate嗎?

接下來,在第3層,再多加1個node,看看要如何算出第2層每個node的error。



用Matrix表達這個式子。



還記得以前,第2層 node的input是如何算出來的嗎?


請觀察這兩個式子,發現公式1的weight matrix是公式2的weight matrix的transposing。

讓我們把它改成下面這個樣子,看起來會比較漂亮一些。


這樣寫的好處,除了漂亮之外,程式也會比較好寫。這是因為,程式一開始,為了算出input的值,所建立的weight matrix,可以拿來用在計算第2層的error上,只要將它transposing即可。

現在,我們有了第2層每個node的error值,然後呢?Error的目的是要調整第1層和第2層之間的weight。調整的方法是用Gradient Descent,之前有簡單介紹過:

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

是對一個Node做Gradient Descent。現在我們面對的是多個Node,如何做Gradient Descent?待續。

-Count