周志華《機器學習》課後習題解答系列(六):Ch5.6 - BP演算法改進

Snoopy_Yuan發表於2017-04-27

相關答案和原始碼託管在我的Github上:PY131/Machine-Learning_ZhouZhihua.

5.6 BP演算法改進

這裡寫圖片描述

注:本題程式基於Python實現(這裡檢視完整程式碼和資料集)。

1. 方法設計

傳統的BP演算法改進主要有兩類:

  • 啟發式演算法:如附加動量法,自適應演算法。
  • 數值優化演算法:如共軛梯度法、牛頓迭代法、Levenberg-Marquardt法。

這裡我們首先採用附加動量實現基本的方法改進。然後分析演算法的不足,設計面向學習率的自適應機制來改進,實現基於動態自適應學習速率的BP演算法改進。

(1) 附加動量項

這是一種廣泛用於加速梯度下降法收斂的優化方法,其核心思想是:在梯度下降搜尋時,若當前梯度下降與之前梯度下降方向相同,則加速搜尋,反之則減速搜尋。

參考書p103(式5.11),標準BP演算法的引數更新項為:

∆ω(t) = ηg(t)

式中,∆ω(t)為第t次迭代的引數調整量,η為學習率,g(t)為第t次迭代所計算出的梯度。

在新增動量項之後,基於梯度下降的引數更新項為:

∆ω(t) = η[(1-μ)g(t)+μg(t-1)]

始終,μ為動量因子(取值0~1)。上式也等效於:

∆ω(t) = α∆ω(t-1)+ηg(t)

式中α被稱為遺忘因子,α∆ω(t-1)代表之前梯度下降的方向和大小資訊對當前梯度下降的調整作用。

(2) 自適應學習率

附加動量法面臨學習率的選取的困難,進而產生收斂速度與收斂性之間的矛盾。於是另考慮引入學習速率自適應設計,這裡給出一種自適應方案:

η(t) = σ(t)η(t-1)

上式中,σ(t)為第t次迭代時的自適應學習速率因子,下面是其一種計算例項:

σ(t) = 2^λ
其中λ為梯度方向:λ = sign(g(t)(t-1))

這樣,學習率的變化可反映前面附加動量項中所說的“核心思想”。

(3) 演算法總結

將上述兩種方法結合起來,形成動態自適應學習率的BP改進演算法

學習演算法原型可參照書p104演算法圖5.8,如下圖所示:

這裡寫圖片描述

從上圖及書中內容可知,輸出層與隱層的梯度項不同,故而對應不同的學習率 η_1 和 η_2,演算法的修改主要是第7行關於引數更新的內容:

將附加動量項與學習率自適應計算代入,得出公式(5.11-5.14)的調整如下圖所示:

這裡寫圖片描述

2. 對比實驗

點選檢視完整程式

這裡我們採用IRIS data set,實驗基於python-pybrain實現,步驟如下:

1. 搭建網路:搭建單隱層網路;
2. 訓練網路:分別採用學習率固定方案和動態調整方案來實現基於BP演算法的模型訓練;
3. 結果比較:比較訓練過程中的引數或誤差收斂情況以及最終的模型預測結果;

BP演算法實現程式碼可參考神經網路基礎 - Python程式設計實現標準BP演算法

(1) 資料預分析

iris(鳶尾花)資料集的一些基本資訊如下(參考iris.names):

屬性資訊,4-輸入(連續值),1-輸出(標稱值,3類):
    Attribute Information:
       1. sepal length in cm
       2. sepal width in cm
       3. petal length in cm
       4. petal width in cm
       5. class: 
          -- Iris Setosa
          -- Iris Versicolour
          -- Iris Virginica

樣本規模(150條,均勻分3類):
    Number of Instances: 150 (50 in each of three classes)

有無缺失值(無):
    Missing Attribute Values: None
...

經過相關預檢,可以看出該資料集規整度很高。

對其中的一些變數進行視覺化如下圖,可以看出其類別分散特性:

這裡寫圖片描述

為了方便進行數值計算,採用獨熱編碼(onehot encoding)對輸出的標稱資料進行數值化,這樣輸出由1維變為3維(每一個輸出對應一類)。在最終結果處理時,可採用勝者通吃(winner-take-all)的準則選擇數值最大的輸出對應的類作為分類結果。

(2) BP網路搭建

這裡搭建單隱層前饋模型,三層節點數從輸入到輸出依次為 <4, n_h, 3>,其中隱層節點數 n_h 根據實驗具體進展靈活取值。

下面是BP網路搭建樣例程式碼:

from BP_network import *
bpn1 = BP_network()  # initial a BP network class
bpn1.CreateNN(4, 5, 3, actfun = 'Sigmoid', learningrate = 0.02)  # build the network

(3) 固定學習率下的模型訓練

為了研究學習率對模型訓練的影響,這裡分別設定三個學習率:很大、很小和合適,分別得出對應訓練誤差曲線如下圖所示:

這裡寫圖片描述

分析上面的圖,可以看出,當學習率過大時,收斂過程出現了嚴重的振盪,當學習率過小時,收斂過慢,當採用合適的學習率時,收斂過程穩定。

(4) 自適應學習率下的模型訓練

根據上面關於學習率過大過小的對比實驗,這裡先為學習率的調整設定上下限。然後實現動態學習率下的標準BP演算法。

最後得出固定學習率與動態學習率下訓練誤差收斂曲線對比如下圖:

這裡寫圖片描述

可以看出,動態學習率的收斂速度較快,兩種機制在足夠多的迭代步驟後均實現了良好的精度。(另外我們看到,動態調整學習率下的收斂曲線最後階段發生了輕微振盪,這和學習率的調整幅度(底數及遺忘係數有關係。這兩個引數需要人工除錯)有關)。

下面是最終的測試集預測誤差結果:

固定學習率:test error rate: 0.013
動態學習率:test error rate: 0.027

3. 小結

採用動態調整學習率的確能夠大幅提升BP演算法的收斂速度,在資料量很大時愈發明顯。但同時也要注意學習率的取值區間和相關加速引數的設定,以期實現最優效能。

相關文章