深度学习导论-BP神经网络识别书写数字(Python实现)

BP简介

Bp神经网络的一大特点就是:信号前向计算,误差反向传播。根据这一特点来编写网络

标准BP算法流程

在这里插入图片描述

学习完一个样本就计算每层的误差信号并调整权重

批训练BP算法流程

在这里插入图片描述

学习完所有样本,根据总误差计算各层的误差信号并调整权重

代码

本文使用多层bp神经网络进行手写数字的识别。采用标准bp算法流程,但训练结束条件为达到训练次数就结束。

class BPNeuralNetwork(object):
    def __init__(self,layers,learing_rate,epochs):
        self.layers=layers
        self.learing_rate=learing_rate
        self.epochs=epochs
        self.W=self.initW()
    @property
    def getW(self):
        return self.W
    @property
    def getV(self):
        return self.V
    
    def initW(self):
        W=[]
        for i in range(0,len(self.layers)-1):
            #输出层
            if(i==len(self.layers)-2):
                W.append(np.random.random((self.layers[i]+1,self.layers[i+1]))*2-1)
            #隐藏层
            else:
                W.append(np.random.random((self.layers[i]+1,self.layers[i+1]+1))*2-1)
        return W
    def sigmoid(self,x):
        return 1/(1+np.exp(-x))
    def dsigmoid(self,x):
        return x*(1-x)
    def back_propagete(self,label,outputs):
        #反向传播
        '''一直没找出原因,最后发现是传入label错误,最开是将所有label传入,然后label[i]-outputs[i].
        导致每次的标签都不一样,得不到正确结果'''
        deltas=[]
        n=len(self.layers)
        delta=0
        for i in range(n-1,0,-1):
            if(i==n-1):
                delta=(label-outputs[i])*self.dsigmoid(outputs[i])
            else:
                delta= delta.dot(self.W[i].T)*self.dsigmoid(outputs[i])    
            #逆序,插入前面
            deltas.insert(0,delta)
            
        for j in range(n-2,-1,-1):
            #更新权值
            d=self.learing_rate*(outputs[j].T).dot(deltas[j])
            self.W[j] += d
 
        
    def update(self,input_data):
        outputs=[]
        outputs.append(input_data)
        for i in range(0,len(self.layers)-1):
            #正向学习
            input_data=self.sigmoid(np.dot(input_data,self.W[i]))
            outputs.append(input_data)
        return outputs
        
    
        
    def fit(self,data,label):
        #添加偏置
        temp = np.ones([data.shape[0],data.shape[1]+1])
        temp[:,0:-1] = data
        data = temp
        
        for n in range(self.epochs+1):
            #随机选取一个数据
            i = np.random.randint(data.shape[0]) 
            x = [data[i]]
            #转为2维数据
            x = np.atleast_2d(x)

            outputs=self.update(x)
            self.back_propagete(label[i],outputs)
    
            
            #每训练1000次预测一次准确率
            if n%1000==0:
                predictions = []
                for j in range(X_test.shape[0]):
                    o = self.predict(X_test[j])
                    #获取预测结果
                    predictions.append(np.argmax(o))
                accuracy = np.mean(np.equal(predictions,y_test))
                print(f'epoch:[',n,f'/ {self.epochs}]   accuracy:',accuracy)
        
        
        
    def predict(self,x):
        #添加偏置
        temp = np.ones(x.shape[0]+1)
        temp[0:-1] = x
        x = temp
        x = np.atleast_2d(x)#转为2维数据
        for i in range(0,len(self.layers)-1):
            x=self.sigmoid(np.dot(x,self.W[i])) 
        return x
        
if __name__ =="__main__":
    #加载手写数字数据集
    digits = load_digits()
    X = digits.data
    y = digits.target
    #输入数据归一化
    X -= X.min()
    X /= X.max()
    #创建网络
    nm = BPNeuralNetwork([64,100,10],0.11,20000)
    X_train,X_test,y_train,y_test = train_test_split(X,y)
    #标签二值化
    labels_train = LabelBinarizer().fit_transform(y_train)
    #标签二值化     
    labels_test = LabelBinarizer().fit_transform(y_test)

    print('start training')

    nm.fit(X_train,labels_train)

    print('end')
  

最终准确率在97%左右
在这里插入图片描述

调整学习率、网络层数、训练次数发现:

  1. 学习率过大 收敛速度快,但是震荡不稳定
  2. 学习率过小,收敛得慢,同等训练次数,不能达到较好的效果
  3. 网络层数,确实没看出有什么规律
  4. 可能是网络自身限制,最多也就准确率97%的样子
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值