当前位置: 首页 > news >正文

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 左右

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • web前端网页设计作业—个人网页(游戏主题)(html+css+js)
  • 智能车逆透视、去畸变教程(含上位机、源码)
  • 拓展班上机课题解22/10/14
  • Matlab论文插图绘制模板第56期—曲面图(Surf)
  • LQ0091 完全二叉树的权值【最值】
  • 量子笔记:张量、外积、张量积
  • Hadoop中的Yarn 生产环境核心参数配置案例、Yarn 案例实操(一)
  • GCN(Graph Convolutional Netwok)公式推导
  • Docker打包深度学习项目
  • 常见十大排序算法(动图剖析)
  • 串口数据流抓包监控监视侦听监测获取PC软件和串口设备
  • 基于MAX-SUM算法的大规模信息系统的协调问题matlab仿真——详细版
  • 【九天·毕昇】一个免费获得GPU的算力平台
  • Java秒杀系统设计
  • 【C语言】自定义类型(构造类型)——结构体、枚举和联合体
  • 【React系列】如何构建React应用程序
  • 08.Android之View事件问题
  • Angular Elements 及其运作原理
  • conda常用的命令
  • cookie和session
  • JavaScript 奇技淫巧
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • Terraform入门 - 1. 安装Terraform
  • Transformer-XL: Unleashing the Potential of Attention Models
  • vue脚手架vue-cli
  • XForms - 更强大的Form
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • 树莓派用上kodexplorer也能玩成私有网盘
  • # C++之functional库用法整理
  • # Spring Cloud Alibaba Nacos_配置中心与服务发现(四)
  • #define用法
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (Oracle)SQL优化基础(三):看懂执行计划顺序
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (八)c52学习之旅-中断实验
  • (苍穹外卖)day03菜品管理
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (转)创业家杂志:UCWEB天使第一步
  • *Django中的Ajax 纯js的书写样式1
  • *上位机的定义
  • .net MVC中使用angularJs刷新页面数据列表
  • .NET Standard 的管理策略
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET 表达式计算:Expression Evaluator
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .NET中的Event与Delegates,从Publisher到Subscriber的衔接!
  • @AliasFor注解
  • @Bean有哪些属性