神經網絡抑制過擬合的方法

過擬合指的是隻能擬合訓練數據,但不能很好地擬合不包含訓練數據的其他數據。神經網絡要求模型能夠具有較高的泛化能力,也就是對不包含訓練數據的未觀測數據也能進行正確識別。所以在訓練表現力強的模型同時,抑制過擬合的技巧也很重要。

防止過擬合的方法:(1)人爲增加訓練數據集;(2)正則化(權值衰減);(3)Dropout

1、人爲增加訓練數據集

發生過擬合的原因主要有:

  • 模型擁有大量參數,表現力強;
  • 訓練數據少。

所以通過增加訓練數據可以抑制過擬合,提高模型的泛化能力。例如增加圖像數據集可以對原始圖像進行旋轉、鏡像。

2、正則化(權值衰減)

    權值衰減是一直以來經常被使用的一種抑制過擬合的方法。該方法通過在學習過程中對大的權重進行懲罰,來抑制過擬合。因爲很多過擬合原本就是因爲權重參數取值過大才發生的。

    神經網絡的習目的是減小損失函數的值。這時,例如爲損失函數加上權值的平方範數(L2範數)。這樣就可以抑制權重變大。用符號表示的話,如果將權重記爲W,L2範數的權值衰減就是\frac{1}{2}\lambda W^{2},然後將\frac{1}{2}\lambda W^{2}加到損失函數上。這裏,\lambda是控制正則化強度的超參數。\lambda設置的越大,對大的權重施加懲罰就越重。此外,\frac{1}{2}\lambda W^{2}開頭的\frac{1}{2}是用於將\frac{1}{2}\lambda W^{2}的求導結果變成\lambda W的調整用常量。

    對於所有權重,權值衰減方法都會爲損失函數加上\frac{1}{2}\lambda W^{2}。因此在求權重梯度的計算中,要爲之前的誤差反向傳播算法的結果加上正則化項的導數\lambda W。正則化項可以使用L1,L2,L∞,這裏使用比較常用的L2。

所以用python搭建神經網絡時,損失函數和計算梯度的代碼要改爲:

    def loss(self, x, t):
        # 前向傳播
        y = self.predict(x)

        weight_decay = 0
        # 計算所有權重的L2範數
        for idx in range(1, self.hidden_layer_num + 2):
            W = self.params['W' + str(idx)]
            weight_decay += 0.5 * self.weight_decay_lambda * np.sum(W ** 2)

        return self.last_layer.forward(y, t) + weight_decay


    def gradient(self, x, t):
        # 計算損失函數
        self.loss(x, t)

        # backward
        dout = 1
        dout = self.last_layer.backward(dout)

        layers = list(self.layers.values())
        layers.reverse()
        for layer in layers:
            dout = layer.backward(dout)

        # 梯度
        grads = {}
        for idx in range(1, self.hidden_layer_num+2):
            grads['W' + str(idx)] = self.layers['Affine' + str(idx)].dW + self.weight_decay_lambda * self.layers['Affine' + str(idx)].W
            grads['b' + str(idx)] = self.layers['Affine' + str(idx)].db

        return grads

 

3、Dropout

    上面介紹的損失函數加上權重的L2範數的權值衰減方法,在某種程度上可以抑制過擬合。但是,如果網絡模型變得複雜,只有權值衰減就顯得力不從心了。在這種情況下,往往使用Dropout方法。

    Dropout是一種在學習過程中隨機刪除神經元的方法。訓練時,隨機選出隱藏層的神經元,然後將其刪除。被刪除的神經元不再進行信號傳遞。如下圖所示。訓練時,每傳遞一次數據,就會隨機選擇要刪除的神經元。然後,測試時,雖然會傳遞所有的神經元信號,但是對於各個神經元的輸出,要乘上訓練時的刪除比例後再輸出。

               

下面來實現Dropout,這裏注重理解實現的方法比較簡單:

class Dropout:
    def __init__(self, dropout_ratio=0.5):
        self.dropout_ratio = dropout_ratio
        self.mask = None

    def forward(self, x, train_flg=True):
        if train_flg:
            self.mask = np.random.rand(*x.shape) > self.dropout_ratio
            return x * self.mask

    def backward(self, dout):
        return dout * self.mask

說明:每次正向傳播時,self.mask中都會以False的形式保存要刪除的神經元。self.mask會隨機生成和x形狀相同的數組,並將值比dropout_ratio大的元素設爲True。傳播行爲和RuLU相同。

在搭建神經網絡時可以這樣使用Dropout:

def __init__(self, input_size, hidden_size_list, output_size,
                 activation='relu', weight_init_std='relu', weight_decay_lambda=0, 
                 use_dropout = False, dropout_ration = 0.5):
        self.input_size = input_size
        self.output_size = output_size
        self.hidden_size_list = hidden_size_list
        self.hidden_layer_num = len(hidden_size_list)
        self.use_dropout = use_dropout
        self.weight_decay_lambda = weight_decay_lambda
        self.params = {}

        # 權重初始化方法
        self.__init_weight(weight_init_std)

        # 每層網絡生成
        activation_layer = {'sigmoid': Sigmoid, 'relu': Relu}
        self.layers = OrderedDict()
        for idx in range(1, self.hidden_layer_num+1):
            self.layers['Affine' + str(idx)] = Affine(self.params['W' + str(idx)],
                                                      self.params['b' + str(idx)])

            if self.use_dropout:
                self.layers['Dropout' + str(idx)] = Dropout(dropout_ration)

        idx = self.hidden_layer_num + 1
        self.layers['Affine' + str(idx)] = Affine(self.params['W' + str(idx)], self.params['b' + str(idx)])

        self.last_layer = SoftmaxWithLoss()

也就是一個全連接層後面使用Dropout。

拓展:

    機器學習中經常使用集成學習。所謂集成學習,就是讓多個模型單獨進行學習,推理時再取多個模型的輸出的平均值。用神經網絡的語境來說,比如,準備5個結構相同的網絡,分別進行學習,測試時,以這5個網絡的輸出的平均值作爲答案。通過實驗可以發現,使用集成學習,神經網絡的識別精度可以提高好幾個百分點。

    這個集成學習與Dropout有密切的關係。這是因爲可以將Dropout理解爲,通過在學習過程中隨機刪除神經元,從而每一次都讓不同的模型進行學習。並且,推理時,通過對神經元的輸出乘以刪除比例(比如0.5),可以取模型的平均值。也就是說,可以理解成,Dropout將集成學習的效果通過一個網絡實現了。

 

 

 

 

 

 

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