深度学习(神经网络) —— BP神经网络原理推导及python实现
深度學(xué)習(xí)(神經(jīng)網(wǎng)絡(luò)) —— BP神經(jīng)網(wǎng)絡(luò)原理推導(dǎo)及python實現(xiàn)
- 摘要
- (一)BP神經(jīng)網(wǎng)絡(luò)簡介
- 1、神經(jīng)網(wǎng)絡(luò)權(quán)值調(diào)整的一般形式為:
- 2、BP神經(jīng)網(wǎng)絡(luò)中關(guān)于學(xué)習(xí)信號的求取方法:
- (二)BP神經(jīng)網(wǎng)絡(luò)原理推導(dǎo)
- 1、變量說明
- 2、BP算法推導(dǎo)
- (三)BP神經(jīng)網(wǎng)絡(luò)python實現(xiàn)
- 1、模型所需傳參介紹
- 2、模型具有的主要方法和屬性
- 3、python代碼
- 4、代碼運行結(jié)果
摘要
本文首先介紹了BP神經(jīng)網(wǎng)絡(luò)求取學(xué)習(xí)信號的方法,其次對BP神經(jīng)網(wǎng)絡(luò)在原理上進(jìn)行了推導(dǎo),最后在python上進(jìn)行編程實現(xiàn),并將其封裝,方便讀者直接調(diào)用。
(一)BP神經(jīng)網(wǎng)絡(luò)簡介
BP神經(jīng)網(wǎng)絡(luò)是整個神經(jīng)網(wǎng)絡(luò)體系中的精華,與一般神經(jīng)網(wǎng)絡(luò)相比,它調(diào)整權(quán)值方式為從最后一層開始逐層調(diào)整,通過多次迭代,使得代價函數(shù)降低至可接受范圍。因此,這就是BP神經(jīng)網(wǎng)絡(luò)的來源(Back Propagation,誤差反向傳播)。
1、神經(jīng)網(wǎng)絡(luò)權(quán)值調(diào)整的一般形式為:
(1)其中 η為學(xué)習(xí)率,可以理解為每次權(quán)值調(diào)整的步長
(2)其中δ為學(xué)習(xí)信號,可以理解為每次權(quán)值調(diào)整的方向,實際上為一個梯度向量。
由上式也可以發(fā)現(xiàn)不同神經(jīng)網(wǎng)絡(luò)的差異主要體現(xiàn)在學(xué)習(xí)信號上的差異。
2、BP神經(jīng)網(wǎng)絡(luò)中關(guān)于學(xué)習(xí)信號的求取方法:
假設(shè)一個神經(jīng)網(wǎng)絡(luò)共n層
上式為求取最后一層,即輸出層的學(xué)習(xí)信號,其中t為期望輸出,y為模型輸出,f(x)為激活函數(shù)(對激活函數(shù)不了解的可自行先百度或查看我的其他文章)。
上式為求取除最后一層以外其他層的學(xué)習(xí)信號,i+1表示第i層后面的一層,可以發(fā)現(xiàn)求取第i層學(xué)習(xí)信號時,需要先求取出第i+1層的學(xué)習(xí)信號,這也是誤差反向傳播的來源。
具體BP神經(jīng)網(wǎng)絡(luò)的學(xué)習(xí)信號推導(dǎo)過程見以下的原理推導(dǎo),推導(dǎo)過程有點小復(fù)雜,即使不看,根據(jù)以上的結(jié)論也可以編寫自己的BP神經(jīng)網(wǎng)絡(luò)程序了。
(二)BP神經(jīng)網(wǎng)絡(luò)原理推導(dǎo)
1、變量說明
(1)以三層感知器構(gòu)成的神經(jīng)網(wǎng)絡(luò)為例(實際為兩層神經(jīng)網(wǎng)絡(luò))。
(2)定義各層的輸入和輸出:
輸入向量
隱含層輸出向量
輸出層輸出向量
期望輸出向量
(3)定義權(quán)值矩陣:
輸入層到隱含層的權(quán)值矩陣
隱含層到輸出層的權(quán)值矩陣
(4)設(shè)定激活函數(shù)
2、BP算法推導(dǎo)
(1)構(gòu)建計算輸出層輸出的函數(shù)
(2)構(gòu)建計算隱含層輸出的函數(shù)
(3)定義代價函數(shù)
(4)式9中x與d分別為輸入與對應(yīng)的期望輸出,皆為已知,所以代價函數(shù)則為兩個權(quán)值矩陣的函數(shù),為了使代價函數(shù)減小,權(quán)值的調(diào)整應(yīng)往負(fù)梯度方向調(diào)整,如下:(η為學(xué)習(xí)率,可以理解為往負(fù)梯度方向改變的步長)
(5)將式10和式11按鏈?zhǔn)角髮?dǎo)法則進(jìn)行展開:
(6)對輸出層和隱含層各定義一個誤差信號(本質(zhì)上為負(fù)梯度):
(7)將式14和式15代入式12和式13,得:
(8)求解輸出層和隱含層的學(xué)習(xí)信號(需結(jié)合式1和式3):
(9)計算式18和19中的偏導(dǎo):
(10)將式20和式21帶回式18和19:
(11)將式22)和式23帶回式16和17,得:
(12)將三層感知器推廣到任意層數(shù)神經(jīng)網(wǎng)絡(luò):
假設(shè)神經(jīng)網(wǎng)絡(luò)共n層。
(三)BP神經(jīng)網(wǎng)絡(luò)python實現(xiàn)
如果讀者想自己動手在python上實現(xiàn)BP神經(jīng)網(wǎng)絡(luò)的話,可以根據(jù)文章給出的關(guān)于學(xué)習(xí)信號的求取方法進(jìn)行編程,本文給出了自己的實現(xiàn)代碼,且將其封裝成一個類,基本上的屬性和方法都具有,通用性較強,讀者既可調(diào)用其來訓(xùn)練自己的模型,也可以參考其架構(gòu)自行編寫代碼。
1、模型所需傳參介紹
layer 為神經(jīng)網(wǎng)絡(luò)各層神經(jīng)元的個數(shù),包括輸出層神經(jīng)元個數(shù),傳參形式以列表傳入; activate:為各層的激活函數(shù),傳參形式為字符串或列表,若傳入一個字符串,則各層激活函數(shù)相同,若傳入一個列表,則列表元素代表各層激活函數(shù)可傳參數(shù)有:(1)sigmoid:S型函數(shù)(2)tanh:雙曲正弦函數(shù)(3)relu:max(0,x)函數(shù)(4)purline:線性函數(shù)(5)softsign:平滑函數(shù)lr:學(xué)習(xí)率,默認(rèn)為0.01 epoch:最大迭代次數(shù) 默認(rèn)為1e42、模型具有的主要方法和屬性
fit(X,Y):模型擬合方法 predict(X):輸出預(yù)測方法 predict_label(X):分類標(biāo)簽輸出預(yù)測方法 activate:激活函數(shù)列表 W:權(quán)值列表3、python代碼
import numpy as np import time class Cyrus_BP(object):"""layer 為神經(jīng)網(wǎng)絡(luò)各層神經(jīng)元的個數(shù),包括輸出層神經(jīng)元個數(shù),傳參形式以列表傳入;activate:為各層的激活函數(shù),傳參形式為字符串或列表,若傳入一個字符串,則各層激活函數(shù)相同,若傳入一個列表,則列表元素代表各層激活函數(shù)可傳參數(shù)有:(1)sigmoid:S型函數(shù)(2)tanh:雙曲正弦函數(shù)(3)relu:max(0,x)函數(shù)(4)purline:線性函數(shù)(5)softsign:平滑函數(shù)lr:學(xué)習(xí)率,默認(rèn)為0.01epoch:最大迭代次數(shù) 默認(rèn)為1e4該模型具有的主要方法和屬性如下:fit(X,Y):模型擬合方法predict(X):輸出預(yù)測方法predict_label(X):分類標(biāo)簽輸出預(yù)測方法activate:激活函數(shù)列表W:權(quán)值列表"""def __init__(self,layer,**kargs):self.layer = np.array(layer).reshape(1,-1)if 'activate' in kargs.keys():if str(type(kargs["activate"])) == "<class 'str'>": self.activate = [kargs["activate"]]*int(len(layer))else:self.activate = kargs["activate"]else:self.activate = ["sigmoid"]*int(len(layer))self.diff_activate = []if 'lr' in kargs.keys():self.lr = kargs["lr"]else:self.lr = 0.01if 'epoch' in kargs.keys():self.epoch = kargs["epoch"]else:self.epoch = int(1e4)self.X = Noneself.Y = Noneself.W = Noneself.output = []self.delta = []self.sum_input = []# 1、選擇激活函數(shù)def activation_func(self):temp_func = []for i in range(len(self.activate)):if self.activate[i] == "sigmoid":temp_func.append(lambda x:1/(1+np.exp(-x)))self.diff_activate.append(lambda x:(1/(1+np.exp(-x)))*(1-(1/(1+np.exp(-x)))))if self.activate[i] == "tanh":temp_func.append(lambda x:(np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x)))self.diff_activate.append(lambda x:((-np.exp(x) + np.exp(-x))*(np.exp(x) - np.exp(-x))/(np.exp(x) + np.exp(-x))**2 + 1))if self.activate[i] == "softsign":temp_func.append(lambda x:x/(1+np.abs(x)))self.diff_activate.append(lambda x:1/((1+x/np.abs(x)*x)**2))if self.activate[i] == "relu":temp_func.append(lambda x:(x+np.abs(x))/(2*np.abs(x))*x)self.diff_activate.append(lambda x:(x+np.abs(x))/(2*np.abs(x)))if self.activate[i] == "purline":temp_func.append(lambda x:x)self.diff_activate.append(lambda x:1+x-x)self.activate = temp_func# 2、權(quán)值初始化函數(shù)def init_w(self):self.W = []for i in range(self.layer.shape[1]):if i == 0:w = np.random.random([self.X.shape[1]+1,self.layer[0,i]])*2-1else:w = np.random.random([self.layer[0,i-1]+1,self.layer[0,i]])*2-1self.W.append(w)# 3、權(quán)值調(diào)整函數(shù)def update_w(self):# 1 計算各層輸出值self.output = []self.sum_input = []for i in range(self.layer.shape[1]):if i == 0:temp = np.dot(np.hstack((np.ones((self.X.shape[0],1)),self.X)),self.W[i])self.sum_input.append(temp)self.output.append(self.activate[i](temp))else:temp = np.dot(np.hstack((np.ones((self.output[i-1].shape[0],1)),self.output[i-1])),self.W[i])self.sum_input.append(temp)self.output.append(self.activate[i](temp))# 2 求每層的學(xué)習(xí)信號self.delta = [0 for i in range(len(self.output))]for i in range(len(self.output)):if i == 0:self.delta [-i-1] = ((self.Y-self.output[-i-1])*self.diff_activate[-i-1](self.sum_input[-i-1]))else:self.delta [-i-1] = ((self.delta[-i].dot(self.W[-i][1:,:].T))*self.diff_activate[-i-1](self.sum_input[-i-1]))# 3 更新權(quán)值for i in range(len(self.W)):if i == 0 :self.W[i] += self.lr * np.hstack((np.ones((self.X.shape[0],1)),self.X)).T.dot(self.delta[i])else:self.W[i] += self.lr * np.hstack((np.ones((self.output[i-1].shape[0],1)),self.output[i-1])).T.dot(self.delta[i])def fit(self,X,Y):self.X = np.array(X)self.Y = np.array(Y)# 1 權(quán)值初始化self.init_w()# 2 選擇激活函數(shù)self.activation_func()# 3 更新權(quán)值start_time = time.time()for i in range(int(self.epoch)):self.update_w()end_time = time.time()if end_time - start_time >= 5:print("Epoch%d:"%(i+1),np.mean(np.square(self.Y-self.output[-1])))print("\n")start_time = time.time()def predict(self,x):x = np.array(x)result = []for i in range(self.layer.shape[1]):if i == 0:result.append(self.activate[i](np.dot(np.hstack((np.ones((x.shape[0],1)),x)),self.W[i])))else:result.append(self.activate[i](np.dot(np.hstack((np.ones((result[i-1].shape[0],1)),result[i-1])),self.W[i])))return result[-1]def predict_label(self,x):x = np.array(x)result = []for i in range(self.layer.shape[1]):if i == 0:result.append(self.activate[i](np.dot(np.hstack((np.ones((x.shape[0],1)),x)),self.W[i])))else:result.append(self.activate[i](np.dot(np.hstack((np.ones((result[i-1].shape[0],1)),result[i-1])),self.W[i])))result = result[-1] return np.array([result[i].argmax() for i in range(result.shape[0])]).reshape(-1,1)if __name__ == "__main__":bp = Cyrus_BP([50,10,3],lr=0.01,epoch = 2e5,activate = ["softsign","softsign","softsign"])from sklearn.datasets import load_irisfrom sklearn.metrics import accuracy_scoredata = load_iris()X = data["data"]Y = data["target"]import pandas as pd# 用神經(jīng)網(wǎng)絡(luò)進(jìn)行分類時,需把輸出先進(jìn)行獨熱編碼Y1 = pd.get_dummies(Y1) # 進(jìn)行獨熱編碼或?qū)⑵谕敵鲛D(zhuǎn)換為啞變量bp.fit(X,Y1)Y_pre = bp.predict_label(X)print("準(zhǔn)確率為:",accuracy_score(Y,Y_pre))4、代碼運行結(jié)果
Epoch9314: 0.02853577904298399Epoch19691: 0.02145897246261971Epoch31495: 0.01784770845276102Epoch42539: 0.01415043927077651Epoch53434: 0.015407038745481208Epoch64893: 0.016390764988851683Epoch76186: 0.015016316993973523Epoch86931: 0.013693150044879728Epoch97390: 0.013706384360315056Epoch108511: 0.012193768543380657Epoch118993: 0.010314480349340294Epoch128337: 0.009862103298377766Epoch138193: 0.01057658278951552Epoch147889: 0.009652582210903272Epoch157632: 0.009137051214565095Epoch165815: 0.009407398018203143Epoch175037: 0.009429640020604707Epoch185229: 0.00991562156191445Epoch194220: 0.009801710064963167 準(zhǔn)確率為: 0.9933333333333333可見模型訓(xùn)練結(jié)果還是不錯的
by CyrusMay 2020 05 11
晚風(fēng)吻盡 荷花葉
任我醉倒在池邊
等你清楚看見我的美
月光曬干眼淚
——五月天(擁抱)——
總結(jié)
以上是生活随笔為你收集整理的深度学习(神经网络) —— BP神经网络原理推导及python实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习 回归篇(1)——多元线性回归
- 下一篇: 机器学习 集成学习篇——python实现