100行Python代碼理解深度學習關鍵概念 從頭構建惡性腫瘤檢測網絡

摘要: 100行Python代碼理解深度學習關鍵概念!

100行Python代碼理解深度學習關鍵概念 從頭構建惡性腫瘤檢測網絡

在構建乳腺癌預測神經網絡過程中,我們主要分為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.強化學習:代理人會在特定環境中做出相應的動作,通過最大化代理人得到的獎勵得到函數。

監督學習

本文中,我們主要關注監督學習。現在,我們有一個數據集,包含輸入及對應的輸出。下面,我們想了解這些輸入和輸出是如何通過一個神祕的函數聯繫起來的。

當數據集達到一定的複雜度時,尋找這個函數的難度就相當大。因此,我們就需要使用神經網絡和深度學習,來探索這個神祕的函數。

本質上來說,神經網絡通過一系列的中間“權重”連接我們的輸入和期望輸出數據。這些權重實際上就是一些數字。

100行Python代碼理解深度學習關鍵概念 從頭構建惡性腫瘤檢測網絡

當我們使用正確的架構和參數,通過神經網絡的結構和優化算法,我們可將神經網絡近似成一個通用函數近似器,將輸入和輸出數據聯繫起來。

創建一個神經網絡

一般來說,簡單的神經網絡包括兩層(輸入不計入層數):

1.輸入:神經網絡的輸入包含了我們的源數據。並且,神經元的數量與源數據的特徵數量相匹配。下圖中有4個輸入,當我們使用威斯康星乳腺癌數據集創建神經網絡的時候,就會使用9個輸入。

2.第一層:隱藏層,包含一些隱藏層神經元,這些神經元將會與周圍層中的所有單元相連接。

3.第二層:有一個單元,為神經網絡的輸出。

在實際的神經網絡構建過程中,我們可以使用更多的層,比如10個或20個層的網絡。為了簡單起見,在這裡,我們使用2個層。千萬不要小看這2個層,它能夠實現很多功能。

100行Python代碼理解深度學習關鍵概念 從頭構建惡性腫瘤檢測網絡

神經網絡如何進行學習

問題來了:在這個神經網絡中,學習將在哪個部分進行?

我們來回顧一下,我們在神經網絡的輸入層放置了一些數據,並向網絡展示某個輸入應該對應什麼輸出,也就是說,神經網絡的輸出(第2層)應該是什麼結果。

在神經網絡中,每個神經元都有一個相關的權重以及一個偏差。這些權重只是神經網絡在開始學習時候初始化的一些隨機數字。

神經網絡根據輸入數據和這些權重值進行計算,通過神經網絡傳播,直到輸出產生最終的結果。

這些計算的結果就是一個將輸入映射到輸出的函數。

我們需要的就是,這些神經網絡能夠計算出一個最佳權重值。因為網絡通過計算,不同的權重和不同的層結合起來,會近似出不同類型的函數。

現在,我們來進一步探索正在探尋的函數。為了方便閱讀,我們需要解釋下這些變量的名稱:

1.X表示輸入層,即提供給網絡的數據集。

2.Y表示與輸入x對應的目標輸出,由輸入經過網絡進行一系列的計算得到的輸出。

3.Yh(y hat)表示預測函數,即我們像網絡提供輸入數據集x後,經過神經網絡一系列的計算產生的輸出。因此,Y是理想的輸出,Yh是神經網絡接收到輸入數據後產生的實際輸出。

4.W表示網絡各層的權重。

我們首先看第一層——隱藏層,它執行了一個運算W*X(即W和X的乘積)。

100行Python代碼理解深度學習關鍵概念 從頭構建惡性腫瘤檢測網絡


然後進行一個加權和:

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,我們就很難確定該神經網絡在該點的輸出方向。

當然,我們也會遇到相反的情況——梯度爆炸。當梯度值非常大時,神經網絡可能就會變得非常不穩定。

不同的激活函數有各自的優點,但是都會面臨梯度消失和梯度爆炸這兩大問題。

100行Python代碼理解深度學習關鍵概念 從頭構建惡性腫瘤檢測網絡


左上: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 )

100行Python代碼理解深度學習關鍵概念 從頭構建惡性腫瘤檢測網絡


因此,本質上來說,神經網絡是一連串的函數,有些是線性函數,有些是非線性函數,它們共同組成了一個複雜的函數,將我們的輸入數據和想要的輸出數據連接了起來。

現在,我們注意到,在這個方程的所有變量中,W和b是兩個未知數,這就是神經網絡需要學習的地方。也就是說,神經網絡必須進行不斷的學習,找到W和b的正確值,才能計算出正確的函數。

因此,我們訓練神經網絡的目的也變得明瞭了,即尋找W1,b1,W2,b2的正確值。但是,在開始訓練神經網絡之前,我們必須首先對這些值進行初始化,即用隨機函數對其進行初始化處理。

初始化以後,我們就可以對神經網絡進行編碼,我們使用Python構建一個類,對這些主要的參數進行初始化處理。

我們將如何進行實戰編碼呢?請繼續閱讀我們的第二部分:用Python構建一個神經網絡。

阿里云云棲社區組織翻譯。

文章原標題《The keys of Deep Learning in 100 lines of code》

譯者:Mags,審校:袁虎。

作者:【方向】

相關推薦

推薦中...