作者:寒小陽 && 龍心塵
時間:2016年1月。
出處:
http://blog.csdn.net/han_xiaoyang/article/details/50447834
http://blog.csdn.net/longxinchen_ml/article/details/50448267
聲明:版權所有,轉載請聯繫作者並註明出處
1.神經元與含義
大家都知道最開始深度學習與神經網絡,是受人腦的神經元啓發設計出來的。所以我們按照慣例也交代一下背景,從生物學的角度開始介紹,當然也是對神經網絡研究的先驅們致一下敬。
1.1 神經元激勵與連接
大家都知道,人腦的基本計算單元叫做神經元。現代生物學表明,人的神經系統中大概有860億神經元,而這數量巨大的神經元之間大約是通過信號
也是順着軸突
(比如
下面是一個簡單的程序例子,表明前向傳播中單個神經元做的事情:
class Neuron:
# ...
def forward(inputs):
"""
假定輸入和權重都是1維的numpy數組,同時bias是一個數
"""
cell_body_sum = np.sum(inputs * self.weights) + self.bias
firing_rate = 1.0 / (1.0 + math.exp(-cell_body_sum)) # sigmoid activation function
return firing_rate
稍加解釋,每個神經元對於輸入和權重做內積,加上偏移量bias,然後通過激勵函數(比如說這裏是sigmoid函數),然後輸出結果。
特別說明:實際生物體內的神經元相當複雜,比如說,神經元的種類就灰常灰常多,它們分別有不同的功能。而加和信號之後的激勵函數的非線性變換,也比數學上模擬出來的函數複雜得多。我們用數學建模的神經網絡只是一個非常簡化後的模型,有興趣的話你可以閱讀材料1或者材料2。
1.2 單個神經元的分類作用
以sigmoid函數作爲神經元的激勵函數爲例,這個大家可能稍微熟悉一點,畢竟我們邏輯迴歸部分重點提到了這個非線性的函數,把輸入值壓縮成0-1之間的一個概率值。而通過這個非線性映射和設定的閾值,我們可以把空間切分開,分別對應正樣本區域和負樣本區域。而對應回現在的神經元場景,我們如果稍加擬人化,可以認爲神經元具備了喜歡(概率接近1)和不喜歡(概率接近0)線性劃分的某個空間區域的能力。這也就是說,只要調整好權重,單個神經元可以對空間做線性分割。
二值Softmax分類器
對於Softmax分類器詳細的內容歡迎參見前面的博文系列,我們標記
二值SVM分類器
同樣的,我們可以設定max-margin hinge loss作爲損失函數,從而將神經元訓練成一個二值支持向量機分類器。詳細的內容依舊歡迎大家查看之前的博客。
對於正則化的解釋
對於正則化的損失函數(不管是SVM還是Softmax),其實我們在神經元的生物特性上都能找到對應的解釋,我們可以將其(正則化項的作用)視作信號在神經元傳遞過程中的逐步淡化/衰減(gradual forgetting),因爲正則化項的作用是在每次迭代過程中,控制住權重
單個神經元的作用,可視作完成一個二分類的分類器(比如Softmax或者SVM分類器)
1.3 常用激勵函數
每一次輸入和權重w線性組合之後,都會通過一個激勵函數(也可以叫做非線性激勵函數),經非線性變換後輸出。實際的神經網絡中有一些可選的激勵函數,我們一一說明一下最常見的幾種:
1.3.1 sigmoid
sigmoid函數提到的次數太多,相信大家都知道了。數學形式很簡單,是
- sigmoid函數在實際梯度下降中,容易飽和和終止梯度傳遞。我們來解釋一下,大家知道反向傳播過程,依賴於計算的梯度,在一元函數中,即斜率。而在sigmoid函數圖像上,大家可以很明顯看到,在縱座標接近0和1的那些位置(也就是輸入信號的幅度很大的時候),斜率都趨於0了。我們回想一下反向傳播的過程,我們最後用於迭代的梯度,是由中間這些梯度值結果相乘得到的,因此如果中間的局部梯度值非常小,直接會把最終梯度結果拉近0,也就是說,殘差回傳的過程,因爲sigmoid函數的飽和被殺死了。說個極端的情況,如果一開始初始化權重的時候,我們取值不是很恰當,而激勵函數又全用的sigmoid函數,那麼很有可能神經元一個不剩地飽和到無法學習,整個神經網絡也根本沒辦法訓練起來。
- sigmoid函數的輸出沒有
0中心化
,這是一個比較鬧心的事情,因爲每一層的輸出都要作爲下一層的輸入,而未0中心化會直接影響梯度下降,我們這麼舉個例子吧,如果輸出的結果均值不爲0,舉個極端的例子,全部爲正的話(例如f=wTx+b 中所有x>0 ),那麼反向傳播回傳到w 上的梯度將全部爲負,這帶來的後果是,梯度更新的時候,不是平緩地迭代變化,而是類似鋸齒狀的突變。當然,要多說一句的是,這個缺點相對於第一個缺點,還稍微好一點,第一個缺點的後果是,很多場景下,神經網絡根本沒辦法學習。
1.3.2 Tanh
Tanh函數的圖像如上圖所示。它會將輸入值壓縮至-1到1之間,當然,它同樣也有sigmoid函數裏說到的第一個缺點,在很大或者很小的輸入值下,神經元很容易飽和。但是它緩解了第二個缺點,它的輸出是0中心化的。所以在實際應用中,tanh激勵函數還是比sigmoid要用的多一些的。
1.3.3 ReLU
ReLU是修正線性單元(The Rectified Linear Unit)的簡稱,近些年使用的非常多,圖像如上圖所示。它對於輸入x計算
它有它對應的優勢,也有缺點:
- 優點1:實驗表明,它的使用,相對於sigmoid和tanh,可以非常大程度地提升隨機梯度下降的收斂速度。不過有意思的是,很多人說,這個結果的原因是它是線性的,而不像sigmoid和tanh一樣是非線性的。具體的收斂速度結果對比如下圖,收斂速度大概能快上6倍:
- 優點2:相對於tanh和sigmoid激勵神經元,求梯度不要簡單太多好麼!!!畢竟,是線性的嘛。。。
- 缺點1:ReLU單元也有它的缺點,在訓練過程中,它其實挺脆弱的,有時候甚至會掛掉。舉個例子說吧,如果一個很大的梯度
流經
ReLU單元,那權重的更新結果可能是,在此之後任何的數據點都沒有辦法再激活它了。一旦這種情況發生,那本應經這個ReLU回傳的梯度,將永遠變爲0。當然,這和參數設置有關係,所以我們要特別小心,再舉個實際的例子哈,如果學習速率被設的太高,結果你會發現,訓練的過程中可能有高達40%的ReLU單元都掛掉了。所以我們要小心設定初始的學習率等參數,在一定程度上控制這個問題。
1.3.4 Leaky ReLU
上面不是提到ReLU單元的弱點了嘛,所以孜孜不倦的ML researcher們,就嘗試修復這個問題咯,他們做了這麼一件事,在x<0的部分,leaky ReLU不再讓y的取值爲0了,而是也設定爲一個坡度很小(比如斜率0.01)的直線。f(x)因此是一個分段函數,x<0時,
1.3.5 Maxout
也有一些其他的激勵函數,它們並不是對
1.4 激勵函數/神經元小總結
以上就是我們總結的常用的神經元和激勵函數類型。順便說一句,即使從計算和訓練的角度看來是可行的,實際應用中,其實我們很少會把多種激勵函數混在一起使用。
那我們咋選用神經元/激勵函數呢?一般說來,用的最多的依舊是ReLU,但是我們確實得小心設定學習率,同時在訓練過程中,還得時不時看看神經元此時的狀態(是否還『活着』)。當然,如果你非常擔心神經元訓練過程中掛掉,你可以試試Leaky ReLU和Maxout。額,少用sigmoid老古董吧,有興趣倒是可以試試tanh,不過話說回來,通常狀況下,它的效果不如ReLU/Maxout。
2. 神經網絡結構
2.1 層級連接結構
神經網絡的結構其實之前也提過,是一種單向的層級連接結構,每一層可能有多個神經元。再形象一點說,就是每一層的輸出將會作爲下一層的輸入數據,當然,這個圖一定是沒有循環的,不然數據流就有點混亂了。一般情況下,單層內的這些神經元之間是沒有連接的。最常見的一種神經網絡結構就是全連接層級神經網絡,也就是相鄰兩層之間,每個神經元和每個神經元都是相連的,單層內的神經元之間是沒有關聯的。下面是兩個全連接層級神經網的示意圖:
命名習俗
有一點需要注意,我們再說N層神經網絡的時候,通常的習慣是不把輸入層計算在內,因此輸入層直接連接輸出層的,叫做單層神經網絡。從這個角度上說,其實我們的邏輯迴歸和SVM是單層神經網絡的特例。上圖中兩個神經網絡分別是2層和3層的神經網絡。
輸出層
輸出層是神經網絡中比較特殊的一層,由於輸出的內容通常是各類別的打分/概率(在分類問題中),我們通常都不在輸出層神經元中加激勵函數。
關於神經網絡中的組件個數
通常我們在確定一個神經網絡的時候,有幾個描述神經網絡大小的參數會提及到。最常見的兩個是神經元個數,以及細化一點說,我們可以認爲是參數的個數。還是拿上面的圖舉例:
- 第一個神經網絡有4+2=6個神經元(我們不算輸入層),因此有[3*4]+[4*2]=20個權重和4+2=6個偏移量(bias項),總共26個參數。
- 第二個神經網絡有4+4+1個神經元,有[3*4]+[4*4]+[4*1]=32個權重,再加上4+4+1=9個偏移量(bias項),一共有41個待學習的參數。
給大家個具體的概念哈,現在實用的卷積神經網,大概有億級別的參數,甚至可能有10-20層(因此是深度學習嘛)。不過不用擔心這麼多參數的訓練問題,因此我們在卷積神經網裏會有一些有效的方法,來共享參數,從而減少需要訓練的量。
2.2 神經網絡的前向計算示例
神經網絡組織成以上的結構,一個重要的原因是,每一層到下一層的計算可以很方便地表示成矩陣之間的運算,就是一直重複權重和輸入做內積後經過激勵函數變換的過程。爲了形象一點說明,我們還舉上面的3層神經網絡爲例,輸入是一個3*1的向量,而層和層之間的連接權重可以看做一個矩陣,比如第一個隱藏層的權重np.dot(W1,x)
實際上就計算出輸入下一層的激勵函數之前的結果,經激勵函數作用之後的結果又作爲新的輸出。用簡單的代碼表示如下:
# 3層神經網絡的前向運算:
f = lambda x: 1.0/(1.0 + np.exp(-x)) # 簡單起見,我們還是用sigmoid作爲激勵函數吧
x = np.random.randn(3, 1) # 隨機化一個輸入
h1 = f(np.dot(W1, x) + b1) # 計算第一層的輸出
h2 = f(np.dot(W2, h1) + b2) # 計算第二層的輸出
out = np.dot(W3, h2) + b3 # 最終結果 (1x1)
上述代碼中,W1,W2,W3,b1,b2,b3
都是待學習的神經網絡參數。注意到我們這裏所有的運算都是向量化/矩陣化之後的,x不再是一個數,而是包含訓練集中一個batch的輸入,這樣並行運算會加快計算的速度,仔細看代碼,最後一層是沒有經過激勵函數,直接輸出的。
2.3 神經網絡的表達力與size
一個神經網絡結構搭起來之後,它就包含了數以億計的參數和函數。我們可以把它看做對輸入的做了一個很複雜的函數映射,得到最後的結果用於完成空間的分割(分類問題中)。那我們的參數對於這個所謂的複雜映射有什麼樣的影響呢?
其實,包含一個隱藏層(2層神經網絡)的神經網絡已經具備大家期待的能力,即只要隱藏層的神經元個數足夠,我們總能用它(2層神經網絡)去逼近任何連續函數(即輸入到輸出的映射關係)。詳細的內容可以參加Approximation by Superpositions of Sigmoidal Function或者Michael Nielsen的介紹。我們之前的博文手把手入門神經網絡系列(1)_從初等數學的角度初探神經網絡也有提到。
問題是,如果單隱藏層的神經網絡已經可以近似逼近任意的連續值函數,那麼爲什麼我們還要用那麼多層呢?很可惜的是,即使數學上我們可以用2層神經網近似幾乎所有函數,但在實際的工程實踐中,卻是沒啥大作用的。多隱藏層的神經網絡比單隱藏層的神經網絡工程效果好很多,即使從數學上看,表達能力應該是一致的。
不過還得說一句的是,通常情況下,我們工程中發現,3層神經網絡效果優於2層神經網絡,但是如果把層數再不斷增加(4,5,6層),對最後結果的幫助就沒有那麼大的跳變了。不過在卷積神經網上還是不一樣的,深層的網絡結構對於它的準確率有很大的幫助,直觀理解的方式是,圖像是一種深層的結構化數據,因此深層的卷積神經網絡能夠更準確地把這些層級信息表達出來。
2.4 層數與參數設定的影響
一個很現實的問題是,我們拿到一個實際問題的時候,怎麼知道應該如何去搭建一個網絡結構,可以最好地解決這個問題?應該搭建幾層?每一層又應該有多少個神經元?
我們直觀理解一下這個問題,當我們加大層數以及每一層的神經元個數的時候,我們的神經網絡容量
變大了。更通俗一點說,神經網絡的空間表達能力變得更豐富了。放到一個具體的例子裏我們看看,加入我們現在要處理一個2分類問題,輸入是2維的,我們訓練3個不同神經元個數的單隱層神經網絡,它們的平面表達能力對比畫出來如下:
在上圖中,我們可以看出來,更多的神經元,讓神經網絡有更好的擬合複雜空間函數的能力。但是任何事物都有雙面性,擬合越來越精確帶來的另外一個問題是,太容易過擬合了!!!,如果你很任性地做一個實驗,在隱藏層中放入20個神經元,那對於上圖這個一個平面,你完全可以做到100%把兩類點分隔開,但是這樣一個分類器太努力地學習和記住我們現在圖上的這些點的分佈狀況了,以至於連噪聲和離羣點都被它學習下來了,這對於我們在新數據上的泛化能力,也是一個噩夢。
經我們上面的討論之後,也許你會覺得,好像對於不那麼複雜的問題,我們用更少數目的層數和神經元,會更不容易過擬合,效果好一些。但是這個想法是錯誤的!!!。永遠不要用減少層數和神經元的方法來緩解過擬合!!!這會極大影響神經網絡的表達能力!!!我們有其他的方法,比如說之前一直提到的正則化來緩解這個問題。
不要使用少層少神經元的簡單神經網絡的另外一個原因是,其實我們用梯度下降等方法,在這種簡單神經網上,更難訓練得到合適的參數結果。對,你會和我說,簡單神經網絡的損失函數有更少的局部最低點,應該更好收斂。是的,確實是的,更好收斂,但是很快收斂到的這些個局部最低點,通常都是全局很差的。相反,大的神經網絡,確實損失函數有更多的局部最低點,但是這些局部最低點,相對於上面的局部最低點,在實際中效果卻更好一些。對於非凸的函數,我們很難從數學上給出100%精準的性質證明,大家要是感興趣的話,可以參考論文The Loss Surfaces of Multilayer Networks。
如果你願意做多次實驗,會發現,訓練小的神經網絡,最後的損失函數收斂到的最小值變動非常大。這意味着,如果你運氣夠好,那你maybe能找到一組相對較爲合適的參數,但大多數情況下,你得到的參數只是在一個不太好的局部最低點上的。相反,大的神經網絡,依舊不能保證收斂到最小的全局最低點,但是衆多的局部最低點,都有相差不太大的效果,這意味着你不需要藉助”運氣”也能找到一個近似較優的參數組。
最後,我們提一下正則化,我們說了要用正則化來控制過擬合問題。正則話的參數是
恩,總之一句話,我們在很多實際問題中,還是得使用多層多神經元的大神經網絡,而使用正則化來減緩過擬合現象。
3. 其他參考資料
- Theano的深度學習導讀
- Michael Nielsen的神經網絡導論
- ConvNetJS demo
作者:寒小陽 && 龍心塵
時間:2016年1月。
出處:http://blog.csdn.net/han_xiaoyang/article/details/50447834
聲明:版權所有,轉載請聯繫作者並註明出處
1.神經元與含義
大家都知道最開始深度學習與神經網絡,是受人腦的神經元啓發設計出來的。所以我們按照慣例也交代一下背景,從生物學的角度開始介紹,當然也是對神經網絡研究的先驅們致一下敬。
1.1 神經元激勵與連接
大家都知道,人腦的基本計算單元叫做神經元。現代生物學表明,人的神經系統中大概有860億神經元,而這數量巨大的神經元之間大約是通過信號
也是順着軸突
(比如
下面是一個簡單的程序例子,表明前向傳播中單個神經元做的事情:
class Neuron:
# ...
def forward(inputs):
"""
假定輸入和權重都是1維的numpy數組,同時bias是一個數
"""
cell_body_sum = np.sum(inputs * self.weights) + self.bias
firing_rate = 1.0 / (1.0 + math.exp(-cell_body_sum)) # sigmoid activation function
return firing_rate
稍加解釋,每個神經元對於輸入和權重做內積,加上偏移量bias,然後通過激勵函數(比如說這裏是sigmoid函數),然後輸出結果。
特別說明:實際生物體內的神經元相當複雜,比如說,神經元的種類就灰常灰常多,它們分別有不同的功能。而加和信號之後的激勵函數的非線性變換,也比數學上模擬出來的函數複雜得多。我們用數學建模的神經網絡只是一個非常簡化後的模型,有興趣的話你可以閱讀材料1或者材料2。
1.2 單個神經元的分類作用
以sigmoid函數作爲神經元的激勵函數爲例,這個大家可能稍微熟悉一點,畢竟我們邏輯迴歸部分重點提到了這個非線性的函數,把輸入值壓縮成0-1之間的一個概率值。而通過這個非線性映射和設定的閾值,我們可以把空間切分開,分別對應正樣本區域和負樣本區域。而對應回現在的神經元場景,我們如果稍加擬人化,可以認爲神經元具備了喜歡(概率接近1)和不喜歡(概率接近0)線性劃分的某個空間區域的能力。這也就是說,只要調整好權重,單個神經元可以對空間做線性分割。
二值Softmax分類器
對於Softmax分類器詳細的內容歡迎參見前面的博文系列,我們標記
二值SVM分類器
同樣的,我們可以設定max-margin hinge loss作爲損失函數,從而將神經元訓練成一個二值支持向量機分類器。詳細的內容依舊歡迎大家查看之前的博客。
對於正則化的解釋
對於正則化的損失函數(不管是SVM還是Softmax),其實我們在神經元的生物特性上都能找到對應的解釋,我們可以將其(正則化項的作用)視作信號在神經元傳遞過程中的逐步淡化/衰減(gradual forgetting),因爲正則化項的作用是在每次迭代過程中,控制住權重
單個神經元的作用,可視作完成一個二分類的分類器(比如Softmax或者SVM分類器)
1.3 常用激勵函數
每一次輸入和權重w線性組合之後,都會通過一個激勵函數(也可以叫做非線性激勵函數),經非線性變換後輸出。實際的神經網絡中有一些可選的激勵函數,我們一一說明一下最常見的幾種:
1.3.1 sigmoid
sigmoid函數提到的次數太多,相信大家都知道了。數學形式很簡單,是
- sigmoid函數在實際梯度下降中,容易飽和和終止梯度傳遞。我們來解釋一下,大家知道反向傳播過程,依賴於計算的梯度,在一元函數中,即斜率。而在sigmoid函數圖像上,大家可以很明顯看到,在縱座標接近0和1的那些位置(也就是輸入信號的幅度很大的時候),斜率都趨於0了。我們回想一下反向傳播的過程,我們最後用於迭代的梯度,是由中間這些梯度值結果相乘得到的,因此如果中間的局部梯度值非常小,直接會把最終梯度結果拉近0,也就是說,殘差回傳的過程,因爲sigmoid函數的飽和被殺死了。說個極端的情況,如果一開始初始化權重的時候,我們取值不是很恰當,而激勵函數又全用的sigmoid函數,那麼很有可能神經元一個不剩地飽和到無法學習,整個神經網絡也根本沒辦法訓練起來。
- sigmoid函數的輸出沒有
0中心化
,這是一個比較鬧心的事情,因爲每一層的輸出都要作爲下一層的輸入,而未0中心化會直接影響梯度下降,我們這麼舉個例子吧,如果輸出的結果均值不爲0,舉個極端的例子,全部爲正的話(例如f=wTx+b 中所有x>0 ),那麼反向傳播回傳到w 上的梯度將全部爲負,這帶來的後果是,梯度更新的時候,不是平緩地迭代變化,而是類似鋸齒狀的突變。當然,要多說一句的是,這個缺點相對於第一個缺點,還稍微好一點,第一個缺點的後果是,很多場景下,神經網絡根本沒辦法學習。
1.3.2 Tanh
Tanh函數的圖像如上圖所示。它會將輸入值壓縮至-1到1之間,當然,它同樣也有sigmoid函數裏說到的第一個缺點,在很大或者很小的輸入值下,神經元很容易飽和。但是它緩解了第二個缺點,它的輸出是0中心化的。所以在實際應用中,tanh激勵函數還是比sigmoid要用的多一些的。
1.3.3 ReLU
ReLU是修正線性單元(The Rectified Linear Unit)的簡稱,近些年使用的非常多,圖像如上圖所示。它對於輸入x計算
它有它對應的優勢,也有缺點:
- 優點1:實驗表明,它的使用,相對於sigmoid和tanh,可以非常大程度地提升隨機梯度下降的收斂速度。不過有意思的是,很多人說,這個結果的原因是它是線性的,而不像sigmoid和tanh一樣是非線性的。具體的收斂速度結果對比如下圖,收斂速度大概能快上6倍:
- 優點2:相對於tanh和sigmoid激勵神經元,求梯度不要簡單太多好麼!!!畢竟,是線性的嘛。。。
- 缺點1:ReLU單元也有它的缺點,在訓練過程中,它其實挺脆弱的,有時候甚至會掛掉。舉個例子說吧,如果一個很大的梯度
流經
ReLU單元,那權重的更新結果可能是,在此之後任何的數據點都沒有辦法再激活它了。一旦這種情況發生,那本應經這個ReLU回傳的梯度,將永遠變爲0。當然,這和參數設置有關係,所以我們要特別小心,再舉個實際的例子哈,如果學習速率被設的太高,結果你會發現,訓練的過程中可能有高達40%的ReLU單元都掛掉了。所以我們要小心設定初始的學習率等參數,在一定程度上控制這個問題。
1.3.4 Leaky ReLU
上面不是提到ReLU單元的弱點了嘛,所以孜孜不倦的ML researcher們,就嘗試修復這個問題咯,他們做了這麼一件事,在x<0的部分,leaky ReLU不再讓y的取值爲0了,而是也設定爲一個坡度很小(比如斜率0.01)的直線。f(x)因此是一個分段函數,x<0時,
1.3.5 Maxout
也有一些其他的激勵函數,它們並不是對
1.4 激勵函數/神經元小總結
以上就是我們總結的常用的神經元和激勵函數類型。順便說一句,即使從計算和訓練的角度看來是可行的,實際應用中,其實我們很少會把多種激勵函數混在一起使用。
那我們咋選用神經元/激勵函數呢?一般說來,用的最多的依舊是ReLU,但是我們確實得小心設定學習率,同時在訓練過程中,還得時不時看看神經元此時的狀態(是否還『活着』)。當然,如果你非常擔心神經元訓練過程中掛掉,你可以試試Leaky ReLU和Maxout。額,少用sigmoid老古董吧,有興趣倒是可以試試tanh,不過話說回來,通常狀況下,它的效果不如ReLU/Maxout。
2. 神經網絡結構
2.1 層級連接結構
神經網絡的結構其實之前也提過,是一種單向的層級連接結構,每一層可能有多個神經元。再形象一點說,就是每一層的輸出將會作爲下一層的輸入數據,當然,這個圖一定是沒有循環的,不然數據流就有點混亂了。一般情況下,單層內的這些神經元之間是沒有連接的。最常見的一種神經網絡結構就是全連接層級神經網絡,也就是相鄰兩層之間,每個神經元和每個神經元都是相連的,單層內的神經元之間是沒有關聯的。下面是兩個全連接層級神經網的示意圖:
命名習俗
有一點需要注意,我們再說N層神經網絡的時候,通常的習慣是不把輸入層計算在內,因此輸入層直接連接輸出層的,叫做單層神經網絡。從這個角度上說,其實我們的邏輯迴歸和SVM是單層神經網絡的特例。上圖中兩個神經網絡分別是2層和3層的神經網絡。
輸出層
輸出層是神經網絡中比較特殊的一層,由於輸出的內容通常是各類別的打分/概率(在分類問題中),我們通常都不在輸出層神經元中加激勵函數。
關於神經網絡中的組件個數
通常我們在確定一個神經網絡的時候,有幾個描述神經網絡大小的參數會提及到。最常見的兩個是神經元個數,以及細化一點說,我們可以認爲是參數的個數。還是拿上面的圖舉例:
- 第一個神經網絡有4+2=6個神經元(我們不算輸入層),因此有[3*4]+[4*2]=20個權重和4+2=6個偏移量(bias項),總共26個參數。
- 第二個神經網絡有4+4+1個神經元,有[3*4]+[4*4]+[4*1]=32個權重,再加上4+4+1=9個偏移量(bias項),一共有41個待學習的參數。
給大家個具體的概念哈,現在實用的卷積神經網,大概有億級別的參數,甚至可能有10-20層(因此是深度學習嘛)。不過不用擔心這麼多參數的訓練問題,因此我們在卷積神經網裏會有一些有效的方法,來共享參數,從而減少需要訓練的量。
2.2 神經網絡的前向計算示例
神經網絡組織成以上的結構,一個重要的原因是,每一層到下一層的計算可以很方便地表示成矩陣之間的運算,就是一直重複權重和輸入做內積後經過激勵函數變換的過程。爲了形象一點說明,我們還舉上面的3層神經網絡爲例,輸入是一個3*1的向量,而層和層之間的連接權重可以看做一個矩陣,比如第一個隱藏層的權重np.dot(W1,x)
實際上就計算出輸入下一層的激勵函數之前的結果,經激勵函數作用之後的結果又作爲新的輸出。用簡單的代碼表示如下:
# 3層神經網絡的前向運算:
f = lambda x: 1.0/(1.0 + np.exp(-x)) # 簡單起見,我們還是用sigmoid作爲激勵函數吧
x = np.random.randn(3, 1) # 隨機化一個輸入
h1 = f(np.dot(W1, x) + b1) # 計算第一層的輸出
h2 = f(np.dot(W2, h1) + b2) # 計算第二層的輸出
out = np.dot(W3, h2) + b3 # 最終結果 (1x1)
上述代碼中,W1,W2,W3,b1,b2,b3
都是待學習的神經網絡參數。注意到我們這裏所有的運算都是向量化/矩陣化之後的,x不再是一個數,而是包含訓練集中一個batch的輸入,這樣並行運算會加快計算的速度,仔細看代碼,最後一層是沒有經過激勵函數,直接輸出的。
2.3 神經網絡的表達力與size
一個神經網絡結構搭起來之後,它就包含了數以億計的參數和函數。我們可以把它看做對輸入的做了一個很複雜的函數映射,得到最後的結果用於完成空間的分割(分類問題中)。那我們的參數對於這個所謂的複雜映射有什麼樣的影響呢?
其實,包含一個隱藏層(2層神經網絡)的神經網絡已經具備大家期待的能力,即只要隱藏層的神經元個數足夠,我們總能用它(2層神經網絡)去逼近任何連續函數(即輸入到輸出的映射關係)。詳細的內容可以參加Approximation by Superpositions of Sigmoidal Function或者Michael Nielsen的介紹。我們之前的博文手把手入門神經網絡系列(1)_從初等數學的角度初探神經網絡也有提到。
問題是,如果單隱藏層的神經網絡已經可以近似逼近任意的連續值函數,那麼爲什麼我們還要用那麼多層呢?很可惜的是,即使數學上我們可以用2層神經網近似幾乎所有函數,但在實際的工程實踐中,卻是沒啥大作用的。多隱藏層的神經網絡比單隱藏層的神經網絡工程效果好很多,即使從數學上看,表達能力應該是一致的。
不過還得說一句的是,通常情況下,我們工程中發現,3層神經網絡效果優於2層神經網絡,但是如果把層數再不斷增加(4,5,6層),對最後結果的幫助就沒有那麼大的跳變了。不過在卷積神經網上還是不一樣的,深層的網絡結構對於它的準確率有很大的幫助,直觀理解的方式是,圖像是一種深層的結構化數據,因此深層的卷積神經網絡能夠更準確地把這些層級信息表達出來。
2.4 層數與參數設定的影響
一個很現實的問題是,我們拿到一個實際問題的時候,怎麼知道應該如何去搭建一個網絡結構,可以最好地解決這個問題?應該搭建幾層?每一層又應該有多少個神經元?
我們直觀理解一下這個問題,當我們加大層數以及每一層的神經元個數的時候,我們的神經網絡容量
變大了。更通俗一點說,神經網絡的空間表達能力變得更豐富了。放到一個具體的例子裏我們看看,加入我們現在要處理一個2分類問題,輸入是2維的,我們訓練3個不同神經元個數的單隱層神經網絡,它們的平面表達能力對比畫出來如下:
在上圖中,我們可以看出來,更多的神經元,讓神經網絡有更好的擬合複雜空間函數的能力。但是任何事物都有雙面性,擬合越來越精確帶來的另外一個問題是,太容易過擬合了!!!,如果你很任性地做一個實驗,在隱藏層中放入20個神經元,那對於上圖這個一個平面,你完全可以做到100%把兩類點分隔開,但是這樣一個分類器太努力地學習和記住我們現在圖上的這些點的分佈狀況了,以至於連噪聲和離羣點都被它學習下來了,這對於我們在新數據上的泛化能力,也是一個噩夢。
經我們上面的討論之後,也許你會覺得,好像對於不那麼複雜的問題,我們用更少數目的層數和神經元,會更不容易過擬合,效果好一些。但是這個想法是錯誤的!!!。永遠不要用減少層數和神經元的方法來緩解過擬合!!!這會極大影響神經網絡的表達能力!!!我們有其他的方法,比如說之前一直提到的正則化來緩解這個問題。
不要使用少層少神經元的簡單神經網絡的另外一個原因是,其實我們用梯度下降等方法,在這種簡單神經網上,更難訓練得到合適的參數結果。對,你會和我說,簡單神經網絡的損失函數有更少的局部最低點,應該更好收斂。是的,確實是的,更好收斂,但是很快收斂到的這些個局部最低點,通常都是全局很差的。相反,大的神經網絡,確實損失函數有更多的局部最低點,但是這些局部最低點,相對於上面的局部最低點,在實際中效果卻更好一些。對於非凸的函數,我們很難從數學上給出100%精準的性質證明,大家要是感興趣的話,可以參考論文The Loss Surfaces of Multilayer Networks。
如果你願意做多次實驗,會發現,訓練小的神經網絡,最後的損失函數收斂到的最小值變動非常大。這意味着,如果你運氣夠好,那你maybe能找到一組相對較爲合適的參數,但大多數情況下,你得到的參數只是在一個不太好的局部最低點上的。相反,大的神經網絡,依舊不能保證收斂到最小的全局最低點,但是衆多的局部最低點,都有相差不太大的效果,這意味着你不需要藉助”運氣”也能找到一個近似較優的參數組。
最後,我們提一下正則化,我們說了要用正則化來控制過擬合問題。正則話的參數是
恩,總之一句話,我們在很多實際問題中,還是得使用多層多神經元的大神經網絡,而使用正則化來減緩過擬合現象。