BP神经网络的算法流程:
算法步骤
步骤1:初始化权重
每二个神经元之间的网络连接权重 被初始化为一个很小的随机数,同时每个神经元有一个偏置 也被初始化为一个随机数。对每个输入样本 按步骤2进行处理。
步骤2:向前传播输入
根据训练样本 提供网络的输人层,通过计算得到每个神经元的输出。都由其输入的线性组合得到,具体公式为:
步骤3:反向误差传播
由步骤2一路向前,最终在输出层得到实际输出,可以通过与预期输出相比较得到每个输出单元 的误差, 如公式 (for each output unit calculate its error term)所示, 是输出单元 的预期输出。得到的误差需要从后向前传播,前面一层单元 的误差可以通过和它连接的后面一层的所有单元k的误差计算所得,用公式: (for each hidden unit )依次得到最后一个隐含层到第一个隐含层每个神经元的误差。
步骤4:网络权重与神经元偏置调整
计算得到的所有神经元的误差,然后统一调整网络权重和神经元的阈值。
调整网络权重的方法是从输入层与第一隐含层的连接权重开始,依次向后进行,每个连接权重 用公式 = + = +( ) 进行调整。
神经元偏置的调整方法是对每个神经元 用公式: = + = +( ) 更新。
步骤5:判断结束
对于每个样本,如果最终的输出误差小于可接受的范围或者迭代次数t达到了一定的阈值,则选取下一个样本,转到步骤2重新继续执行。否则,迭代次数加1,然后转向步骤2继续使用当前样本进行训练。
举例:
已知一个前馈型神经网络例子如下图所示。设学习率l为0.9,当前的训练样本为x={1,0,1},而且预期分类标号为1,同时,下表给出了当前该网络的各个连接权值和神经元偏置。求该网络在当前训练样本下的训练过程 。
python代码实现:
import numpy as np import random import math import matplotlib.pyplot as plt ##初始化权重矩阵,N为输入层的神经元个数,n为输出层的神经元个数 def init(N,n): C = [] for i in range(N): c = [] for j in range(n): a = np.random.uniform(-1,1) c.append(a) C.append(c) return C ##每一层的总输入和输出 def cal_s(W,N,n,X,c): Q = [] for i in range(n):##对第i列 s=0 for j in range(N):##对第j行 s =s+W[j][i]*X[j] s+=c[i] q = 1/(1+math.e**(-s)) Q.append(q) return Q ## 计算输出层的能量函数E def cal_e2(Q,T,n): E = [] for i in range(n): e = Q[i]*(1-Q[i])*(T[i]-Q[i]) E.append(e) return E ##计算隐含层的能量函数E1 def cal_e1(Q, W, E, n): E1 = [] for i in range(n): s = 0 for j in range(len(E)): s = s + W[i][j] * E[j] e1 = Q[i] * (1 - Q[i]) * s E1.append(e1) return E1 ##调整权重矩阵 def fit_W(W,N,n,E,Q,l): for i in range(N): for j in range(n): W[i][j]=W[i][j]+l*E[j]*Q[i] return W ##调整阈值 def fit_c(c,E,n,l): for i in range(n): c[i] += l*E[i] return c N = 3 ##输入层神经元数 n = 2 ##隐含层神经元数 m = 1 ##输出层神经元数 ##初始化第一层权重函数W1,第二层权重函数W2,阈值函数c1,c2(在-1到1中随机取值) W1 = init(N,n) W2 = init(n,m) c1 = (np.random.random(n)-0.5)*2 c2 = (np.random.random(m)-0.5)*2 X = [1,0,1] T = [1] l = 0.9 t = 500##迭代次数 Y =[] for i in range(1,t+1): #print("第",i,"次迭代:") ##计算隐藏层的输出Q1,输出层的输出Q2 Q1 = cal_s(W1,N,n,X,c1) Q2 = cal_s(W2,n,m,Q1,c2) #print(Q1,Q2) ##计算输出层的误差 E2 = cal_e2(Q2,T,m) E1 = cal_e1(Q1,W2,E2,n) #print(E2,E1) ##调整权重矩阵 W1 = fit_W(W1,N,n,E1,X,l) #print(W1) W2 = fit_W(W2,n,m,E2,Q1,l) #print(W2) ##调整阈值 c1 = fit_c(c1,E1,n,l) c2 = fit_c(c2,E2,m,l) #print(c1,c2) Y.append(E2[0]) plt.plot(Y) plt.show()
运行结果:
代码改进:
import numpy as np import scipy.special as sp import math import matplotlib.pyplot as plt # 函数:前向传播 # 函数:后向传播 # 函数:读取数据---初始化数据 # 函数:初始化w b # 超参数:输入节点数,输出节点数,隐藏层节点数 class net: def __init__(self,iteration,rate,input_data,label,input_num=3,hidden_num=2,output_num=1): """initialize variable and run train funtion""" self.w1=np.random.rand(hidden_num,input_num)*2-1 self.w2=np.random.rand(output_num,hidden_num)*2-1 self.b1=np.random.rand(hidden_num,1)*2-1 self.b2=np.random.rand(output_num,1)*2-1 self.input_num=input_num self.output_num=output_num self.hidden_num=hidden_num self.iteration=iteration self.rate=rate self.E=[] # self.activate_function= lambda x:sp.expit(x) self.input_data=input_data self.label=np.reshape(label,(output_num,1)) for i in range(self.iteration): self.train(self.input_data,self.label) print("finish") def activate_function(self, data): """activate funciton for matrix""" """ arg: data:example :np.ndarray (not list) """ shape=data.shape s= list(map(lambda x: 1 / (1 + math.exp(-x)),data)) return np.reshape(s,shape) def train(self,input_data,label): """train data""" """ arg: input_data: train_data_X label: train_data_Y """ input_data = np.reshape(input_data,(self.input_num,1))#np.reshape(data,(a,b))把data变换(a,b)的维度 hidden_inputs = np.dot(self.w1,input_data)+self.b1#np.dot(X,Y) 矩阵X Y相乘 hidden_output = self.activate_function(hidden_inputs) output_input=np.dot(self.w2,hidden_output)+self.b2 final=self.activate_function(output_input) E2=abs(final-label) self.E.append(E2[0][0]) E1=np.dot(self.w2.T,E2)*hidden_output*(1-hidden_output) self.w2+=self.rate*hidden_output.T*E2 self.w1+=self.rate*input_data.T*E1 self.b1+=self.rate*E1 self.b2+=self.rate*E2 def query(self,input_data): """query text_data""" input_data = np.reshape(input_data,(self.hidden_num,1))#np.reshape(data,(a,b))把data变换(a,b)的维度 hidden_inputs = np.dot(self.w1,input_data)+self.b1#np.dot(X,Y) 矩阵X Y相乘 hidden_output = self.activate_function(hidden_inputs) output_input=np.dot(self.w2,hidden_output)+self.b2 final=self.activate_function(output_input) return final a=net(500,0.9,[1,0,1],[1]) print(a.E[-1]) plt.plot(a.E) plt.show()