简单的单隐层神经网络实现,需要注意的是,隐层的结点个数需要经过多次试验获得最佳参数,如果设置太多可能引起过拟合问题,目前就简单实现其原理。
import numpy as np class BP_network: def __init__(self): ###初始化变量### ###每一层的节点数 self.input_node=0 #输入层 self.hide_node=0 #隐层 self.output_node=0 #输出层 ###初始化每一层的输出变量 self.input_out=[] self.hide_out=[] self.output_out=[] ###初始化输入层到隐层与隐层到输出层的权值 self.ih_weight=[] self.ho_weight=[] ###初始化隐层与输出层的阈值 self.hide_threshold=[] self.output_threshold=[] ####定义可选的激活函数与导数 self.fun={ 'Sigmoid':Sigmoid, 'SigmoidDerivate':SigmoidDerivate } def CreateNN(self,ni,nh,no,actiFun): """ 创建一个神经网络结构并且初始化参数 ni,nh,no为三层节点个数 actiFun:string,为激活函数 """ ###给各层节点数赋值 self.input_node=ni self.hide_node=nh self.output_node=no ###给各层输出的值赋初值 self.input_out=np.zeros(self.input_node) #赋0 [0,0,0.......,0] self.hide_out=np.zeros(self.hide_node) self.output_out=np.zeros(self.output_node) ###给两层之间的权值赋初值 self.ih_weight=np.zeros([self.input_node,self.hide_node]) self.ho_weight=np.zeros([self.hide_node,self.output_node]) ####给所有权值赋初始值,(0,1) for i in range(self.input_node): for h in range(self.hide_node): self.ih_weight[i][h]=rand(0,1) for h in range(self.hide_node): for j in range(self.output_node): self.ho_weight[h][j]=rand(0,1) ###给阈值赋初始值(0,1)### self.hide_threshold=np.zeros(self.hide_node) self.output_threshold=np.zeros(self.output_node) for h in range(self.hide_node): self.hide_threshold[h]=rand(0,1) for j in range(self.output_node): self.output_threshold[j]=rand(0,1) ####初始化激活函数 self.activateFunc=self.fun[actiFun] self.actiFuncDerivation=self.fun[actiFun+'Derivate'] def Predict(self,x): ###通过构造的神经网络预测结果 ###参数x为一个list,保存input层的输入值 #激活输出层 for i in range(self.input_node): self.input_out[i]=x[i] #激活隐层 for h in range(self.hide_node): total=0.0 for i in range(self.input_node): total+=self.ih_weight[i][h]*self.input_out[i] self.hide_out[h]=self.activateFunc(total-self.hide_threshold[h]) #激活输出层 for j in range(self.output_node): total=0.0 for h in range(self.hide_node): total+=self.ho_weight[h][j]*self.hide_out[h] self.output_out[j]=self.activateFunc(total-self.output_threshold[j]) #return self.output_out#######################################3 def BackPropagate(self,x,y,learningRate): """ 通过一个样本进行BP算法, x与y是数组:输入与输出的数据集 learningRate:学习率 """ #将样例输入进行预测 self.Predict(x) #计算梯度 #计算Gj o_gradient=np.zeros(self.output_node) for j in range(self.output_node): o_gradient[j]=(y[j]-self.output_out[j])*self.actiFuncDerivation(self.output_out[j]) #计算Eh h_gradient=np.zeros(self.hide_node) for h in range(self.hide_node): for j in range(self.output_node): h_gradient[h]+=self.ho_weight[h][j]*o_gradient[j] h_gradient[h]=h_gradient[h]*self.actiFuncDerivation(self.hide_out[h]) ###更新参数 #更新W hj for h in range(self.hide_node): for j in range(self.output_node): self.ho_weight[h][j]+=learningRate*o_gradient[j]*self.hide_out[h] #更新V ih for i in range(self.input_node): for h in range(self.hide_node): self.ih_weight[i][h]+=learningRate*h_gradient[h]*self.input_out[i] #更新θj for j in range(self.output_node): self.output_threshold[j]-=learningRate*o_gradient[j] #更新γh for h in range(self.hide_node): self.hide_threshold[h]-=learningRate*h_gradient[h] def TrainStandard(self,data_in,data_out,learningRate=0.05): """ 标准BP算法 """ #误差,list E_k=[] for k in range(len(data_in)): x=data_in[k] y=data_out[k] self.BackPropagate(x,y,learningRate) y_delta2=0 for j in range(self.output_node): y_delta2+=(self.output_out[j]-y[j])*(self.output_out[j]-y[j]) E_k.append(y_delta2/2) #训练总误差 error=sum(E_k)/len(E_k) return error,E_k def PredictLabel(self,X): #通过神经网络预测结果 y=[] for m in range(len(X)): self.Predict(X[m]) if(self.output_out[0]>0.5): y.append(1) else: y.append(0) return np.array(y) def Sigmoid(x): from math import exp return 1.0/(1.0+exp(-x)) def SigmoidDerivate(y): return y*(1-y) def rand(a,b): from random import random return (b-a)*random()+a if __name__=='__main__': from sklearn.datasets import make_circles import matplotlib.pyplot as plt X,y=make_circles(100,noise=0.05)#不设置noise则会围成一个标准的椭圆 """ X : array of shape [n_samples, The generated samples. y : array of shape [n_samples] The integer labels (0 or 1) for class membership of each sample. noise:Standard deviation of Gaussian noise added to the data. Double or None(default=none) """ f1=plt.figure(1) plt.scatter(X[:,0],X[:,1],s=40,c=y) # plt.scatter(0,0.5,s=50,c='red') plt.title("circles data") #plt.show() #BP实现 nn=BP_network() nn.CreateNN(2,6,1,'Sigmoid') e=[] for i in range(2000): err,err_k=nn.TrainStandard(X,y.reshape(len(y),1),learningRate=0.1) e.append(err) print(len(e)) f2=plt.figure(2) plt.xlabel("epochs") plt.ylabel("accumulated error") plt.title("circles convergence curve") plt.plot(e) plt.show() predictResult=nn.PredictLabel(X) accuracy=0 for i in range(len(y)): t=predictResult[i] #print(t,y[i]) if(t==y[i]): accuracy+=1 print("accuracy:%d %%"%(accuracy))
最后结果:
效果还是不错的,神经网络太强大了,我更佩服哪位率先将生物中的MP-神经元模型引入机器学习的,脑洞有点大~