1. 程式人生 > >deeplearning.ai 改善深層神經網絡 week3 聽課筆記

deeplearning.ai 改善深層神經網絡 week3 聽課筆記

drop 概率 向量 mini 之前 裏的 bsp 結合 一周

這一周的主體是調參。

1. 超參數:No. 1最重要,No. 2其次,No. 3其次次。

  No. 1學習率α:最重要的參數。在log取值空間隨機采樣。例如取值範圍是[0.001, 1],r = -4*np.random.rand(), α = 10r

  No. 2 Momentum β:0.9是個不錯的選擇。在1-β的log取值空間隨機采樣。例如取值範圍[0.9, 0.999],則1-β的取值空間[0.001, 0.1]。

  No. 2 各個隱含層的神經元數量:可以在線性取值空間隨機采樣。

  No. 2 mini-batch的大小:

  No. 3 神經網絡層數:可以在線性取值空間隨機采樣。

  No. 3 Learning rate decay:

  Adam算法中的 β1、β1、ε:從來不調,用默認值,0.9、0.999、10-8.

  調試超參數的時候,不要在參數的取值範圍均勻采樣(網格),而要隨機采樣。

  從粗到細收縮參數的取值範圍。

  同一個神經網絡用在不同的領域,最優的超參數是很可能不同的;即使在同一個領域,隨著時間的推移,數據的變化,最優的超參數也會發生變化。所以要時不時重新調參,看能不能找到更好地。

  兩大類調參流派:1)對於數據量很大(比如計算機視覺、廣告),計算資源不夠,一次只能負擔起試驗一個模型或一小批模型,維護一條loss function,逐漸改良模型,努力讓loss function越來越小。2)並行試驗多種模型,同時看好多條loss function,直接選最好的那個。NG戲稱第一類是熊貓型,每次只生一個(或幾個)小孩,悉心照料;第二類則是魚子(caviar)類,每次生一大堆,也不管不問,就看最後誰長得好。如果有足夠的計算資源並行計算模型,那一定選第二類。否則,則選第一類。

2. Batch normalization:

  基本想法是,既然把輸入歸一化可以加速優化,那麽可以把中間層對下一層的輸出也歸一化。NG說這裏可以選擇是歸一化未激活的z[l],也可以歸一化激活後的a[l],他建議默認選擇是z[l]。

  具體算法:

  對於神經網絡中的某一層,z[l](i), ..., z[l](m),這裏是對每個特征在所有樣本上的分布。

    μ = 1/m*(∑z(i)),#省略了第l層的[l]標記。

    σ2 = 1/m*(∑(z(i)-μ)2),

    znorm(i) = (z(i) - μ)/sqrt(σ2+ε)

    ztilde(i) = γznorm

(i) + β,#這裏γ和β是神經網絡可以學習的參數,這相當於給它自由度,並不像對輸入數據一樣強制要求均值為0方差為1。

  

  例如對於某個網絡可能會是這樣的前向傳播:

w[1], b[1] β[1], γ[1] w[2], b[2] β[2], γ[2]

x ---------------> z[1] ---------------> ztilt[1] ---------------> a[1] = g[1](ztilt[1]) ---------------> z[2] ---------------> ztilt[2] ---------------> a[2] --------------->...

  此時的參數包括 w[1], b[1], w[2], b[2],...,w[l], b[l],β[1], γ[1], β[2], γ[2],...,β[l], γ[l]。註意這裏的β和優化中的β(例如Momentum)是完全不同的參數,不要搞混。

  由於z[l] = w[l]*a[l-1] + b[l],緊跟著做歸一化時,b[l]是被減去了,所以實際可以把公式簡化為z[l] = w[l]*a[l-1] 。然後計算znorm[l],接著計算ztilde[l][l]znorm[l] + β[l]。此時β[l]體現了之前b[l]的作用。所以實際的參數包括w[1], w[2],...,w[l], β[1], γ[1], β[2], γ[2],...,β[l], γ[l]。另外,z[l]的維度是(n[l], 1),β[l]和γ[l]的維度也都是(n[l], 1)。n[l]是第l層的神經元數量。

  當和mini-batch結合的時候,則是對每個mini-batch前向計算的時候,在z[l]和a[l]之間插入針對當前mini-batch數據的歸一化層。

  總結算法:

  遍歷所有mini-batch

    計算當前mini-batch的前向傳播

      在每一層,用batch normalization計算出ztilt[l]

    計算反向傳播,得到 dw[l], dβ[l], dγ[l]

    更新參數,可以用標準梯度下降、Momentum、RMSprop、Adam等算法。

  

  為什麽在中間層做batch normalization有效呢?1)第一個很淺顯的原因是和輸入層特征歸一化一樣,各個維度近似分布更利於優化。2)第二個原因是它使得後面的層對於前面層的變化更魯棒。為了更好地解釋這個原因,我們先設想一個算法在數據集A上訓練,然後在B上測試,A和B的分布相差約大,越不利於算法泛化。Covariate shift描述的就是這種數據分布發生變化的現象。對於深度學習來說,各個層神經元是處理前面的網絡傳過來的數據,如果前面網絡的參數發生變化(比如因為優化叠代),則傳入這一層的數據也會發生變化,這就產生了covaraite shift。Batch normalization就緩解了這個問題,它把不同分布的數據歸一化成比較穩定的分布,限制了前面網絡產生的數據的shift。或者說它減小了不同層之間的關聯,使得每一層網絡可以自己學習。這有助於加速整個網絡的學習。3)第三個原因是batch normalization有輕微的正則化效果,在歸一化的作用下每個mini-batch被它的均值和方差縮放,由於均值、方差只是小部分數據算出來是有噪音的,所以類似dropout(每個神經元有一定概率被刪掉),它在每個隱藏層的輸出上加了噪音,這迫使後面的層不過分依賴任何一個隱藏單元。但是由於噪音小,所以並不是巨大的正則化效果,可以把batch normalization和dropout一起用。NG強調batch normalizatoin只是有輕微正則化效果,但是還是不要把它當做正則化手段。

  訓練階段是用mini-batch訓練權重,而在測試階段,需要根據訓練集來估算測試樣本的均值μ和方差σ2,一般采用的方法是對mini-batch算出的均值、方差做指數加權平均。

3. Softmax回歸:logistic回歸的一般形式,從識別兩個分類推廣到多個分類。

  對於多分類的應用,神經網絡的最後一層(第L層)是Softmax層,z[L] = w[L]a[L-1] + b[L],中間變量t = exp(z[L]),這是對z[L]的每個元素進行exp操作,如果是四分類的問題,則z[L]的形狀是(4, 1),t也是(4, 1)。激活函數 a[L] = exp(z[L])/(∑ti),ti是t的第i個元素,a[L]的形狀也是(4, 1),a[L]的第i個元素ai[L] = ti/∑ti。ai[L]的可以看成是每個類的概率。

  Softmax和Logistic回歸都是對特征空間的線性劃分。

  Softmax名字的來源是“hard max”,hard max是把最大值設為1,其他值都抹成0,非常強硬,例如向量[0.842, 0.042, 0.002, 0.114]T經過hard max操作就變成[1, 0, 0, 0]T

單個訓練樣本的損失函數L(y_hat, y) = -∑(yj*logy_hatj)。想要損失函數盡可能小,就要使正確類別的概率盡可能大。

整個訓練集的損失J(w[1], b[1], ...) = 1/m*∑(L(y_hat(i), y(i)))。

反向傳播的計算,dz[L] = y_hat - y。

  

4. 市面上的深度學習框架:

  用戶只需要定義網絡架構以及前向傳播,框架自己會搞定反向傳播。

  NG選框架的標準:1)容易編程;2)運行速度快,尤其是針對大數據;3)是否真的開放,不僅僅開源,而且要有很好的維護。

  TensorFlow:

import numpy as np
import tensorflow as tf

coefficients = np.array([[1.], [-10.], [25.]]) #傳給x的數據。

w = tf.Variable(0, dtype=tf.float32) #希望被優化的參數。
x = tf.placeholder(tf.float32, [3, 1]) #告訴TensorFlow稍後會為x提供數據,這種方式便於把訓練數據加入損失方程。
# cost = tf.add(tf.add(w**2, tf.multiply(-10., w)), 25) #這是第一個例子。
# cost = w**2 - 10*w + 25 # 由於TensorFlow重載了運算發,所以可以直接這樣寫。
cost = x[0][0]w**2 + x[1][0]*w+x[2][0] #第二個例子加入了樣本x。 
train = tf.train.GradientDescentOptimizer(0.01).minimize(cost) #使用梯度下降法最小化cost,這裏0.01是學習率。

init = tf.global_variables_initializer()
session = tf.Session() # with命令在python中更方便防止內循環出現錯誤,這一句也可以寫成 with tf.Session() as session:
session.run(init)
print(session.run(w)) #還沒有運行優化,w現在是0.

session.run(train, feed_dict={x:coefficients}) #運行一步梯度下降,把coefficients餵給x。如果在做mini-batch梯度下降,每次叠代可以餵不同的mini-batch
print(session.run(w)) #一步梯度下降之後,w現在是0.1

for i in range(1000):
    session.run(train, feed_dict={x:coefficients})
print(session.run(w)) # 運行1000次梯度下降之後,w現在是4.99999

  

deeplearning.ai 改善深層神經網絡 week3 聽課筆記