Python: 搭建BP神經網絡


 

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

 


 

路漫漫其修遠兮,吾將上下而求索 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM