當前位置:
首頁 > 科技 > 小白都能看懂的神經網路教程:從原理到優化如此簡單

小白都能看懂的神經網路教程:從原理到優化如此簡單

曉查 發自 凹非寺

量子位 報道 | 公眾號 QbitAI

「我在網上看到過很多神經網路的實現方法,但這一篇是最簡單、最清晰的。」

一位來自普林斯頓的華人小哥Victor Zhou,寫了篇神經網路入門教程,在線代碼網站Repl.it聯合創始人Amjad Masad看完以後,給予如是評價。

這篇教程發布僅天時間,就在Hacker News論壇上收穫了574贊。程序員們紛紛誇讚這篇文章的代碼寫得很好,變數名很規範,讓人一目了然。

下面就讓我們一起從零開始學習神經網路吧。

實現方法

搭建基本模塊——神經元

在說神經網路之前,我們討論一下神經元(Neurons),它是神經網路的基本單元。神經元先獲得輸入,然後執行某些數學運算後,再產生一個輸出。比如一個2輸入神經元的例子:

在這個神經元中,輸入總共經歷了3步數學運算,

先將兩個輸入乘以權重(weight):

x1x1×w1

x2x2×w2

把兩個結果想加,再加上一個偏置(bias):

(x1×w1) (x2×w2) b

最後將它們經過激活函數(activation function)處理得到輸出:

y = f(x1×w1 x2×w2 b)

激活函數的作用是將無限制的輸入轉換為可預測形式的輸出。一種常用的激活函數是sigmoid函數:

sigmoid函數的輸出介於0和1,我們可以理解為它把 (?∞, ∞) 範圍內的數壓縮到 (0, 1)以內。正值越大輸出越接近1,負向數值越大輸出越接近0。

舉個例子,上面神經元里的權重和偏置取如下數值:

w=[0,1]

b = 4

w=[0,1]是w1=0、w2=1的向量形式寫法。給神經元一個輸入x=[2,3],可以用向量點積的形式把神經元的輸出計算出來:

w·x b =(x1×w1) (x2×w2) b= 0×2 1×3 4=7

y=f(w?X b)=f(7)=0.999

以上步驟的Python代碼是:

我們在代碼中調用了一個強大的Python數學函數庫NumPy

搭建神經網路

神經網路就是把一堆神經元連接在一起,下面是一個神經網路的簡單舉例:

這個網路有2個輸入、一個包含2個神經元的隱藏層(h1和h2)、包含1個神經元的輸出層o1。

隱藏層是夾在輸入輸入層和輸出層之間的部分,一個神經網路可以有多個隱藏層。

把神經元的輸入向前傳遞獲得輸出的過程稱為前饋(feedforward)。

我們假設上面的網路里所有神經元都具有相同的權重w=[0,1]和偏置b=0,激活函數都是sigmoid,那麼我們會得到什麼輸出呢?

h1=h2=f(w?x b)=f((0×2) (1×3) 0)

=f(3)

=0.9526

o1=f(w?[h1,h2] b)=f((0?h1) (1?h2) 0)

=f(0.9526)

=0.7216

以下是實現代碼:

訓練神經網路

現在我們已經學會了如何搭建神經網路,現在我們來學習如何訓練它,其實這就是一個優化的過程。

假設有一個數據集,包含4個人的身高、體重和性別:

現在我們的目標是訓練一個網路,根據體重和身高來推測某人的性別。

為了簡便起見,我們將每個人的身高、體重減去一個固定數值,把性別男定義為1、性別女定義為0。

在訓練神經網路之前,我們需要有一個標準定義它到底好不好,以便我們進行改進,這就是損失(loss)。

比如用均方誤差(MSE)來定義損失:

n是樣本的數量,在上面的數據集中是4;

y代表人的性別,男性是1,女性是0;

ytrue是變數的真實值,ypred是變數的預測值。

顧名思義,均方誤差就是所有數據方差的平均值,我們不妨就把它定義為損失函數。預測結果越好,損失就越低,訓練神經網路就是將損失最小化。

如果上面網路的輸出一直是0,也就是預測所有人都是男性,那麼損失是:

MSE= 1/4 (1 0 0 1)= 0.5

計算損失函數的代碼如下:

減少神經網路損失

這個神經網路不夠好,還要不斷優化,盡量減少損失。我們知道,改變網路的權重和偏置可以影響預測值,但我們應該怎麼做呢?

為了簡單起見,我們把數據集縮減到只包含Alice一個人的數據。於是損失函數就剩下Alice一個人的方差:

預測值是由一系列網路權重和偏置計算出來的:

所以損失函數實際上是包含多個權重、偏置的多元函數:

(注意!前方高能!需要你有一些基本的多元函數微分知識,比如偏導數、鏈式求導法則。)

如果調整一下w1,損失函數是會變大還是變小?我們需要知道偏導數?L/?w1是正是負才能回答這個問題。

根據鏈式求導法則:

而L=(1-ypred)2,可以求得第一項偏導數:

接下來我們要想辦法獲得ypred和w1的關係,我們已經知道神經元h1、h2和o1的數學運算規則:

實際上只有神經元h1中包含權重w1,所以我們再次運用鏈式求導法則:

然後求?h1/?w1

我們在上面的計算中遇到了2次激活函數sigmoid的導數f′(x),sigmoid函數的導數很容易求得:

總的鏈式求導公式:

這種向後計算偏導數的系統稱為反向傳播(backpropagation)。

上面的數學符號太多,下面我們帶入實際數值來計算一下。h1、h2和o1

h1=f(x1?w1 x2?w2 b1)=0.0474

h2=f(w3?x3 w4?x4 b2)=0.0474

o1=f(w5?h1 w6?h2 b3)=f(0.0474 0.0474 0)=f(0.0948)=0.524

神經網路的輸出y=0.524,沒有顯示出強烈的是男(1)是女(0)的證據。現在的預測效果還很不好。

我們再計算一下當前網路的偏導數?L/?w1:

這個結果告訴我們:如果增大w1,損失函數L會有一個非常小的增長。

隨機梯度下降

下面將使用一種稱為隨機梯度下降(SGD)的優化演算法,來訓練網路。

經過前面的運算,我們已經有了訓練神經網路所有數據。但是該如何操作?SGD定義了改變權重和偏置的方法:

η是一個常數,稱為學習率(learning rate),它決定了我們訓練網路速率的快慢。將w1減去η·?L/?w1,就等到了新的權重w1。

當?L/?w1是正數時,w1會變小;當?L/?w1是負數 時,w1會變大。

如果我們用這種方法去逐步改變網路的權重w和偏置b,損失函數會緩慢地降低,從而改進我們的神經網路。

訓練流程如下:

1、從數據集中選擇一個樣本;

2、計算損失函數對所有權重和偏置的偏導數;

3、使用更新公式更新每個權重和偏置;

4、回到第1步。

我們用Python代碼實現這個過程:

隨著學習過程的進行,損失函數逐漸減小。

現在我們可以用它來推測出每個人的性別了:

更多

這篇教程只是萬里長征第一步,後面還有很多知識需要學習:

1、用更大更好的機器學習庫搭建神經網路,如Tensorflow、Keras、PyTorch

2、在瀏覽器中的直觀理解神經網路:https://playground.tensorflow.org/

3、學習sigmoid以外的其他激活函數:https://keras.io/activations/

4、學習SGD以外的其他優化器:https://keras.io/optimizers/

5、學習卷積神經網路(CNN)

6、學習遞歸神經網路(RNN)

這些都是Victor給自己挖的「坑」。他表示自己未來「可能」會寫這些主題內容,希望他能陸續把這些坑填完。如果你想入門神經網路,不妨去訂閱他的博客。

關於這位小哥

Victor Zhou是普林斯頓2019級CS畢業生,已經拿到Facebook軟體工程師的offer,今年8月入職。他曾經做過JS編譯器,還做過兩款頁游,一個仇恨攻擊言論的識別庫。

最後附上小哥的博客鏈接:

https://victorzhou.com/

訂閱AI內參,獲取行業資訊

誠摯招聘

量子位正在招募編輯/記者,工作地點在北京中關村。期待有才氣、有熱情的同學加入我們!相關細節,請在量子位公眾號(QbitAI)對話界面,回復「招聘」兩個字。

喜歡就點「好看」吧 !


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 量子位 的精彩文章:

迄今最大公開語音數據集上線,漢語部分還不夠強,需要你來幫忙
Waymo要開啟對外融資:跟歐洲車廠火熱,拿錢應付股權兌現危機

TAG:量子位 |