神經網路(Neural Network)與深度學習(Deep Learning) - YC Note

文章推薦指數: 80 %
投票人數:10人

本篇內容涵蓋神經網路(Neural Network, NN)、深度學習(Deep Learning, DL)、反向傳播算法(Backpropagation, BP)、Weight-elimination ... 機器學習技法學習筆記(6):神經網路(NeuralNetwork)與深度學習(DeepLearning) YCChen 2017-04-17 AI.ML 機器學習技法 本篇內容涵蓋神經網路(NeuralNetwork,NN)、深度學習(DeepLearning,DL)、反向傳播算法(Backpropagation,BP)、Weight-eliminationRegularizer、EarlyStop、Autoencoder、PrincipalComponentAnalysis(PCA) 神經網路(NeuralNetwork) 最後一個主題,我們要來講第三種「特徵轉換」—ExtractionModels,其實就是現今很流行的「類神經網路」(NeuralNetwork)和「深度學習」(DeepLearning),包括下圍棋的AlphaGo、Tesla的自動駕駛都是採用這一類的MachineLearning。

ExtractionModels的基本款就是廣為人知的「神經網路」(NeuralNetwork),它的特色是使用神經元來做非線性的特徵轉換,那如果具有多層神經元,就是做了多次的非線性特徵轉換,這就是所謂的「深度學習」(DeepLearning)。

上圖左側就是具有一層神經元的NeuralNetwork,首先我們有一組特徵\(X\),通常我們會加入一個維度\(X_{0}=1\),這是為了可以讓結構變得更好看,未來可以與\(W_{0}\)相乘產生常數項。

使用\(W\)來給予特徵\(X\)權重,最後總和的結果稱之為Score,\(s=W_{0}X_{0}+𝚺_{i=1}W_{i}X_{i}=𝚺_{i=0}W_{i}X_{i}\)。

這個Score會被輸入到一個ActivationFunction裡頭,ActivationFunction的用意就是開關,當Score大於某個閥值,就打通線路讓這條路的貢獻可以繼續向後傳遞;當Score小於某個閥值,就關閉線路,所以ActivationFunction可以是BinaryFunction,但在實際操作之下不會使用像BinaryFunction這類不可以微分的ActivationFunction,所以我們會找具有相似特性但又可以微分的函數,例如\(tanh\)或者是\(ReLU\)這類比較接近開關效果的函數,經過ActivationFunction轉換後的輸出表示成\(g_{t}=σ(𝚺_{i}W_{i}X_{i})\),這個\(g_{t}\)就稱為神經元、\(σ\)為ActivationFunction、\(𝚺_{i}W_{i}X_{i}\)是Score。

如果我們有多組權重\(W\)就能產生多組神經元\(g_{t}\),然後最後把\(g_{t}\)做線性組合並使用OutputFunction\(h(x)\)來衡量出最後的答案,OutputFunction可以是LinearClassification的BinaryFunction\(h(x)=sign(x)\),不過一樣的問題,它不可以微分,通常不會被使用,常見的是使用LinearRegression\(h(x)=x\),或者LogisticRegression\(h(x)=Θ(x)\)來當作OutputFunction,最後的結果可以表示成\(y=h(𝚺_{t}α_{t}g_{t})\),看到這個式子有沒有覺得很熟悉,它就像我們上一回講的Aggregation,將特徵X使用特徵轉換轉成使用\(g_{t}\)表示,再來組合這些\(g_{t}\)成為最後的Model,所以單層的NeuralNetwork就使用到了Aggregation,它繼承了Aggregation的優點。

有了這個Model的形式了,我們可以使用GradientDescent的手法來做最佳化,這也就是為什麼要讓操作過程當中所使用的函數都可以微分的原因。

GradientDescent在NeuralNetwork的領域裡面發展出一套方法稱為Backpropagation,我們待會會介紹。

因此實現Backpropagation,我只要餵Data進去,Model就會去尋找可以描述這組Data的特徵轉換\(g_{t}\),這就好像是可以從Data中萃取出隱含的Feature一樣,所以這類的Models才會被統稱為ExtractionModels。

深度學習(DeepLearning) 剛剛我們介紹了最基本款的NeuralNetwork,那如果這個NeuralNetwork有好幾層,我還會稱它為DeepLearning,所以基本上DeepNeuralNetwork和DeepLearning是指同一件事,那為什麼會有兩個名字呢?其實是有歷史典故的。

NeuralNetwork的歷史相當悠久,早在1958年就有人提出以Perceptron當作ActivationFunction的單層NeuralNetwork,大家也知道一層的NeuralNetwork是不Powerful的,所以在1969年,就有人寫了論文叫做「perceptronhaslimitation」,從那時起NeuralNetwork的方法就很少人研究了。

直到1980年代,有人開始使用多層的NeuralNetwork,並在1989年,YannLeCun博士等人就已經將反向傳播演算法(Backpropagation,BP)應用於NeuralNetwork,當時NeuralNetwork的架構已經和現在的DeepLearning很接近了,不過礙於當時的硬體設備計算力不足,NeuralNetwork無法發揮功效,並且緊接的有人在1989年證明了只要使用一層NeuralNetwork就可以代表任意函數,那為何還要Deep呢?所以DeepNeuralNetwork這方法就徹底黑掉了。

一直到了最近,G.E.Hinton博士為了讓DeepNeuralNetwork起死回生,重新給了它一個新名字「DeepLearning」,再加上他在2006年提出的RBM初始化方法,這是一個非常複雜的方法,所以在學術界就造成了一股流行,雖然後來被證明RBM是沒有用的,不過卻因為很多人參與研究DeepLearning的關係,也找出了解決DeepLearning痛處的方法,2009年開始有人發現使用GPU可以大大的加速DeepLearning,從這一刻起,DeepLearning就開始流行起來,直到去年的2016年3月,圍棋程式AlphaGO運用DeepLearning技術以4:1擊敗世界頂尖棋手李世乭,DeepLearning正式掀起了AI的狂潮。

聽完這個故事我們知道改名字的重要性XDD,不過大家是否還有看到什麼關鍵,「使用一層NeuralNetwork就可以代表任意函數,那為何還要Deep呢?」這句話,這不就否定了我們今天做的事情了嗎?的確,使用一層的NeuralNetwork就可以形成任意函數,而且完全可以用一層的神經元來表示任何多層的神經元,數學上是行得通的,但重點是參數量。

DeepLearning的學習方法和人有點類似,我們在學習一個艱深的理論時,會先單元式的針對幾個簡單的概念學習,然後在整合這些概念去理解更高層次的問題,DeepLearning透過多層結構學習,雖然第一層的神經元沒有很多,能學到的也只是簡單的概念而已,不過第二層再重組這些簡單概念,第三層再用更高層次的方法看問題,所以同樣的問題使用一層NeuralNetwork可能需要很多神經元才有辦法描述,但是DeepLearning卻可以使用更少的神經元做到一樣的效果, 同樣表示的數學轉換過程,雖然單層和多層都是做得到相同轉換的,但是多層所用的參數量是比單層來得少的,依照VCGeneralizationBound理論(請參考:機器學習基石學習筆記(2):為什麼機器可以學習?)告訴我們可調控的參數量代表模型的複雜度,所以多層的NN比單層的有個優勢是在做到同樣的數學轉換的情況下更不容易Overfitting。

因此,DeepLearning中每一層當中做了Aggregation,在增加模型複雜度的同時,也因為平均的效果而做到截長補短,這具有Regularization的效果,並且在採用多層且瘦的結構也同時因為「模組化」而做到降低參數使用量,來減少模型複雜度,這就不難想像DeepLearning為何如此強大。

反向傳播算法(Backpropagation,BP) 我們接下來就來看一下DeepLearning的演算法—反向傳播法,我們來看要怎麼從GradientDescent來推出這個算法。

看一下上面的圖,我畫出了具有\(L\)層深的DeepLearning,每一層都有一個權重\(W_{ij}^{(ℓ)}\),因此我們可以估計出每一層的Score\(s_{j}^{(ℓ)}=𝚺_{i}W_{ij}^{(ℓ)}X_{i}^{(ℓ-1)}\),把Score\(s_{j}^{(ℓ)}\)通過ActivationFunction,就可以得到下一層的Input,如此不斷的疊上去,直到最後一層L為OutputLayer,Output最後的結果\(y\),這裡我使用LinearFunction來當作OutputFunction,這就是DeepLearning最簡單的架構。

而我們需要Training的就是這些權重\(W_{ij}^{(ℓ)}\),我們如何一步一步的更新\(W_{ij}^{(ℓ)}\),使得它可以Fit數據呢?回想一下GradientDescent的流程: 定義出Error函數 Error函數讓我們可以去評估\(E_{in}\) 算出它的梯度\(∇E_{in}\) 朝著\(∇E_{in}\)的反方向更新參數W,而每次只跨出\(η\)大小的一步 反覆的計算新參數\(W\)的梯度,並一再的更新參數\(W\) 假設使用平方誤差的話,Error函數在這邊就是 \(L=(1/2)(y-\overline{y})^{2}\), 因此我們的更新公式可以表示成 \(W_{ij}^{(ℓ)}←W_{ij}^{(ℓ)}-η×∂L/∂W_{ij}^{(ℓ)}\) 那我們要怎麼解這個式子呢?關鍵就在\(∂L/∂W_{ij}^{(ℓ)}\)這項要怎麼計算,這一項在OutputLayer(\(ℓ=L\))是很好計算的, \(∂L/∂W_{ij}^{(L)}\) \(=\frac{∂L}{∂s_{j}^{(L)}}\frac{∂s_{j}^{(L)}}{{∂W_{ij}^{(L)}}}\)(連鎖率) \(={δ_{j}^{(L)}}×{X_{i}^{(L-1)}}\) 上式當中我們使用了微分的連鎖率,並且令 \(δ_{j}^{(L)}=∂L/∂s_{j}^{(L)}\) \(δ_{j}^{(L)}\)這一項被稱為BackwardPassTerm,而\(X_{i}^{(L-1)}\)這項被稱為ForwardPassTerm,所以\(L\)層權重的更新取決於ForwardPassTerm和BackwardPassTerm相乘\(δ_{j}^{(L)}×X_{i}^{(L-1)}\)。

我們先來看一下\(L\)層的ForwardPassTerm要怎麼計算,\(X_{i}^{(L-1)}\)這項是很容易求的,我們只要讓數據一路從\(0\)層傳遞上來就可以自然而然的得到\(X_{i}^{(L-1)}\)的值,所以我們會稱\(X_{i}^{(L-1)}\)這一項為ForwardPassTerm,因為我們必須要往前傳遞才可以得到這個值。

再來看一下\(L\)層的BackwardPassTerm要怎麼計算,\(δ_{j}^{(L)}\)一樣是很容易求得的, \(δ_{j}^{(L)}=∂L/∂s_{j}^{(L)}=∂[(1/2)(y-\overline{y})^{2}]/∂y=(y-\overline{y})\) 你會發現這一項的計算需要得到誤差的資訊,而誤差資訊要等到Forward的動作做完才有辦法得到,所以資訊的傳遞方向是從尾巴一路回到頭,是一個Backword的動作。

因此,最後一層也是OutputLayer的更新公式如下: \(W_{ij}^{(L)}←W_{ij}^{(L)}-η×δ_{j}^{(L)}×X_{i}^{(L-1)}\) 權重的更新取決於Input和Error的影響,需要考慮ForwardPassTerm和BackwardPassTerm。

那除了Output這一層以外的權重應該怎麼更新?來看一下\((ℓ)\)層, \(∂L/∂W_{ij}^{(ℓ)}\) \(=\frac{∂L}{∂s_{j}^{(ℓ)}}\frac{∂s_{j}^{(ℓ)}}{∂W_{ij}^{(ℓ)}}\)(連鎖率) \(=δ_{j}^{(ℓ)}×X_{i}^{(ℓ-1)}\) 一樣是ForwardPassTerm和BackwordPassTerm相乘,不過\(δ_{j}^{(ℓ)}\)這一項的計算有點技巧性,來看一下, \(δ_{j}^{(ℓ)}\) \(=∂L/∂s_{j}^{(ℓ)}\) \(=𝚺_{k}\frac{∂L}{∂s_{k}^{(ℓ+1)}}\frac{∂s_{k}^{(ℓ+1)}}{∂X_{jk}^{(ℓ)}}\frac{∂X_{jk}^{(ℓ)}}{∂s_{j}^{(ℓ)}}\)(連鎖率) \(=𝚺_{k}{δ_{k}^{(ℓ+1)}}×{W_{jk}^{(ℓ)}}×{σ'(s_{j}^{(ℓ)})}\) \(W_{jk}^{(ℓ)}\)和\(σ'(s_{j}^{(ℓ)})\)都是Forward之後就會得到的資訊,而\(δ_{k}^{(ℓ+1)}\) 而是需要Backward才可以得到,我們已經知道\(δ_{j}^{(ℓ=L)}\)的值,就可以從\(δ_{j}^{(ℓ=L)}\)開始利用上面的公式,一路Backward把所有的\(δ_{j}\)都找齊。

好!那現在我們已經找到了更新所有Weights的方法了。

看一下上圖中的最下面的Flow,一開始我們Forward,把所有\(X\)和\(s\)都得到,到了OutputLayer,我們得到了\(δ_{j}^{(ℓ=L)}\),再Backward回去找出所有的\(δ\),接下來就可以用ForwardPassTerm和BackwordPassTerm來Update所有的\(W\)了。

總結一下,反向傳播算法(Backpropagation,BP)更新權重的方法為 \(W_{ij}^{(ℓ)}←W_{ij}^{(ℓ)}-η×δ_{j}^{(ℓ)}×X_{i}^{(ℓ-1)}\) Ifoutputlayer(\(ℓ=L\)),\(δ_{j}^{(ℓ=L)}=(y-ŷ)\) Ifotherlayer,\(δ_{j}^{(ℓ)}=σ'(s_{j}^{(ℓ)})×𝚺_{k}δ_{k}^{(ℓ+1)}×W_{jk}^{(ℓ)}\) \(δ_{j}^{(ℓ)}\)為BackwordPassTerm;\(X_{i}^{(ℓ-1)}\)為ForwardPassTerm。

RegularizationinDeepLearning 那麼使用DeepLearning的時候,我們要怎麼避免Overfitting呢?有五個方法。

第一個方法,就是我們剛剛提過的「設計DeepNeuralNetwork的結構」,藉由限縮一層當中的神經元來達到一種限制,做到Regularization。

第二個方法是「限制W的大小」,和標準Regularization作一樣的事情,我們將\(W\)的大小加進去Cost裡頭做Fitting,例如使用L2Regularizer\(Ω(W)=𝚺(W_{jk}^{(ℓ)})^{2}\),但這樣使用有一個問題就是\(W\)並不是Sparse的,L2Regularizer在抑制\(W\)的方法是,如果W的分量大的話就抑制多一點,如果分量小就抑制少一點(因為\(W^{2}\)微分為1次),所以最後會留下很多很小的分量,造成計算量大大增加,尤其像是DeepLearing這麼龐大的Model,這樣的Regularization顯然不夠好,L1Regularizer顯然可以解決這個問題(因為在大部分位置微分為常數),但不幸的是它無法微分,所以就有了L2Regularizer的衍生版本, Weight-eliminationL2regularizer:\(𝚺\frac{(W_{jk}^{(ℓ)})^{2}}{1+(W_{jk}^{(ℓ)})^{2}}\) 這麼一來不管\(W\)大或小,它受到抑制的值大小是接近的(因為Weight-eliminationL2regularizer微分為\(-1\)次方),因此就可以使得部分\(W\)可以為\(0\),大大便利於我們做計算。

第三種方法是最常使用的「EarlyStopping」,所謂的EarlyStopping就是,在做Backpropagation的過程去觀察ValidationData的Error有沒有脫離TrainingData的Error太多,如果開始出現差異,我們就立刻停止計算,這樣就可以確保Model裡的參數沒有使得Model產生Overfitting,是一個很直接的作法。

第四種方法是「Drop-out」,在DeepLearingFitting的過程中,隨機的關閉部分神經元,藉由這樣的作法使得Fitting的過程使用較少的神經元,並且使得結構是瘦長狀的,來達到Regularization。

第五種方法是接下來會用更大篇幅介紹的「DenoisingAutoencoder」,在DeepNeuralNetwork前面加入這樣的結構有助於抑制雜訊。

Autoencoder NeuralNetwork針對不同需要發展出很多不同的型態,包括CNN,RNN,還有接下來要介紹的Autoencoder,Autoencoder是一種可以將資料重要資訊保留下來的NeuralNetwork,效果有點像是資料壓縮,在做資料壓縮時,會有一個稱為Encoder的方法可以將資料壓縮,那當然還要有另外一個方法將它還原回去,這方法稱為Decoder,壓縮的過程就是用更精簡的方式保存了資料。

Autoencoder同樣的有Encoder和Decoder,不過它不像資料壓縮一樣可以百分之一百還原,不過特別之處是Autoencoder會試著從Data中自己學習出Encoder和Decoder,並盡量讓資料在壓縮完了可以還原回去原始數據。

見上圖中BasicAutoencoder的部分,透過兩層的轉換,我們試著讓Input\(X\)可以完整還原回去,通常中間這一層會使用比較少的神經元,因為我們想要將資訊做壓縮,所以第一層的部分就是一個Encoder,而第二層則是Decoder,他們由權重\(W_{jk}^{(ℓ)}\)決定,而在Training的過程,Autoencoder會試著找出最好的\(W_{jk}^{(ℓ)}\)來使得資訊可以盡量完整還原回去,這也代表Autoencoder可以自行找出了Encoder和Decoder。

Encoder這一段就是在做一個DemensionReduction,Encoder轉換原本數據到一個新的空間,這個空間可以比原本Features描述的空間更能精準的描述這群數據,而中間這層Layer的數值就是新空間裡頭的座標,有些時候我們會用這個新空間來判斷每筆Data之間彼此的接近程度。

我們也可以讓Encoder和Decoder可以設計的更複雜一點,所以你同樣的可以使用多層結構,稱之為DeepAutoencoder。

另外,也有人使用Autoencoder的方法來Pre-trainDeepNeuralNetwork的各個權重。

緊接著介紹兩種特殊的例子,第一個是LinearAutoencoder,我們把所有的ActivationFunction改成線性的,這個方法可以等效於待會要講的PrincipalComponentAnalysis(PCA)的方法,PCA是一個全然線性的方法,所以它的效力會比Autoencoder差一點。

第二個是剛剛提到的DenoisingAutoencoder,我們在原本Autoencoder的前面加了一道增加人工雜訊的流程,但是又要讓Autoencoder試著去還原出原來沒有加入雜訊的資訊,這麼一來我們將可以找到一個Autoencoder是可以消除雜訊的,把這個DenoisingAutoencoder加到正常NeuralNetwork的前面,那這個NeuralNetwork就擁有了抑制雜訊的功用,所以可以當作一種Regularization的方法。

PrincipalComponentAnalysis(PCA) 最後來講一下PrincipalComponentAnalysis(PCA),它不太算是DeepLearning的範疇,不過它是一個傳統且重要的DimensionReduction的方法,我們就來看一下。

PCA的演算法是這樣的,第一步先求出資料Features的平均值,並且將各個Features減掉平均值,令為\(ζ\),第二步求出由\(ζ^{T}ζ\)產生的矩陣的Eigenvalue和Eigenvector,第三步,從這些Eigenvalue和Eigenvector中挑選前面\(k\)個,並組成轉換矩陣\(W\),而最終PCA的轉換就是\(Φ(x)=W^{T}(X-mean(X))\),這個轉換做的就是DimensionReduction,將數據降維到\(k\)維。

PCA做的事是這樣的,每一個Eigenvector代表新空間裡頭的一個軸,而Eigenvalue代表站在這個軸上看資料的離散程度,當然我們如果可以描述每筆資料越分離,就代表這樣的描述方法越好,所以Eigenvalue越大的Eigenvector越是重要,所以取前面\(k\)個Eigenvector的用意是在降低維度的過程,還可以盡量的保持對數據的描述力,而且Eigenvector彼此是正交的,也就是說在新空間裡頭的每個軸是彼此垂直,彼此沒有Dependent的軸是最精簡的,所以PCA所做的DimensionReduction一定是線性模型中最好、最有效率的。

另外,剛剛有提到的LinearAutoencode幾乎是等效於PCA,大家可以看上圖中的描述,這裡不多贅述,不過不同的是,LinearAutoencoder並沒有限制新空間軸必須是正交的特性,所以它的效率一定會比PCA來的差。

結語 這一篇當中,我們介紹了NeuralNetwork,並且探討多層NeuralNetwork—DeepNeuralNetwork,也等同於DeepLearning,並且說明為什麼需要「Deep」,然後介紹DeepLearning最重要的演算法—反向傳播算法,接著介紹五種常用的Regularization的方法:設計DeepNeuralNetwork的結構、限制W的大小、EarlyStopping、Drop-out和DenoisingAutoencoder。

介紹完以上內容,我們就已經對於DeepLearning的全貌有了一些認識了,緊接著來看DeepLearning的特殊例子—Autoencoder,Autoencoder可以用來做DimensionReduction,那既然提到了DimensionReduction,那就不得不在講一下重要的線性方法PCA。

那在下一回,我們會繼續探討NeuralNetwork還有哪些特殊的分支。

PreviousPost 大數據BigData:ARevolutionThatWillTransformHowWeLive,Work,andThink NextPost Python玩數據(2):Numpy[1/2] RelatedArticles 機器學習技法學習筆記(4):BasicAggregationModels 機器學習技法學習筆記(5):BoostAggregationModels 機器學習技法學習筆記(7):RadialBasisFunctionNetwork與MatrixFactorization 實作Tensorflow(1):SimpleLogisticClassificationonMNIST 實作Tensorflow(2):BuildFirstDeepNeurelNetwork(DNN) 實作Tensorflow(3):BuildFirstConvolutionalNeurelNetwork(CNN)



請為這篇文章評分?