作者 | Javier Ideami
譯文來源 | 雲棲社群(譯者: Mags,審校:袁虎)
在構建乳腺癌預測神經網路過程中,我們主要分為3大部分:
1.用Python從零開始建立一個神經網路,並使用梯度下降演演算法訓練模型。
2.在該神經網路中使用威斯康星乳腺癌資料集,根據9種不同的特徵,預測腫瘤是良性還是惡性的。
3.探索反向傳播和梯度下降演演算法的工作原理。
在這個領域中,有很多大牛都透過影片和博文分享了自己掌握的專業知識,如fast.ai的Jeremy Howard、吳恩達、Andrej Karpathy、Yann Lecun等等。
他們一致認為,深度學習的關鍵之一就是,儘快親自動手編寫一個深度學習的模型。當前,深度學習領域中有很多強大的庫可供我們使用,如Tensorflow、 PyTorch、 Fast.ai、 Keras、 Mxnett、Nctk、DL4J 等。如果僅僅直接使用這些強大的庫,我們可能會錯過很多關鍵的東西,因此,我們需要進一步思考這些行程中最重要的那部分。
如果能自己親自動手編碼建立一個神經網路,我們就不得不面對建立過程中出現的一些問題和障礙,挖掘深度學習背後隱藏的那些令人驚嘆的知識。
當前,深度學習領域中有各種各樣的架構和開發:摺積神經網路、迴圈神經網路和生成對抗網路等等。在這些不同種類的網路背後,都包含了兩個相同的演演算法:反向傳播演演算法和梯度下降演演算法。
探索神秘的函式
宇宙中的很多事物都可以用函式表示。本質上來說,函式是一種數學結構,接受一個輸入並產生一個輸出,表示因果關係、輸入輸出關係。
當我們審視周圍的世界時,會接收到很多資訊,我們將這些資訊轉化為資料,就可以從這些資料中學到很多知識。在利用這些資料進行學習的時候,會有很多不同的種類。通常來說,深度學習中有三種最常見的型別:
1.監督學習:從一組有標簽(已分類)的訓練資料中學習函式,輸入和輸出是成對的資料集。
2.非監督學習:從沒有任何標簽或分類的資料中學習到函式。
3.強化學習:代理人會在特定環境中做出相應的動作,透過最大化代理人得到的獎勵得到函式。
監督學習
本文中,我們主要關註監督學習。現在,我們有一個資料集,包含輸入及對應的輸出。下麵,我們想瞭解這些輸入和輸出是如何透過一個神秘的函式聯絡起來的。
當資料集達到一定的複雜度時,尋找這個函式的難度就相當大。因此,我們就需要使用神經網路和深度學習,來探索這個神秘的函式。
本質上來說,神經網路透過一系列的中間“權重”連線我們的輸入和期望輸出資料。這些權重實際上就是一些數字。
當我們使用正確的架構和引數,透過神經網路的結構和最佳化演演算法,我們可將神經網路近似成一個通用函式近似器,將輸入和輸出資料聯絡起來。
建立一個神經網路
一般來說,簡單的神經網路包括兩層(輸入不計入層數):
1.輸入:神經網路的輸入包含了我們的源資料。並且,神經元的數量與源資料的特徵數量相匹配。下圖中有4個輸入,當我們使用威斯康星乳腺癌資料集建立神經網路的時候,就會使用9個輸入。
2.第一層:隱藏層,包含一些隱藏層神經元,這些神經元將會與周圍層中的所有單元相連線。
3.第二層:有一個單元,為神經網路的輸出。
在實際的神經網路構建過程中,我們可以使用更多的層,比如10個或20個層的網路。為了簡單起見,在這裡,我們使用2個層。千萬不要小看這2個層,它能夠實現很多功能。
神經網路如何進行學習
問題來了:在這個神經網路中,學習將在哪個部分進行?
我們來回顧一下,我們在神經網路的輸入層放置了一些資料,並向網路展示某個輸入應該對應什麼輸出,也就是說,神經網路的輸出(第2層)應該是什麼結果。
在神經網路中,每個神經元都有一個相關的權重以及一個偏差。這些權重只是神經網路在開始學習時候初始化的一些隨機數字。
神經網路根據輸入資料和這些權重值進行計算,透過神經網路傳播,直到輸出產生最終的結果。
這些計算的結果就是一個將輸入對映到輸出的函式。
我們需要的就是,這些神經網路能夠計算出一個最佳權重值。因為網路透過計算,不同的權重和不同的層結合起來,會近似出不同型別的函式。
現在,我們來進一步探索正在探尋的函式。為了方便閱讀,我們需要解釋下這些變數的名稱:
1.X表示輸入層,即提供給網路的資料集。
2.Y表示與輸入x對應的標的輸出,由輸入經過網路進行一系列的計算得到的輸出。
3.Yh(y hat)表示預測函式,即我們像網路提供輸入資料集x後,經過神經網路一系列的計算產生的輸出。因此,Y是理想的輸出,Yh是神經網路接收到輸入資料後產生的實際輸出。
4.W表示網路各層的權重。
我們首先看第一層——隱藏層,它執行了一個運算W*X(即W和X的乘積)。
然後進行一個加權和:
1.這一層中的每個單元都和前一層中的每個單元相連線。
2.權重值存在於每個連線中。
3.該層中每個單元的值都是由前一個層中每個單元的值*權重的總和,而該權重則是1中所得到的權重。
從某種程度上來說,權重表示連線的強度,即:不同層之間單元連線的強度。
現在,我們要在這個架構中新增一個額外的量——偏差:W*X+b。
這個偏差能夠給神經網路帶來更多的靈活性,偏差允許網路“移動”單位的線性計算,加強網路學習這些函式的能力。
b代表單位偏差項。
我們看到,W*X+b就是一個線性方程,透過乘積與和運算表示輸入和輸出的線性關係。
現在,我們的神經網路只有2層,但是請記住,一個神經網路可以有很多層,比如20個甚至200個。因此,我們用數字表述這些變數屬於哪一層。這樣一來,定義隱藏層(第1層)的線性方程則為:W1*X+b1,併為其輸出命名為Z,表示某一層計算的輸出。因此,我們得到如下方程:
Z1=W1*X+b1
註意,這個計算應該針對每個層的每個單元進行。當我們為神經網路編寫程式碼的時候,我們將使用向量化程式設計,也就是說,利用矩陣將某一層的所有計算放在一個單一的數學運算中。
上面所講述的是隻有一個層的神經網路。現在,我們考慮一個有很多層的神經網路,每個層執都執行一個類似上面的線性運算,當所有的線性運算連線在一起時,這個神經網路就能夠計算複雜的函式了。
啟用函式
然而,現在就有一個問題:線性函式——太簡單了吧。
這個世界是複雜的,因此,線性函式遠遠滿足不了實際需求。一般來說,複雜的函式往往都是非線性的。而且,如果神經網路的架構僅僅由線性函式計算,那麼就很難計算非線性行為。這就是為什麼我們要在神經網路的每一層末尾加上一個額外的量:啟用函式。現在,我們介紹4個最典型的例子。
為了方便我們後續對啟用函式進行深入探索,首先需要介紹梯度這一概念。一個函式在某一點上的梯度也稱為函式的導數,表示該函式在該點輸出值的變化率。
我們來思考這樣一個問題:當特定輸入發生變化時,函式的輸出會發生怎樣的變化?
當梯度(導數)非常小,即函式的輸出變化非常平坦時,我們稱之為梯度消失。在後邊的反向傳播演演算法中,我們可以透過梯度瞭解網路中每個引數將會如何影響網路的輸出,從而就能夠決定如何調整網路的權值,也就是說瞭解這個引數的變化將會使網路的輸出增加還是減少?
梯度消失是我們所面臨的一個問題,因為如果某一點的梯度變化很小或趨於0,我們就很難確定該神經網路在該點的輸出方向。
當然,我們也會遇到相反的情況——梯度爆炸。當梯度值非常大時,神經網路可能就會變得非常不穩定。
不同的啟用函式有各自的優點,但是都會面臨梯度消失和梯度爆炸這兩大問題。
左上:Sigmoid啟用函式;右上:Tanh啟用函式;
左下:Relu啟用函式;右下:Leaky Relu啟用函式
(1)Sigmoid啟用函式——1/(1+e**-x)
1.輸出範圍:[0,1]。
2.非線性,輸出為兩個極端變數0和1。適用於二分類問題。
3.曲線變化溫和,因此,梯度(導數)比較容易控制。
4.該啟用函式的主要缺點為:在極端情況下,函式的輸出曲線變得非常平坦,也就是說,函式的導數(變化率)將變得非常小,在這種情況下,Sigmoid啟用函式的計算效率和速度將會非常低,甚至會完全沒效率。
5.當Sigmoid啟用函式出現在神經網路的最後一層時,將會特別有用,因為Sigmoid啟用函式有助於將輸出變為0或1(即二分類問題)。如果將Sigmoid啟用函式放在神經網路的其他層,就會出現梯度消失問題。
(2)Tanh啟用函式——(2/(1+e**-2x))-1
1.輸出範圍:[-1,1]。
2.曲線和Sigmoid啟用函式的曲線類似,是Sigmoid啟用函式曲線的縮小版。
3.Tanh啟用函式曲線較為陡峭,因此,該啟用函式的導數(變化率)比較大。
4.Tanh啟用函式的缺點與Sigmoid啟用函式類似。
(3)Relu啟用函式——max (0,x)
1.如果輸入大於0,那麼,輸出值等於輸入值;否則,輸出為0。
2.Relu啟用函式的範圍是[0,+∞),這就意味著輸出可能是+∞,可能會存在梯度爆炸問題。
3.優點:使神經網路輕量化,因為一些神經元可能輸出為0,防止所有的神經元被同時啟用。
4.Relu啟用函式存在一個問題,即輸入為0的時候,輸出全部為0,這將會導致梯度為0,會讓我們忽視某些神經元的一些有用的計算。
5.Relu啟用函式計算簡單,成本低廉。
6.當前,Relu啟用函式是神經網路內層最經常使用的啟用函式。
(4)   Leaky Relu啟用函式——e**x / Sum(e**x)
1.輸出範圍:[0,1]
2.Leaky Relu啟用函式將輸入進行標準化處理為一個機率分佈。
3.通常用於多分類場景中的輸出層。
在這裡,我們在輸出層使用Sigmoid啟用函式,在隱藏層使用Relu啟用函式。
好了,現在我們已經理解了啟用函式,那麼,就需要對其進行命名!
A:表示啟用函式的輸出。
因此,在神經網路的隱藏層中,將會進行如下計算:
A1=Relu(Z1)
Z1=W1*X+b1
在第二層的輸出層中,將會進行如下計算:
A2=Sigmoid(Z2)
Z2=W2*A1+b2
請註意,第二層(輸出層)的輸入為第一層的輸出,即A1。
第二層的輸出就是網路的最終輸出。將上面的計算歸納一下,就得到2層神經網路所執行的全部計算:
Yh = A2 = Sigmoid(W2*ReLU (W1*X+ b1) + b2 )
因此,本質上來說,神經網路是一連串的函式,有些是線性函式,有些是非線性函式,它們共同組成了一個複雜的函式,將我們的輸入資料和想要的輸出資料連線了起來。
現在,我們註意到,在這個方程的所有變數中,W和b是兩個未知數,這就是神經網路需要學習的地方。也就是說,神經網路必須進行不斷的學習,找到W和b的正確值,才能計算出正確的函式。
因此,我們訓練神經網路的目的也變得明瞭了,即尋找W1,b1,W2,b2的正確值。但是,在開始訓練神經網路之前,我們必須首先對這些值進行初始化,即用隨機函式對其進行初始化處理。
初始化以後,我們就可以對神經網路進行編碼,我們使用Python構建一個類,對這些主要的引數進行初始化處理。
我們將如何進行實戰編碼呢?請繼續閱讀我們的第二部分:用Python構建一個神經網路。
原文地址:
https://towardsdatascience.com/the-keys-of-deep-learning-in-100-lines-of-code-907398c76504
譯文地址:
https://yq.aliyun.com/articles/694113?utm_content=g_1000047152
朋友會在“發現-看一看”看到你“在看”的內容