2017CS231n筆記_S7訓練神經網絡(下)

目錄

S7.1更好的優化Fancier optimization

S7.2集成模型

S7.3正則化(Regularization)

S7.4遷移學習(Transer Learning)


S7.1更好的優化Fancier optimization

訓練神經網絡的核心問題是對損失函數的優化問題。優化方法有:隨機梯度下降法(Stochastic Gradient Descent,SGD),帶動量的SGD,AdaGrad,RMSProp,Adam等等。下面是對這些方法的簡單描述。

  • SGD:這是一個簡單的優化方法。該方法先計算損失函數的值,再計算權重參數的梯度,再更新權重參數的值。不停地重複上述過程,直到損失函數值最小。但存在一些問題。首先:在某些函數上(某一維變化很小,某一維變化很大)運行SGD,會得到特有的之字形圖形。因爲梯度並不是與最小值成一條線。這樣會造成優化速度慢,特別在高維空間尤其普遍。有的損失函數有局部最小點或者鞍點(不是最大值,也不是極小值的臨界點),如下圖所示,直線代表損失函數。當遇到這個值,SGD得到的梯度爲0,訓練就會卡在這裏。在高維空間,鞍點更多。當接近鞍點時,優化都會非常緩慢,這是個大問題。除此之外,SGD會耗費很大的計算量。在遇到噪聲時,SGD會耗費更大的計算量才能得到極小值。

  • 帶動量的SGD:保持一個不隨時間變化的速度,並將梯度估計添加到這個速度上,然後在這個速度的方向上前進。v_w作爲梯度的運行均值。rho是摩擦參數,該參數會對速度進行衰減,通常設置爲0.9或0.99。該方法解決了SGD存在的問題。即使經過局部最小點或者鞍點,即使梯度爲0,也會有速度,使之跨過這些點。
  • AdaGrad:在優化時保持一個在訓練過程中的每一步的梯度的平方和的持續估計。如果有兩個座標軸,其中一個軸有很高的梯度,另一個軸有很小的梯度。隨着累加小梯度的平方,會在最後更新參數向量時除以一個很小的數字,從而加速了在小梯度維度上的學習速度。在另一個維度方向上,由於梯度變得特別大,會除以一個非常大的數,所以會降低在這個維度方向上的訓練進度。但存在一個問題,當訓練時間越來越長時,由於grad_squared值一直在隨時間單調遞增,步長會變得越來越小。當學習目標是一個凸函數的情況下,該特性很好,因爲到達極小點會逐漸慢下來最後到達收斂。但當不是凸函數時,訓練過程會被困在局部極小點。
  • RMSProp:AdaGrad的改進方法。仍然計算梯度的平方,但在訓練時,會讓平方梯度按照一定比率下降。decay_rate通常是0.9或者0.99。但該方法可能會造成訓練總是一直在變慢,這並不是我們想要的。
  • Adam:首先構造第一動量和第二動量。第一動量等於梯度的加權和,第二動量是梯度平方的動態近似值。然後構造第一動量和第二動量的無偏估計。最後使用無偏估計做每一步更新。Adam是一個很好的算法。並且對於不同的問題使用該算法都能得到非常不錯的結果。因此,基本上先考慮使用該方法。beta1設置爲0.9,beta2設置爲0.999,學習率爲1e-3或者5e-4。

上述部分優化算法的代碼如下:

''' SGD method '''
while True:
    weights_grad = compute_gradient(loss_fun, data, weights)
    weights -= learning_rate * weigthts_grad # perform parameter update


''' SGD with Momentum method '''
v_w = 0
while True:
    weights_grad = compute_gradient(loss_fun, data, weights)
    v_w = rho * v_w + weights_grads
    weights -= learning_rate * v_w 


''' AdaGrad method '''
grad_squared = 0
while True:
    weights_grad = compute_gradient(loss_fun, data, weights)
    grad_squared += weights_grad * weights_grad 
    weights -= learning_rate * weights_grad / (np.sqrt(grad_squared) + 1e-7)


''' RMSProp method '''
grad_squared = 0
while True:
    weights_grad = compute_gradient(loss_fun, data, weights)
    grad_squared = decay_rate * grad_squared + (1 - decay_rate) * weights_grad * weights_grad 
    weights -= learning_rate * weights_grad / (np.sqrt(grad_squared) + 1e-7)


''' Adam method '''
first_moment = 0
second_moment = 0
for t in range(num_iterations):
    weights_grad = compute_gradient(loss_fun, data, weights)
    first_moment = beta1 * first_moment + (1 - beta1) * weights_grad  # moment
    second_moment = beta2 * second_moment + (1 - beta2) * weights_grad * weights_grad # moment
    first_unbias = first_moment / (1 - beta1 ** t) # bias correction
    second_unbias = second_moment / (1 - beta2 ** t) # bias correction
    weights -= learning_rate * first_unbias / (np.sqrt(second_unbias) + 1e-7) # AdaGrad/RMSProp

上述優化方法都需要學習learning_rate這個超參數。不必在訓練中一直固定使用同一個值。有時候人們會把學習率沿着時間衰減,在訓練開始使用較大的一些學習率,然後在訓練過程中逐漸衰減地越來越小。一個衰減的策略是步長衰減。需要注意的是,在開始之前,還是要挑選一個不帶衰減的合適的學習率。在交叉驗證中調整學習率衰減。學習率衰減在帶動量SGD很常見,但在Adam的優化算法就很少用。在實際中,選擇Adam方法作爲優化方法。

優化方法力圖降低損失函數的值,使得模型在訓練集上的效果好,但更應該關注的是驗證集/測試集上的效果。往往會出現訓練集效果好而驗證集效果一般甚至不好,或者是訓練集的loss/acc與驗證集的loss/acc之間有很大的差距。這是過擬合現象,如下圖所示。出現這種情況是因爲模型在訓練時過度擬合了訓練集的特徵,從而造成模型的泛化性能差。過擬合常常是因爲數據較小。在小的數據集上很容易過擬合。爲了解決過擬合問題,提高在未訓練數據上的性能,可以使用這三種方法:集成模型,正則化和遷移學習。需要注意的是,我們不是爲了縮小訓練集和測試集結果之間的差距,而是關注在測試集上的性能,提高測試集上的性能。


S7.2集成模型

該方法首先訓練多個獨立的模型,然後在測試時對模型結果求平均。一般能夠提高2%的準確率。這個提升不是很大,但卻是固定的提升。在使用集成方法時,有如下幾個技巧:

  • 選擇從不同的隨機初始值上訓練多個不同的模型。這種集成技術是很常見的。
  • 有時候可以不用獨立地訓練不同的模型,可以在訓練時保留多個模型的快照,然後用這些快照做集成。該方式可以在一次訓練中集成多個模型。
  • 不使用實際的參數向量,而是保持參數向量的移動平均值,並在測試時使用它(polyak averaging)

S7.3正則化(Regularization)

常見正則化模式如下表所示,y爲模型,W爲模型,x是模型輸入,z是隨機數據。給模型添加隨機性是防止模型過度擬合訓練數據。在一定程度上擾亂它,防止它擬合數據。在測試時,要抵消所有隨機性,提高模型泛化能力。

階段 操作 函數
訓練 給網絡添加一些隨機性 y=f_{W}(x,z)
測試 將隨機性進行平均(有時近似) y=f(x)=E_{z}[f(x,z)]=\int p(z)f(x,z)dz

符合該模式的方法有:

  • 隨機失活(Dropout):每次在網絡正向傳播時,以p的概率,隨機地將每層的部分神經元的輸出置爲0。每次正向傳遞隨機置0的神經元都不完全相同。該方法在網絡中常用,一般在全連接層中使用,有時候也在卷積層使用。但在卷積層,是將某些通道的所有激活映射圖置0。被置零的項即爲z。在訓練時,梯度只在未被丟棄的節點上傳遞。在測試階段需要消除這種隨機性。有人認爲dropout避免了特徵之間的相互適應;也有人認爲dropout是在進行集成學習。下面是使用Dropout的3層網絡的實現代碼:
  • ''' Dropout implementation '''
    
    p=0.5 # probability of keeping a unit active.higher = less dropout 
    
    ''' Vanilla Dropout: Not recommended implementation '''
    def train_step(X):
        ''' X constains the data '''
        # forward pass for example 3-layer neural network
        H1 = np.maximum(0, np.dot([W1, X) + b1)
        U1 = np.random.rand(*H1.shape) < p # first dropout mask
        H1 *= U1 # drop!
        H2 = np.maximum(0, np.dot([W2, H1) + b2)
        U2 = np.random.rand(*H2.shape) < p # second dropout mask
        H2 *= U2 # drop!
        out = np.dot(W3, H2)+b3
        
        # backward pass: compute gradients...(not shown)
        # perform parameter update...(not shown)
    
    
    def predict(X):
        #ensembled forward pass
        H1 = np.maximum(0, np.dot([W1, X) + b1) * p # NOTE: scale the activations
        H2 = np.maximum(0, np.dot([W2, H1) + b2) * p # NOTE: scale the activations
        out = np.dot(W3, H2)+b3
    
    
    ''' Inverted dropout: more common '''
    def train_step(X):
        ''' X constains the data '''
        # forward pass for example 3-layer neural network
        H1 = np.maximum(0, np.dot([W1, X) + b1)
        U1 = (np.random.rand(*H1.shape) < p) / p  # first dropout mask. Notice /p!
        H1 *= U1 # drop!
        H2 = np.maximum(0, np.dot([W2, H1) + b2)
        U2 = (np.random.rand(*H2.shape) < p) / p # second dropout mask. Notice /p!
        H2 *= U2 # drop!
        out = np.dot(W3, H2)+b3
        
        # backward pass: compute gradients...(not shown)
        # perform parameter update...(not shown)
    
    
    def predict(X):
        #ensembled forward pass
        H1 = np.maximum(0, np.dot([W1, X) + b1) # no scaling necessary
        H2 = np.maximum(0, np.dot([W2, H1) + b2) 
        out = np.dot(W3, H2)+b3
  • 批歸一化(Batch Normalization,BN):BN在S6已經講過。它在訓練階段從隨機批數據中獲得統計值進行歸一化,測試階段使用固定的統計值來進行歸一化。BN在網絡中基本上是單獨使用。相比之下,Dropout能夠使用p調整正則化的力度,但在BN中並沒有這種控制機制。
  • 數據增強(Data Augmentation,DA):在訓練中以某種方式對輸入圖像進行隨機地轉換。使用轉換的圖像進行訓練。增強方式有:水平翻轉Horizontal Flips,隨機裁剪Random crops,scales,色彩抖動Color Jitter(不太常見)。下圖給出在訓練和測試時數據增強的具體操作。
  • DropConnect:在訓練時添加隨機噪聲,在測試時邊緣化噪聲。該方法在正向傳播時,隨機將權重矩陣的一些值置零。Dropout和DropConnect方法效果如下圖所示:
  • 部分最大池化Fractional Max Pooling:對區域進行隨機池化。該方法並不常用,但視頻老師會使用該方法,認爲該想法很好。
  • 隨機深度Stochastic Depth:有一個很深的網絡,在訓練時,隨機丟棄部分層。測試時,使用全部的網絡。該方法並不常用,但想法不錯。

在進行正則化時,一般選擇單獨使用BN方法。當僅使用BN不夠用時,就再添加了Dropout等方法,但不要盲目地去使用這些方法。當網絡過擬合時,再把它們加進去。


S7.4遷移學習(Transer Learning)

集成模型和正則化能夠幫助減小訓練誤差和測試誤差的間隙。然而有時候過擬合是由於數據不夠。使用小數據集時,大的和功能強的網絡更容易過擬合。此時,可以使用遷移學習方法來進行模型的訓練。遷移學習不需要大的數據集就能夠訓練卷積網絡。遷移學習方法首先找到預訓練好的網絡模型,然後凍結模型的前幾個層的權重,最後微調模型最後一層或者最後幾層的權重(一般這些層是全連接層)。該方法是爲了獲得預訓練模型的學習特徵能力,因此才凍結前幾個層的權重。如下圖所示。

對於所擁有數據集的大小,以及任務的相似度,遷移學習的訓練方式可分爲以下四種:

深度學習軟件包有提供一個模型庫,可以從中下載不同模型的預訓練版本。以下是相關網址:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章