BP神經網路及其C語言實現
BP神經網路是目前為止最為成功的神經網路模型之一,本文首先介紹BP神經網路的基本概念和理論推導,最後給出具有訓練、模擬及實際擬合功能的C語言實現。
本文的理論部分全部來源於周志華《機器學習》,P97-P106,如需詳細了解,請查閱本書。
1. 基本概念
- 神經網路:由簡單的神經元組成的廣泛互聯的網路,其具有適應性,可以模擬生物神經系統對真實世界所做出的交互反應。
- 神經元模型:神經元模型是神經網路中的基本模型,單個神經元可以接收網路中其他神經元的信息,如果接收的信息超過閾值,則此神經元被激活,接著向其他神經元發送信息。
- M-P神經元模型:M-P神經元模型是典型的神經元模型,其基本結構如圖1所示。
圖1 M-P神經元模型
在這個模型中,神經元接收來自n個其他神經元傳遞過來的輸入信號,這些輸入信號通過帶權重的連接進行傳遞,神經元接收到的總輸入值將與神經元的閾值進行比較,然後通過「激活函數」處理產生神經元的輸出。
- Sigmoid函數:sigmoid是最常用的激活函數,如圖2所示。
圖2 sigmoid函數
其函數表達式為
- 多層前饋神經網路(multi-layer feedforward neural networks):基本結構如圖3所示,此種結構的聖經網路,每層神經元與下一層神經元全連接,神經元之間不存在同層連接,也不存在跨層連接。其網路層次包含3層,其中輸入層神經元用於接收外界輸入,隱層與輸出層神經元對信號進行加工,最終結果由輸出層神經元輸出。
圖3 多層前饋神經網路
- 神經網路的學習過程:根據訓練數據來調整神經元之間的連接權以及每個功能神經元的閾值,換言之,神經網路學習到的東西蘊含在連接權與閾值中。
2. BP神經網路理論推導
2.1 BP神經網路結構
BP神經網路是目前為止最為成功的神經網路演算法之一,其學習方式採用標準梯度下降的誤差逆傳播(error BackPropagation)的方式,以下介紹的基本BP神經網路為3層前饋神經網路。
圖4 BP神經網路模型
對於BP神經網路,我們需要使用訓練數據集對其進行參數訓練,然後使用測試機檢驗訓練結果,如果訓練效果達標,則可使用訓練出的數據應用於實際使用場景,對於神經網路其訓練過程最為主要,以下我們主要闡述其訓練方法。
對於圖4中的神經網路模型,我們做如下定義:
- 給定訓練集,即輸入數據維度為,輸出數據維度為。
- 圖4中,假設神經網路是輸入節點為個,輸出節點為個,隱層有個的多層前向反饋神經網路,輸出層第個神經元閾值為,第個隱層神經元閾值為.輸入層第個節點與隱層第個節點之間的權重為,隱層第個節點與輸出層第個節點的權重為.
根據以上假設可以有如下公式:
- 激活函數為
- 隱層第個神經元接收到的輸入為
- 隱層第個神經元的輸出為
- 輸出層第個神經元接收到的輸入為
- 輸出層第個神經元的輸出為
由以上5個公式可知,神經網路之中只要以下個參數確定,則就可以由輸入計算出輸出,這些參數分別為
- 輸入層到隱層權重個,隱層到輸出層權重個
- 隱層神經元閾值個,輸出層神經元閾值個
那麼我們如何得到這麼多個參數呢?BP神經網路演算法使用誤差逆向傳播進行訓練。
2.2 BP神經網路的訓練
神經網路的初始參數為內隨機數,假設某次訓練過程中神經網路的輸入的某個訓練數據為,經過神經網路的輸出為,其中
6. 對於訓練數據集中的單個數據其誤差
我們採用梯度下降法根據誤差對神經網路中的參數進行反饋學習,神經網路中參數更新的公式為,
此處以隱層到輸出層權重為例對神經網路參數更新公式進行推導:
我們以誤差的負梯度方向對參數進行更新,為學習率,有如下公式:
7. 參數更新公式
8. 參數調整力度 9. 注意到,先影響到第個輸出神經元的輸入值,再影響到其輸出值, 根據偏導數的鏈式法則有 10. 根據的定義顯然有 11. 由於sigmoid函數的導數具有特殊性質12. 則
按照以上推導方法有
13.
14.
15. 同理,16. 17. 在15.16式中,而影響個,又影響,所以有
注意在公式13.14.15.16中控制著每一輪迭代中的更新步長,若太大,則容易振蕩,太小則學習過程收斂很慢,為了細微調節,13.14中的學習率可以和15.16中的不一樣。
18. 使用訓練集上的累積誤差衡量訓練質量
2.3 BP神經網路的訓練過程
- 在內隨機初始化神經網路中的連接權重和閾值;
- repeat
- for 遍歷訓練集中的每一個樣本
- 根據當前參數按照公式1.2.3.4.5計算樣本的與.
- 根據公式12.17計算與.
- 根據公式13.14.15.16更新.
- end for
- until (迭代若干次或者累積誤差小於特定值)
- 得到BP神經網路的參數
3. C語言實現
C語言的實現就很簡單了,BP神經網路分為兩個部分:
1. 訓練模塊,包含訓練以及驗證過程,注意此神經網路的輸入輸出都需要預先進行歸一化處理。
/**n * To fetch test_set.n * The length of in is IN_N, the length of out is OUT_N.n */ntypedef bool (*test_set_get_t)(double *in, double *out);nn/**n * Reset test_set fetch process.n */ntypedef bool (*test_set_init_t)(void);nn/**n * Init bpnn module.n */nvoid bpnn_init(void);nn/**n * Train bpnn module and produce parameter file.n * @param f_get To get test data in stream.n */nvoid bpnn_train(test_set_get_t f_get, test_set_init_t f_init);nn/**n * Test result of bpnn train parameter.n * @param f_getn */nvoid bpnn_sim(test_set_get_t f_get);n
2. 擬合模塊;
#define T bpnn_tntypedef struct T *T;nn/**n * Init bpnn module.n * @returnn */nT bpnn_fit_new(void);nn/**n * Using bpnn fit in to out.n * @param bpnnn * @param inn * @param outn */nvoid bpnn_fit(T bpnn, double *in, double *out);nn/**n * Uninit bpnn.n * @param bpnnn */nvoid bpnn_fit_free(T *bpnn);n
詳細的實現請訪問github:ThreeClassMrWang/c-bpnn
實現里教會了神經網路進行的計算,詳細請見github,謝謝!
推薦閱讀:
※深度學習(Deep Learning)基礎概念2:深度學習測試題及詳解1
※KL散度不對稱。如果分布P和Q,KL(P||Q)很大而KL(Q||P)很小表示什麼現象?
※刷頁還是刷專題:ACM競賽做題之道