Python课程设计基于卷积神经网络的手写数字识别系统源码

目录

一、选题

二、用到的知识

三、具体流程

1、参数配置文件的加载

2、加载数据集,分割训练集和测试集

3、layer的生成

4、神经网络的反向传播


一、选题

源 码 免 费 下 载 链 接 如 下:

Python课程设计基于卷积神经网络的手写数字识别系统源码.zip-Python文档类资源-CSDN下载Python课程设计基于卷积神经网络的手写数字识别系统源码.zipPython课程设计基于卷积神经网更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/chengxuyuanlaow/86762748利用numpy完成手写数字数据集的识别,完成多分类问题,搭建神经网络,并且完成模型的训练以及性能评估,可视化数据

二、用到的知识

  1. sklearn 数据集的提取分割
  2. yaml配置文件使用
  3. numpy实现各个神经层
  4. 参数初值选择
  5. 梯度下降方法选择
  6. sklearn 分类模型评估
  7. matplotlib数据可视化
  8. 设计模式
  9. Markdown写报告
  10. 防脱发技术

代码框架如下所示:

.
├── save_params.pkl 训练好的模型 
├── params.yaml     神经网络搭建参数配置
├── tools.py        卷积和池化过程用到的转换
    ├── im2col            将图像卷积转化为矩阵相乘的形式
    └── col2im            反向传播将矩阵相乘形式转化为原图像
├── optimizer.py    参数更新方法
    ├── OptimizerBase类     参数更新方法基类,必须重写覆盖虚函数才能构造类
          └── update     对参数进行更新,子类的update同作用
    ├── AdaGrad类        AdaGrad方法
    └── SGD类            随机梯度下降法
├── network.py      主程序,将所有其它模块连接起来
    └── NeuralNetwork类     神经网络总类
        ├── test       模型测试
        ├── loadAndTest 加载已经训练好的模型然后测试
        ├── runNetWork  训练模型
        ├── predict     所有网络层前向传播
        ├── update      所有网络层反向传播并更新参数
        ├── getParams   获取yaml配置文件参数
        ├── saveParams  保存训练好的参数模型
        ├── getData     获取训练集和测试集
        ├── getLayer    根据配置文件生成神经网络
        └── getTrainData  随机抽取训练数据
├── method.py       参数初始化方法
    ├── ParamsInitBase类  参数初始化基类
        ├── getParams 获取卷积层初始化参数,子类同
        └── getAffineParams 获取Affine层初始化参数,子类同
    ├── He 类      He方法初始化参数
    └── Xavier类    Xavier方法初始化参数
├── layer.py        神经网络层
    ├── LayerBase类    神经网络层基类
        ├── forward 前向传播,子类同
        ├── backward 反向传播,子类同
        ├── update 参数更新,子类同
        ├── saveParams 参数保存,子类同
        └── loadParams 参数加载,子类同
    ├── AffineLayer类
        └── ininParams 参数初始化
    ├── ReluLayer类
    ├── SoftMaxLayer类
    ├── SoftMaxLossLayer类
        └── cross_entropy_error 计算交叉熵
    ├── ConvolutionLayer类
        └── initParams 参数初始化
    ├── PoolingLayer类
    ├── DropOutLayer类
    └── LayerFactory类
        └── produce 根据神经网络层的名称和参数来构造类
├── drawer.py       结果绘制
    └── Drawer类     数据可视化类
        ├── record    记录数据
        └── plot      绘制数据
├── dataset.py      获取数据集并且split好
    └── DataPreparer类  数据准备类
        ├── getData 加载数据并且划分测试集和训练集
        └── get     外部获取数据接口
├── analyser.py     模型分析
    └── Analyser类  模型分析类
        └── analyse  分析函数

三、具体流程和代码

1、参数配置文件的加载

with open(params_path) as params_file:
        self.params = yaml.load((params_file))

这里使用了yaml文件作为配置文件,原因是yaml文件结构比较简单简洁,可以清楚地表示出层次结构,通过参数文件的配置,可以不用修改源代码就可以配置出不同的神经网络,具体见下面layer生成的分析

2、加载数据集,分割训练集和测试集

使用sklearn 来获取数据集,并且进行分割

    # 加载数据
digits_data, digits_target = load_digits(
        return_X_y=True)
# 划分训练集和测试集
self.x_train, self.x_test, self.y_train, self.y_test = \
train_test_split(digits_data, digits_target,
                test_size=1-train_size_, train_size=train_size_,
                random_state=3, shuffle=True)

3、layer的生成

def produce(self, layer: str, params_set) -> object:
    if params_set is None:
        params_set = {}
    return eval(layer)(**params_set)

这里利用eval动态生成构造信息,这样的话就可以根据配置文件的信息来动态生成类,也就是说网络选择哪些层,层的顺序是什么,只要符合一定的顺序(这个规则在yaml文件有写),就可以构造网络并且顺利运行,所得到的层使用OrderDict按顺序存储

  1. 训练数据的提取

    由于训练集数据并不多,如果仅仅利用这些数据训练的话,一定不够,所以采用了每次随机提取一个batch的数据的方案来进行训练,这样可以缓解数据集不足的问题

  2. 参数初始化方法

    • 由于使用Relu函数作为激活函数,故参数初始化统一使用He方法,Xavier方法可选
  3. 神经网络的前向传播

    根据 ConvolutionLayer -> ReluLayer -> PoolingLayer -> ConvolutionLayer -> ReluLayer -> PoolingLayer -> ConvolutionLayer -> ReluLayer -> DropOutLayer -> AffineLayer -> ReluLayer -> AffineLayer -> SoftMaxLossLayer 的顺序搭建网络,然后依次调用forward函数即可

  • AffineLayer的前向传播

    1. 由于传进的维度可能不是二维,所以首先要保存原来的维度信息,然后resize成二维矩阵

    2. 根据矩阵的乘法以及加法来计算前向传播值

  • ConvolutionLayer的前向传播

    1. 将图像卷积转化为易于矩阵相乘的形式

    2. 用相同与AffineLayer前向传播的方式计算

  • ReluLayer的前向传播

    1. mask标记出小于零的项,然后使这些项等于0
  • PoolingLayer的前向传播

    1. 利用im2col将4个数放在同一行(2*2池化核的情况下)

    2. 计算每一行的最大值,保留最大值,其它全部删去,传播给下一层

    3. 保存最大值的索引,方便反向传播

  • DropOutLayer的前向传播

    1. 训练模式下,删去部分神经元,即将参数设置为0,传播给下一层

    2. 测试模式下,将每一个神经元参数下降一定比例

  • SoftMaxLossLayer的前向传播

    1. 利用SoftMax层进行计算,得到前向传播的最终结果

    2. 对SoftMax层的计算结果利用交叉熵方法求loss

4、神经网络的反向传播

  • AffineLayer的反向传播

    1. 根据矩阵乘法求取梯度(这里不具体分析原因,需要用到矩阵论的知识)

    2. 矩阵乘法求取反向传播值,并且将值resize回原来的形状

  • ConvolutionLayer的反向传播

    1. 用同于计算AffineLayer反向传播的方法计算

    2. 将结果用col2im还原为原来图片的形状

  • ReluLayer的反向传播

    1. 使原来小于零的项反向传播值也为0
  • PoolingLayer的反向传播

    1. 使前向传播最大值处的梯度值保留,其余处的梯度值变为0

    2. 将矩阵使用col2im转化回原来的形式

  • DropOutLayer的反向传播

    1. 删除部分的神经元反向传播值为0
  • SoftMaxLossLayer的前向传播

    1. 公式 y-t 来进行计算

神经网络的参数更新

  • 通过反向传播之后,我们获得了AffineLayer和ConvolutionLayer的梯度值,于是可以根据这些梯度值对参数进行更新,更新方法有两种可选:
    1. 随机梯度下降法,学习率恒定

    2. AdaGrad:学习率会根据之前梯度的平方和来逐渐削弱

  1. 模型测试

        x_test = self.x_test.reshape(-1, 1, 8, 8)
        x_predict = self.predict(x_test)
        predict_y = np.argmax(x_predict, axis=1)
  2. 参数保存

  • 通过调用每一层的saveParams()函数,可以对每一层的参数按顺序保存,然后利用pickle保存模型参数为pkl格式

    params_list = []
        for layer in self.order_layer.values():
            params_list.append(layer.saveParams())
        with open(self.params['save_params_path'], 'wb') as f:
            pickle.dump(params_list, f)
  1. 参数加载
  • 在已经保存参数模型之后,可以调用loadAndTest()函数对参数进行加载。思路是先通过正常方式构建网络,然后将W,b两个参数通过调用网络的initParams()函数进行构造
  1. 模型评估
  • 使用sklearn的metrics板块对分类模型进行评估

        print(metrics.classification_report(target, predict_y))
        print(metrics.accuracy_score(target, predict_y))
        print(metrics.confusion_matrix(target, predict_y))
  • 通过不同的测试集和不同的数据集,正确率在 97.2 - 99.4 不等

    • 由数据可以知道,准确率只有1,5 不到1.00,根据混淆矩阵,可以知道1被错误识别为5,5被错误识别为6(这个也可以通过召回率来得到,通过混淆矩阵可以知道准确率和召回率是怎样计算的)
  1. loss曲线绘制
  • 利用matplitlib中的绘制散点图函数,即

        plt.scatter(x, self.data_set)
        plt.title("handwriting digits classification")
        plt.xlabel('num')
        plt.ylabel('loss')
        plt.legend('loss')
  • 由图可以看出,第一次迭代时梯度下降最快,后续下降越来越慢最终loss稳定在 10 * e-4 左右

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不安分的小女孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值