詳解 BP 神經網路基本原理及 C 語言實現
BP(Back Propagation)即反向傳播,指的是一種按照誤差反向傳播來訓練神經網路的方法。而 BP 神經網路即為一種按照誤差反向傳播的方法訓練的神經網路,是一種應用十分廣泛的神經網路。
BP 神經網路主要可以解決以下兩種問題:
分類問題:用給定的輸入向量和標籤訓練網路,實現網路對輸入向量的合理分類。
函數逼近問題:用給定的輸入向量和輸出向量訓練網路,實現對函數的逼近。
本文主要介紹 BP 神經網路的基本結構,而後簡單介紹用 C 語言實現神經網路必需要用到的語法知識(老手請放心跳過),最後一步一步從構建單個神經元開始到完成整個神經網路的構建和訓練。
VS2013 安裝及新建工程
安裝過程
由於本文主要還是面向初學者,考慮到有些小白朋友的需求,所以還是簡單介紹下軟體安裝和使用,此部分可選擇性跳過。
下載完成後如下圖。
解壓後,如下圖所示。
雙擊運行如下的 exe 文件。
出現下圖所示的界面,在此可以修改安裝位置,建議設置成全英文路徑。
之後按照默認設置一路下一步到安裝完成即可。但安裝完成後默認不會生成桌面快捷方式,需要從開始菜單欄運行,也可以從開始菜單欄創建桌面快捷方式。
新建工程
首先運行VS2013,得到如下界面。
點擊左上角的 「文件" -> "新建」 -> "項目"。在下圖所示的界面上可以修改保存名稱和路徑。
選擇 「visual c++」 -> 「Win32 控制台應用程序"後點擊「確定」,出現如下界面。
單擊下一步,如下圖所示。
勾選「空項目」後單擊「完成」後,出現如下界面,此處重點是觀察右側的工程結構。
我們在右邊的「解決方案管理器」選擇「源文件」,右鍵選擇「添加」 -> 「新建項」,如下圖所示。
在出現的新界面的下方重命名為 main.cpp,如下圖所示。
按照相同的方法在源文件中再添加一個 neuralnetwork.cpp,在頭文件中添加 neuralnetwork.h。
最後完成的工程結構非常簡單,如下圖所示。
我們寫點簡單的代碼,測試下整個工程能否編譯通過,三部分的代碼如下。
main.cpp
neural_network.cpp:
neural_network.h:
這是個簡單的測試程序,如果一切正常就會輸出 HelloWorld,至此軟體安裝和工程新建就結束了。
BP 神經網路原理
人工神經元模型
人工神經元模型如下圖所示。
一般神經元模型包含這樣幾個要素:
輸入:X1、X2、X3......Xn(可以有多個)。
權重:W1、W2、W3......Wn。
偏置:Bias。
激活函數:f(x)。
輸出:y(僅一個)。
這裡需要重點說明的是激活函數。如果不加入激活函數,只是簡單的對輸入進行加權求和,那麼整個模型就是個線性模型,而線性模型的表示能力是非常有限的,因此通過加入激活函數的方式給模型引入非線性因素,以提高模型的表示能力,所以一般情況下會採用非線性函數作為激活函數。常見的激活函數有 Sigmoid、Tanh、Step、ReLU、Softmax 等。
本文只用 Sigmoid 函數,下圖給出了 Sigmoid 函數圖像。
現在神經元模型的結構比較清楚了,下面看看如何計算模型的輸出。通過給定的權重對輸入進行加權求和後(默認加上偏置 Bias),再將得到的和作為參數輸入一個激活函數,得到的激活函數的輸出值即為神經元的輸出。
對應的數學公式如下:
下面舉個例子來說明一下計算輸出的過程。
設 X1=1,X2=0,X3=0,W1=0.1,W2=0.2,W3=0.3,Bias=0.1,f(x)=x。
由上面給出的計算公式可得:
z = X1W1+X2W2+X3*W3+Bias = 0.1+0+0+0.1 = 0.2
y = f(z) = z = 0.2
學過初高中生物的朋友應該可以看出,人工神經元模型的 X1、X2、X3 作為輸入,和生物神經元的樹突是非常相似的。而模型的 y 作為唯一的輸出,和生物神經元的軸突也是非常相似。仔細觀察對比還能發現更多的相似之處,此處不做更多討論。
下面簡單介紹一下人工神經元模型的訓練方法。為了減少不必要的演示計算步驟,這裡我們用只有兩個輸入一個輸出(只有 X1、X2)的模型進行演示,方法如下。
先給模型一個任意權值和偏置,設 W1=0,W2=0,Bias=0,再設激活函數為:
再給定兩組訓練用的數據,模擬一個簡單的二分類問題:
第一組:data1=1,data2=1,期望輸出aim_output1=1
第二組:data3=-1,data4=-1,期望輸出aim_output2=0
然後我們先把第一組 data 代入模型根據前面所說的計算神經元輸出的方法進行計算,得到實際輸出real_output1=f(data1W1+data2W2+Bias)=f(0)=0。
實際輸出realoutput1和期望輸出aimoutput1之間就存在一個差值err1=aimoutput1-realoutput1=1。
根據這個差值,可以通過如下公式來修正我們隨機給定的權值和偏置:
W1=W1+etaerr1data1
W2=W2+etaerr1data2
Bias=Bias+eta*err1
這裡的 eta 表示學習率,一般取 0~1 之間的值。eta 值越大學習速率也越快,也就是每一次訓練,權值和偏置的變動越大,但也並不是越大越好。如果 eta 過大容易產生震蕩而不能穩定到目標值,若 eta 值越小,則效果相反。這裡我們簡單的取 eta=1,帶入計算式可得經過一次修正過後的權值和偏置:
W1=1,W2=1,Bias=1
注意,這裡第一次訓練還沒結束,還要繼續代入第二組的 data,並且要記住 W1、W2、Bias 已經改變,通過相同的方法計算輸出:
real_output2=f(data3W1+data4W2+Bias)=f(-1-1+1)=0
計算差值為:
err2=aimoutput2-realoutput2=0
由於實際輸出和期望輸出沒有誤差,所以不用修正權值和偏置(也可以看做變化量為0)。
這樣第一次訓練結束,繼續下一次訓練。
還是先把第一組 data 代入模型進行計算得到實際輸出:
real_output1=f(data1W1+data2W2+Bias)=f(11+11+1)=1
計算差值:
err1=aimoutput1-realoutput1=0
由於實際輸出和期望輸出沒有誤差,所以不修正權值和偏置。
再把第二組 data 代入模型得輸出:
real_output2=f(data3W1+data4W2+Bias)=f(-1-1+1)=0
計算差值:
err2=aimoutput2-realoutput2=0
由於實際輸出和期望輸出沒有誤差,所以不修正權值和偏置。
至此訓練完成,這個模型已經能對輸入的兩組數據準確分類,現在給出解決這個二分類問題的 C 語言代碼。
運行結果如下圖所示。
和我們的計算結果一致,也是第二次訓練得出正確的分類。
※演算法入門,其實可以像讀小說一樣有趣
※Hybris平台Web架構模式演變:前後端分離
TAG:CSDN技術頭條 |