BP(back propagation)神經網絡是1986年由Rumelhart和McClelland為首的科學家提出的概念,是一種按照誤差逆向傳播算法訓練的多層前饋神經網絡,是目前應用最廣泛的神經網絡。
在一般的BP神經網絡中,單個樣本有m個輸入和n個輸出,在輸入層和輸出層之間還有若干個隱藏層h,實際上 1989年時就已經有人證明了一個萬能逼近定理 :
在任何閉區間的連續函數都可以用一個隱藏層的BP神經網絡進行任意精度的逼近。
所以說一個三層的神經網絡就可以實現一個任意從m維到n維的一個映射,這三層分別是 輸入層、隱藏層、輸出層 。
一般來說,在BP神經網絡中,輸入層和輸出層的節點數目都是固定的,關鍵的就是在於隱藏層數目的選擇,隱藏層數目的選擇決定了神經網絡工作的效果。
BP神經網絡的工作原理分為兩個過程 :
1、工作信號正向傳遞子過程
2、 誤差信號逆向傳遞過程
實驗目的:搭建BP神經網絡(包括模型層的定義和正向反向傳播過程),訓練出表格中"?"處的數據。
導入數據:
data_tr = pd.read_csv(r'3.3 data_te1.txt') # 訓練集樣本 data_te = pd.read_csv(r'3.3 data_tr1.txt') # 測試集樣本 n = len(data_tr) yita = 0.85
其余代碼見下面”完整代碼“部分。
運行結果如下:
圖1為對訓練集進行1000輪訓練,曲線代表訓練集上每一輪的平均誤差。
圖1
預測結果:
即9、10處的y值各為
0.18291413127495168 0.18291413127495168
圖2為對測試集進行訓練,曲線代表測試集上每一輪的誤差。
圖2
以上是小規模樣本,下面導入大規模樣本數據並用圖形展示BP神經網絡訓練過程和誤差。完整代碼如下:
1.導入庫
import pandas as pd import numpy as np import matplotlib.pyplot as plt import matplotlib
2.定義激活函數sigmoid
def sigmoid(x): # 定義網絡激活函數 return 1/(1+np.exp(-x))
3.導入訓練集和測試集樣本
data_tr = pd.read_csv(r'3.3 data_te.txt') # 訓練集樣本 data_te = pd.read_csv(r'3.3 data_tr.txt') # 測試集樣本 n = len(data_tr) yita = 0.85
4.設置神經網絡結構及參數
out_in = np.array([0, 0, 0, 0, -1]) # 輸出層的輸入,即隱層的輸出 w_mid = np.zeros([3,4]) # 隱層神經元的權值&閾值 w_out = np.zeros([5]) # 輸出層神經元的權值&閾值 delta_w_out = np.zeros([5]) # 輸出層權值&閾值的修正量 delta_w_mid = np.zeros([3,4]) # 中間層權值&閾值的修正量 Err = []
5.訓練模型
''' BP神經網絡模型訓練 ''' for j in range(1000): error = [] for it in range(n): #訓練集有n條記錄 net_in = np.array([data_tr.iloc[it, 0], data_tr.iloc[it, 1], -1]) # 網絡輸入 real = data_tr.iloc[it, 2] #第it行第2列的值,也就是此記錄的真實值 for i in range(4): out_in[i] = sigmoid(sum(net_in * w_mid[:, i])) # 從輸入到隱層的傳輸過程 res = sigmoid(sum(out_in * w_out)) # 預測值 error.append(abs(real-res))#第一條記錄的誤差 # print(it, '個樣本的模型輸出:', res, 'real:', real) delta_w_out = yita*res*(1-res)*(real-res)*out_in # 輸出層權值的修正量 delta_w_out[4] = -yita*res*(1-res)*(real-res) # 輸出層閾值的修正量 w_out = w_out + delta_w_out # 更新,加上修正量 for i in range(4): delta_w_mid[:, i] = yita*out_in[i]*(1-out_in[i])*w_out[i]*res*(1-res)*(real-res)*net_in # 中間層神經元的權值修正量 delta_w_mid[2, i] = -yita*out_in[i]*(1-out_in[i])*w_out[i]*res*(1-res)*(real-res) # 中間層神經元的閾值修正量,第2行是閾值 w_mid = w_mid + delta_w_mid # 更新,加上修正量 # error=[error1,error2,...,error500] np.mean(error):500條記錄的平均誤差 Err.append(np.mean(error)) print(w_mid,w_out) #訓練集上每一輪的平均誤差,對訓練集進行1000輪訓練 plt.plot(Err, linewidth = '1', label = "Ren35_test", color='forestgreen', linestyle=':', marker='|') plt.legend(loc='upper left') plt.show() plt.close()
圖3
6.將測試集樣本放入訓練好的BP神經網絡模型中去
''' 將測試集樣本放入訓練好的BP神經網絡模型中去 ''' error_te = [] score=[] m=len(data_te) for it in range(m): #測試集有m條記錄 net_in = np.array([data_te.iloc[it, 0], data_te.iloc[it, 1], -1]) # 網絡輸入 real = data_te.iloc[it, 2] for i in range(4): out_in[i] = sigmoid(sum(net_in * w_mid[:, i])) # 從輸入到隱層的傳輸過程 res = sigmoid(sum(out_in * w_out)) # 模型預測值 print(res) error_te.append(abs(real-res)) if(abs(real-res)<0.1718): score.append(1) else: score.append(0) score_array = np.asfarray(score) print("測試集進行1輪測試的正確率是:",(score_array.sum()/score_array.size)*100,'%') #測試集上每一輪的誤差 plt.plot(error_te, linewidth = '1', label = "Ren35_test", color='forestgreen', linestyle=':', marker='|') plt.legend(loc='upper left') plt.show() err2=np.mean(error_te) print("測試集進行1輪測試的平均誤差:",err2)
輸出預測值:
【P.S.預測值過多,僅截此圖示意】
圖4
路漫漫其修遠兮,吾將上下而求索