神经网络 python实现

本文是将mnist的分类测试,神经网络的python实现
文章的加载路径也是电脑本地的路径,所以应用时注意路径和读取数据的名称的关系
读取mnist数据集,输出结果是一矩阵,每一列为一张图片拉成的向量

import struct
import os
import numpy as np
from matplotlib import pyplot as plt
class MNIST(object):
    '''
    MNIST数据集类
    '''
    def __init__(self,root, image_file, lable_file):
        '''
        方法说明:
            初始化类
        参数说明:
            root: 文件夹根目录
            image_file: mnist图像文件 'train-images.idx3-ubyte' 'test-images.idx3-ubyte'
            label_file: mnist标签文件 'train-labels.idx1-ubyte' 'test-labels.idx1-ubyte'
        '''
        self.img_file = os.path.join(root, image_file)
        self.label_file = os.path.join(root, lable_file)
        
        self.img = self._get_img()
        self.label = self._get_label()

    #读取图片
    def _get_img(self):

        with open(self.img_file,'rb') as fi:
            ImgFile = fi.read()
            head = struct.unpack_from('>IIII', ImgFile, 0)
            #定位数据开始位置
            offset = struct.calcsize('>IIII')
            ImgNum = head[1]
            width = head[2]
            height = head[3]
            #每张图片包含的像素点
            pixel = height*width
            bits = ImgNum * width * height
            bitsString = '>' + str(bits) + 'B'
            #读取文件信息
            images = struct.unpack_from(bitsString, ImgFile, offset)
            #转化为n*726矩阵
            images = np.reshape(images,[ImgNum,pixel])
        
        return images

    #读取标签
    def _get_label(self):

        with open(self.label_file,'rb') as fl:
            LableFile = fl.read()
            head = struct.unpack_from('>II', LableFile, 0)
            labelNum = head[1]
            #定位标签开始位置
            offset = struct.calcsize('>II')
            numString = '>' + str(labelNum) + "B"
            labels = struct.unpack_from(numString, LableFile, offset)
            #转化为1*n矩阵
            labels = np.reshape(labels, [labelNum])

        return labels

    #数据标准化
    def normalize(self):
        
        min = np.min(self.img, axis=1).reshape(-1,1)
        max = np.max(self.img, axis=1).reshape(-1,1)
        self.img = (self.img - min)/(max - min)

    #数据归一化
    def standardlize(self):
        
        mean = np.mean(self.img, axis=1).reshape(-1,1)
        var = np.var(self.img, axis=1).reshape(-1,1)
        self.img = (self.img-mean)/np.sqrt(var)
        
    def out(self):
        self.standardlize()
        self.normalize()
        
        return self.img

读取数据

train_image=MNIST('./相关资料/','train-images.idx3-ubyte','train-labels.idx1-ubyte').out()
train_labels=MNIST('./相关资料/','train-images.idx3-ubyte','train-labels.idx1-ubyte')._get_label()
test_image=MNIST('./相关资料/','test-images.idx3-ubyte','test-labels.idx1-ubyte').out()
test_labels=MNIST('./相关资料/','test-images.idx3-ubyte','test-labels.idx1-ubyte')._get_label()

将标签转化成向量

def labels_to_vec(labels):
    list_labels=[]
    for i in range(len(labels)):
        vec=[0]*10
        vec[labels[i]]=1
        list_labels.append(vec)
    return list_labels
 list_labels=labels_to_vec(train_labels)
 train_labels=np.array(list_labels)   

改用cupy加速运算(cupy和numpy的函数是基本一致的,只是在gpu和cpu的关系,也就是说将下面代码中的cupy的缩写cp均改为numpy的前缀仍可以运行)

import cupy as cp
train_image=cp.asarray(train_image)
train_labels=cp.asarray(train_labels)
test_image=cp.asarray(test_image)

神经网络实现,内含测试函数,通过迭代次数观察正确率的变化

class neural_network(object):
    
    def __init__(self,datasets,labels,maxiter,test_data,test_labels):
        '''
        初始化
        '''
        self.datasets=datasets
        self.labels=labels
        self.maxiter=maxiter
        
        self.test_data=test_data
        self.test_labels=test_labels
        
        
        self.w1=cp.random.randn(512,784)
        self.w2=cp.random.randn(256,512)
        self.w3=cp.random.randn(10,256)
        
        self.learn_rate=0.001
        
    def tanh(self,z):
        
        return (cp.exp(z)-cp.exp(-z))/(cp.exp(z)+cp.exp(-z))
    
    def de_tanh(self,z):
        return  1 - self.tanh(z) * self.tanh(z)
    
    def softmax(self,z):
        
        return cp.exp(z)/cp.sum(cp.exp(z))
    
    def forward_net(self,dataset):
        '''
        正向传播
        '''
        
        x=dataset.T
        z1=cp.dot(self.w1,x)
        a1=self.tanh(z1)
        z2=cp.dot(self.w2,a1)
        a2=self.tanh(z2)
        z3=cp.dot(self.w3,a2)
        y_pred=self.softmax(z3)
       
        
        
        return z1,a1,z2,a2,z3,y_pred
    def backpropagation(self,x,z1,a1,z2,a2,z3,y_pred,y):
        '''
        采用交叉熵损失函数
        反向传播
        '''
      
        
        dl_dz3=y_pred-y
        dl_dw3=cp.dot(dl_dz3,a2.T)

        dl_dz2=cp.dot(self.w3.T,dl_dz3)*self.de_tanh(z2)
        dl_dw2=cp.dot(dl_dz2,a1.T)

        dl_dz1=cp.dot(self.w2.T,dl_dz2)*self.de_tanh(z1)
        dl_dw1=cp.dot(dl_dz1,x.T)
        
        
        self.w1=self.w1-self.learn_rate*dl_dw1
        self.w2=self.w2-self.learn_rate*dl_dw2
        self.w3=self.w3-self.learn_rate*dl_dw3
    def test_Correct_rate(self):
        '''
        正确率测试
        '''
        count=0
        for i in range(len(self.test_data)):
            x=self.test_data[i].reshape(1,-1)
            x=x.T
            z1=cp.dot(self.w1,x)#(1000,1)
            a1=self.tanh(z1)
            z2=cp.dot(self.w2,a1)#(300,1)
            a2=self.tanh(z2)
            z3=cp.dot(self.w3,a2)#(1,1)
            y_pred=self.softmax(z3)

            y_pred=y_pred.argmax()
            if y_pred==self.test_labels[i]:
                count+=1
        rate=count/len(self.test_data)
        
        return rate
    def train(self):
        '''
        训练函数
        '''
        iters=0
        list_rate=[0]
        while iters<=self.maxiter:
            iters+=1
            for i in range(60000):
                dataset=self.datasets[i].reshape(1,-1)

                z1,a1,z2,a2,z3,y_pred=self.forward_net(dataset)

                self.backpropagation(dataset.T,z1,a1,z2,a2,z3,y_pred,self.labels[i].reshape(-1,1))
        
            rate=self.test_Correct_rate()
            list_rate.append(rate)
            
            print("\r最新正确率%.2f %%" % ( list_rate[-1]*100 ), end="")
        plt.plot(list(np.array(range(iters+1))),list_rate,color = 'r')

应用

neural_network(train_image,train_labels,20,test_image,test_labels).train()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值