keras深度学习框架构建LeNet5神经网络模型实现手写数字识别

news2024/12/23 13:56:27

    之前两篇文章分别通过keras深度学习框架构建简单神经网络和卷积神经网络实现过手写数字识别实验。这篇文章分享我根据LeNet5模型构建的卷积神经网络来实现手写数字识别。

     这个实验是根据LeNet5模型构建卷积神经网络,LeNet5模型的原理图如下所示:

     相信大家在很多地方见过这个模型,但是实际上,很多代码里面并没有严格按照这个模型来做实验。为什么?主要是手写数字识别模型数据mnist规格是28*28,而这个LeNet5模型需要的数据输入是32*32。大家为了凑合,就私自改了这个模型的参数,最后输入变为了28*28,然后经历第一次卷积之后,特征图就变成了6@24*24 ,下采样再缩小一半:6@12*12。到了全连接层的时候,特征图就变为了16@4*4。

    其实这样修改,没有什么毛病,最后也能达到实验的目的,而且训练模型之后,测试准确率可以达到98%以上。

     真正要按照这个LeNet5模型就需要32*32输入形状,而现如今好像只有KNN手写数字识别那个实验好像有32*32=1024规格的训练数据集trainingDigits和测试数据集testDigits,而且那个数据量比较少,训练数据集2000个,测试数据集900多个,另一个就是它的数据是文本,要得到那个数据,还需要读文本转换。

    有一个折中的办法,就是我们可以通过opencv提供的resize方法把mnist数据集的28*28形状转为32*32形状,可能就是会丢失一些精度,而现在测试数据和用来预测图片数据也一样会修改,所以精度问题可以认为抵消。

    其实本身这个模型也有一些模糊的地方,就是这图里面并没有给出下采样层的具体方式,是使用最大值采样,还是平均值采样,还有卷积层的激活函数,只有细看论文才能找到答案。

     所以在实现中,卷积层的激活函数一般使用tanh,但是使用relu也没有问题,同理,下采样层SubSampling这里采用MaxPool2D,AveragePooling2D都行。

    简单说一下这个模型:

    输入图片矩阵形状 (32,32)

    第一层卷积层:6个卷积核,卷积核大小5*5,所以输出特征图(feature maps)大小就是6@(32-5+1) * (32-5+1) = 6@28*28

    第二层下采样(SubSampling):2*2大小,结果就是特征图大小继续减半6@14*14

    第三层卷积层:16个卷积核,卷积核大小5*5,输出特征图大小:16@(14-5+1)*(14-5+1)=16@10*10

   第四层下采样:2*2大小,特征图减小一半16@5*5

    第五层展平层:120个神经元

    第六层全连接层:84个神经元

    第七层输出层:10个神经元

    下面根据mnist数据集以及LeNet5数据模型搭建神经网络并训练测试,代码如下:

from keras.models import Sequential
from keras.layers import Conv2D, MaxPool2D, AveragePooling2D
from keras.layers import Dense, Flatten
import keras
from keras.datasets import mnist
from keras.utils import np_utils
from keras.utils.vis_utils import plot_model
import numpy as np
import cv2

# 加载数据
(X_train, y_train), (X_test, y_test) = mnist.load_data()
input_shape = (32, 32, 1)
train_x = []

test_x = []

for val in X_train:
    img = cv2.resize(val, (input_shape[0], input_shape[1]))
    train_x.append(img.reshape(input_shape))

for val_ in X_test:
    img = cv2.resize(val_, (input_shape[0], input_shape[1]))
    test_x.append(img.reshape(input_shape))

# 数据预处理
X_train = np.array(train_x) / 255.0
X_test = np.array(test_x) / 255.0

# to_categorical()将类别向量转换为二进制(只有0和1)的矩阵类型表示
y_train = np_utils.to_categorical(y_train, num_classes=10)
y_test = np_utils.to_categorical(y_test, num_classes=10)

model = Sequential()
model.add(Conv2D(6, kernel_size=(5, 5), activation='tanh', input_shape=input_shape))
model.add(AveragePooling2D(pool_size=(2, 2)))
model.add(Conv2D(16, kernel_size=(5, 5), activation='tanh'))
model.add(AveragePooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(120, activation='tanh'))
model.add(Dense(84, activation='tanh'))
model.add(Dense(10, activation='softmax'))

# 模型编译
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()
# 训练
model.fit(X_train, y_train, batch_size=128, epochs=10)

# 评估模型
score = model.evaluate(X_test, y_test)
print('acc', score[1])
plot_model(model, to_file='model.png', show_shapes=True)
model.save("lenet5.h5")

    运行代码,打印模型参数信息如下所示:

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 28, 28, 6)         156       
                                                                 
 average_pooling2d (AverageP  (None, 14, 14, 6)        0         
 ooling2D)                                                       
                                                                 
 conv2d_1 (Conv2D)           (None, 10, 10, 16)        2416      
                                                                 
 average_pooling2d_1 (Averag  (None, 5, 5, 16)         0         
 ePooling2D)                                                     
                                                                 
 flatten (Flatten)           (None, 400)               0         
                                                                 
 dense (Dense)               (None, 120)               48120     
                                                                 
 dense_1 (Dense)             (None, 84)                10164     
                                                                 
 dense_2 (Dense)             (None, 10)                850       
                                                                 
=================================================================
Total params: 61,706
Trainable params: 61,706
Non-trainable params: 0

    训练和测试过程如下:

Epoch 1/10
2023-08-30 22:04:32.166768: I tensorflow/stream_executor/cuda/cuda_dnn.cc:368] Loaded cuDNN version 8800
469/469 [==============================] - 8s 12ms/step - loss: 0.3042 - accuracy: 0.9110
Epoch 2/10
469/469 [==============================] - 5s 10ms/step - loss: 0.1113 - accuracy: 0.9664
Epoch 3/10
469/469 [==============================] - 5s 10ms/step - loss: 0.0709 - accuracy: 0.9784
Epoch 4/10
469/469 [==============================] - 5s 11ms/step - loss: 0.0530 - accuracy: 0.9843
Epoch 5/10
469/469 [==============================] - 5s 11ms/step - loss: 0.0410 - accuracy: 0.9875
Epoch 6/10
469/469 [==============================] - 5s 11ms/step - loss: 0.0329 - accuracy: 0.9898
Epoch 7/10
469/469 [==============================] - 6s 12ms/step - loss: 0.0283 - accuracy: 0.9910
Epoch 8/10
469/469 [==============================] - 6s 12ms/step - loss: 0.0228 - accuracy: 0.9928
Epoch 9/10
469/469 [==============================] - 6s 12ms/step - loss: 0.0193 - accuracy: 0.9939
Epoch 10/10
469/469 [==============================] - 6s 13ms/step - loss: 0.0159 - accuracy: 0.9949
313/313 [==============================] - 2s 4ms/step - loss: 0.0406 - accuracy: 0.9871
acc 0.9871000051498413

   测试准确率高达98.7%。

    代码最后,我们还通过plot_model保存了模型图片:

 

    另外,为了用来预测,我们还保存了模型文件lenet5.h5。 

    预测,还是祖传代码,改动了图片形状32*32像素,因为预测图片还是28*28像素,黑底白字:

import keras
import numpy as np
import cv2
from keras.models import load_model

model = load_model("lenet5.h5")


def predict(img_path):
    img = cv2.imread(img_path, 0)
    img = cv2.resize(img, (32, 32))
    img = img.astype("float32") / 255  # 0 1
    img = img.reshape(1, 32, 32, 1)  # 32 * 32 -> (1,32,32,1)
    label = model.predict(img)
    label = np.argmax(label, axis=1)
    print('{} -> {}'.format(img_path, label[0]))


if __name__ == '__main__':
    for _ in range(10):
        predict("number_images/b_{}.png".format(_))

    实验结果:

 

    这个结果,其实并不意外,也不是因为这个模型非常牛逼,预测高达100%,其实这里预测的图片只有10个,数量不多,很多图片都是自己测试过的,所以看着好像很厉害。 

    这里面有很多可变的地方,第一个就是前面说过的输入大小的问题,如果我们改动32*32到28*28,那么我们在使用mnist数据集的时候,也不用修改形状。但是这个就与这个模型有出入,虽然最后也能运行出很高的测试准确率和预测准确率。再一个可变的地方就是卷积层的激活函数,这里使用的是tanh,其实使用relu也没问题,再一个就是使用MaxPool2D作为下采样也是可以的。在模型编译的时候,我们使用的是rmsprop优化器,其实adam也行。

     LeNet5模型其实非常适合用来做数字识别,但是数字识别没有合适的训练数据集,而cifar10这个数据集就是32*32的,所以,从编码角度来说,这个模型最适合的还是图像分类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/950595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3、DVWA——CSRF

文章目录 一、CSRF概述二、low2.1 通关思路2.2 源码分析 三、medium3.1 通关思路3.2 源码分析 四、high4.1 通关思路4.2 源码分析 五、impossible 一、CSRF概述 CSRF全称为跨站请求伪造(Cross-site request forgery),是一种网络攻击方式&…

基于向量加权平均算法优化的BP神经网络(预测应用) - 附代码

基于向量加权平均算法优化的BP神经网络(预测应用) - 附代码 文章目录 基于向量加权平均算法优化的BP神经网络(预测应用) - 附代码1.数据介绍2.向量加权平均优化BP神经网络2.1 BP神经网络参数设置2.2 向量加权平均算法应用 4.测试结…

华为 连接OSPF和RIP网络---OSPF和RIP网络相互引入

路由引入简介 不同路由协议之间不能直接共享各自的路由信息,需要依靠配置路由的引入来实现。 获得路由信息一般有3种途径:直连网段、静态配置和路由协议。可以将通过这3种途径获得的路由信息引入到路由协议中,例如,把直连网段引入…

vue3+element plus 封装上传组件(图片、文件)

vue3element plus 封装上传组件&#xff08;图片、文件&#xff09; 1、新建封装组件components/upload.vue2、引入upload组件3、效果展示 1、新建封装组件components/upload.vue <template><el-upload v-model:file-list"waitFileList" class"upload…

阿里云矢量图标透明背景转换/展示时变为黑色解决方法

下载了一个矢量图标&#xff0c;背景是透明的 上传到minio然后在前端展示&#xff0c;发现透明&#xff08;白色&#xff09;的地方变成黑色了 处理方法&#xff1a;去除透明的底色。使用window的画图程序打开保存一遍&#xff0c;将透明色转为白色 OK

【UniApp开发小程序】小程序首页完善(滑到底部数据翻页、回到顶端、基于回溯算法的两列数据高宽比平衡)【后端基于若依管理系统开发】

文章目录 说明细节一&#xff1a;首页滑动到底部&#xff0c;需要查询下一页的商品界面预览页面实现 细节二&#xff1a;当页面滑动到下方&#xff0c;出现一个回到顶端的悬浮按钮细节三&#xff1a;商品分列说明优化前后效果对比使用回溯算法实现ControllerService回溯算法 优…

Mac网页开发工具 RapidWeaver 9

RapidWeaver是一款Mac上的网页设计和开发工具&#xff0c;它使用户能够快速创建专业级别的网站&#xff0c;而无需编写代码。 以下是RapidWeaver软件的一些主要特点和功能&#xff1a; 模板和主题&#xff1a;RapidWeaver提供了大量的预先设计好的模板和主题&#xff0c;使用…

【jvm】运行时数据区

目录 一、运行时数据区一、作用二、说明三、线程共用与私有区域 一、运行时数据区 一、作用 1.内存是非常重要的系统资源&#xff0c;是硬盘和CPU 的中间仓库及桥梁&#xff0c;承载着操作系统和应用程序的实时运行。JVM内存布局规定了Java在运行过程中内存申请、分配、管理的策…

扫盲:OLTP和OLAP的区别

定义 OLTP是Online Transaction Processing的缩写&#xff0c;其中文含义为&#xff1a;联机事务处理&#xff1b; OLAP是Online Analysis Processing的缩写&#xff0c;其中文含义为&#xff1a;联机分析处理。 上世纪60年代&#xff0c;关系数据库之父E.F.Codd提出了关系模…

URL重定向漏洞

URL重定向漏洞 1. URL重定向1.1. 漏洞位置 2. URL重定向基础演示2.1. 查找漏洞2.1.1. 测试漏洞2.1.2. 加载完情况2.1.3. 验证漏洞2.1.4. 成功验证 2.2. 代码修改2.2.1. 用户端代码修改2.2.2. 攻击端代码修改 2.3. 利用思路2.3.1. 用户端2.3.1.1. 验证跳转 2.3.2. 攻击端2.3.2.1…

Stable Diffusion 提示词入门指南

前言 本文主要讲解 Stable Diffusion &#xff08;下文简称 SD&#xff09;提示词的用法&#xff0c;帮助大家生成更高质量的图片 本章节主要讲解文生图&#xff0c;其他类型读者可以自行探索。同时本文主要是以 Stable Diffusion Discard 的形式生成图片 如果各位对于图片隐…

leetcode idea debug 刷题debug神器

目录 1 安装leetcode editor插件2 创建刷题目录和包3 配置配置插件模板4 参考 配置好后debug效果&#xff0c;可以一步步debug设置断点查看各个变量的变化&#xff0c;也可以跳转到对应的方法查看源码&#xff01;&#xff01;&#xff01; 1 安装leetcode editor插件 这个直接…

小赢科技,寻找金融科技核心价

如果说金融是经济的晴雨表&#xff0c;是通过改善供给质量以提高经济质量的切入口&#xff0c;那么金融科技公司&#xff0c;就是这一切行动的推手。上半年&#xff0c;社会经济活跃程度提高背后&#xff0c;金融科技公司既是奉献者&#xff0c;也是受益者。 8月29日&#xff0…

智慧景区方案:AI与视频融合技术如何助力景区监管智能化升级?

随着经济的发展&#xff0c;人们对生活的需求也不再局限于温饱层面&#xff0c;越来越多的人们开始追求文化、艺术的高层次需求&#xff0c;旅游也逐渐成为人们日常放松的一种方式。由于我国人口多、易扎堆等特点&#xff0c;景区的运营监管方式也亟需改革。TSINGSEE青犀智能分…

118.杨辉三角

一、题目 118. 杨辉三角 - 力扣&#xff08;LeetCode&#xff09; 二、代码 class Solution { public:vector<vector<int>> generate(int numRows) {vector<vector<int>>data(numRows);for(int i0;i<numRows;i){data[i].resize(i1);//扩容data[i]…

java解析html

目录 场景描述一.引入依赖二.调用接口响应回来的html三.测试代码 场景描述 我调用外部接口&#xff0c;但是返回来的数据是html的格式&#xff0c;所以我就需要进行处理来获得我想要的数据。我使用的是jsoup。 一.引入依赖 <dependency><groupId>org.jsoup</gr…

C++:初始化表总结

1.为成员变量赋值2.指定基类的构造函数3.指定组合对象所在类的构造函数

Vue.js安装步骤和注意事项

安装完node.js后开始安装和部署Vue在检查webpack的下载版本时出现错误出现错误的原因是之前下载时未指定对应的版本号导致版本不兼容先卸载掉之前下载的版本 cnpm uninstall webpack-cli -g cnpm install webpack-cli4.9.2 -g 最后检查版本是否对应

【不会用这个工具,你的Linux服务器就是个摆设!】

01 Tcpdump Tcpdump 是一个强大的网络监控工具&#xff0c;它允许用户有效地过滤网络上的数据包和流量。 这可以获得有关 TCP/IP 和网络上传输的数据包的详细信息。 当你遇到网络协议问题一筹莫展的时候&#xff0c;这时候往往可以通过tcpdump来看网络的通讯过程中发生了什么…

Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin

Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片&#xff0c;Kotlin <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name"android.permission.RE…