小白学习机器学习---第五章:神经网络简单模型python实现

简单的单隐层神经网络实现,需要注意的是,隐层的结点个数需要经过多次试验获得最佳参数,如果设置太多可能引起过拟合问题,目前就简单实现其原理。


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-神经元模型引入机器学习的,脑洞有点大~

猜你喜欢

转载自blog.csdn.net/hx14301009/article/details/79743120