1. 程式人生 > 其它 >bp神經網路 人工智慧

bp神經網路 人工智慧

一、用BP神經網路算y=x1^2+x2^2

import numpy as np
import scipy.special
import pylab
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def sigmoid(x):    # 定義網路啟用函式
    return 1/(1+np.exp(-x))
data_tr = pd.read_csv(r'D:\20信計大學學習\人工智慧\3.3 data_tr.txt')  # 訓練集樣本
data_te = pd.read_csv(r'D:\20信計大學學習\人工智慧\3.3 data_te.txt')  # 測試集樣本
n = len(data_tr)
yita = 0.85
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 = []
'''
模型訓練
'''
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)
plt.plot(Err)#訓練集上每一輪的平均誤差,對訓練集進行1000輪訓練
plt.show()
plt.close()
'''
將測試集樣本放入訓練好的網路中去
'''
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))   # 模型預測值
    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)#測試集上每一輪的誤差
plt.show()
err2=np.mean(error_te)

 

 

 

 

二、手工搭建神經網路

import numpy as np
import scipy.special
import pylab
import matplotlib.pyplot as plt
#%%
class NeuralNetwork():
    # 初始化神經網路
    def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
         # 設定輸入層節點,隱藏層節點和輸出層節點的數量和學習率
        self.inodes = inputnodes
        self.hnodes = hiddennodes
        self.onodes = outputnodes
        self.lr = learningrate                #設定神經網路中的學習率
        # 使用正態分佈,進行權重矩陣的初始化
        self.wih = np.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))  #(mu,sigma,矩陣)
        self.who = np.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))
        self.activation_function = lambda x: scipy.special.expit(x)       #啟用函式設為Sigmod()函式
        pass
    # 定義訓練神經網路
    print("************Train start******************")
    def train(self,input_list,target_list):
        # 將輸入、輸出列表轉換為二維陣列
        inputs = np.array(input_list, ndmin=2).T    #T:轉置
        targets = np.array(target_list,ndmin= 2).T
        hidden_inputs = np.dot(self.wih, inputs)                           #計算到隱藏層的訊號,dot()返回的是兩個陣列的點積
        hidden_outputs = self.activation_function(hidden_inputs)           #計算隱藏層輸出的訊號
        final_inputs = np.dot(self.who, hidden_outputs)                    #計算到輸出層的訊號
        final_outputs = self.activation_function(final_inputs)

        output_errors = targets - final_outputs                           #計算輸出值與標籤值的差值
        #print("*****************************")
        #print("output_errors:",output_errors)
        hidden_errors = np.dot(self.who.T,output_errors)


        #隱藏層和輸出層權重更新
        self.who += self.lr * np.dot((output_errors*final_outputs*(1.0-final_outputs)),
                                       np.transpose(hidden_outputs))#transpose()轉置
        #輸入層和隱藏層權重更新
        self.wih += self.lr * np.dot((hidden_errors*hidden_outputs*(1.0-hidden_outputs)),
                                       np.transpose(inputs))#轉置
        pass

        #查詢神經網路
    def query(self, input_list):   # 轉換輸入列表到二維數
        inputs = np.array(input_list, ndmin=2).T                     #計算到隱藏層的訊號
        hidden_inputs = np.dot(self.wih, inputs)                     #計算隱藏層輸出的訊號
        hidden_outputs = self.activation_function(hidden_inputs)        #計算到輸出層的訊號
        final_inputs = np.dot(self.who, hidden_outputs)
        final_outputs = self.activation_function(final_inputs)
        return final_outputs
#%%
input_nodes = 784              #輸入層神經元個數
hidden_nodes = 100             #隱藏層神經元個數
output_nodes = 10              #輸出層神經元個數
learning_rate = 0.3            #學習率為0.3
# 建立神經網路
n = NeuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
#%%
#讀取訓練資料集 轉化為列表
training_data_file = open(r"D:\20信計大學學習\人工智慧\mnist_train.csv",'r')
training_data_list = training_data_file.readlines()     #方法用於讀取所有行,並返回列表
#print("training_data_list:",training_data_list)
training_data_file.close()
#%%
#訓練次數
i = 2
for e in range(i):
    #訓練神經網路
    for record in training_data_list:
        all_values = record.split(',')                   #根據逗號,將文字資料進行拆分
        #將文字字串轉化為實數,並建立這些數字的陣列。
        inputs = (np.asfarray(all_values[1:])/255.0 * 0.99) + 0.01
        #建立用零填充的陣列,陣列的長度為output_nodes,加0.01解決了0輸入造成的問題
        targets = np.zeros(output_nodes) + 0.01     #10個元素都為0.01的陣列
        #使用目標標籤,將正確元素設定為0.99
        targets[int(all_values[0])] = 0.99#all_values[0]=='8'
        n.train(inputs,targets)
        pass
pass
#%%
test_data_file = open(r"D:\20信計大學學習\人工智慧\mnist_test.csv",'r')
test_data_list = test_data_file.readlines()
test_data_file.close()

all_values = test_data_list[2].split(',')       #第3條資料,首元素為1
# print(all_values)
# print(len(all_values))
# print(all_values[0])  #輸出目標值
#%%
score = []
print("***************Test start!**********************")
for record in test_data_list:
    #用逗號分割將資料進行拆分
    all_values = record.split(',')
    #正確的答案是第一個值
    correct_values = int(all_values[0])
    # print(correct_values,"是正確的期望值")
    #做輸入
    inputs = (np.asfarray(all_values[1:])/255.0 * 0.99) + 0.01
    #測試網路 作輸入
    outputs= n.query(inputs)#10行一列的矩陣
    #找出輸出的最大值的索引
    label = np.argmax(outputs)
    # print(label,"是網路的輸出值\n")
    #如果期望值和網路的輸出值正確 則往score 數組裡面加1 否則新增0
    if(label == correct_values):
        score.append(1)
    else:
        score.append(0)
    pass
pass
print(outputs)
#%%
# print(score)
score_array = np.asfarray(score)
#%%
print("正確率是:",(score_array.sum()/score_array.size)*100,'%')