python与深度学习(五):CNN和手写数字识别

news2024/12/23 16:24:53

目录

  • 1. 说明
  • 2. 卷积运算
  • 3. 填充
  • 4. 池化
  • 5. 卷积神经网络实战-手写数字识别的CNN模型
    • 5.1 导入相关库
    • 5.2 加载数据
    • 5.3 数据预处理
    • 5.4 数据处理
    • 5.5 构建网络模型
    • 5.6 模型编译
    • 5.7 模型训练、保存和评价
    • 5.8 模型测试
    • 5.9 模型训练结果的可视化
  • 6. 手写数字识别的CNN模型可视化结果图
  • 7. 完整代码

1. 说明

从这篇文章开始介绍卷积神经网络CNN,CNN比ANN更适用于图片分类问题。

2. 卷积运算

卷积运算的过程如下图所示,灰度图像(可以认为是一个二维矩阵),通过将卷积核从最左上角贴合,然后将对应位置的数进行相乘再相加就得到了特征图的第一个数。
在这里插入图片描述
然后通过移动卷积核,再进行对应位置相乘再相加可以得到特征图的第二个结果,这里步长是1。
卷积核的运动方向是先往右运动,到了末尾,然后再向下移动并且回到开头,然后再继续向右运动,经过如此往复运动可以得到下图结果。
在这里插入图片描述
针对于单通道输入和多核现象,就是用每一个卷积核和单通道图像进行运算,最后得到两个特征图,如下图所示。
在这里插入图片描述
针对于多通道情况,如下图所示。
在这里插入图片描述
多通道的每个通道和卷积核的对应通道进行卷积,然后把所有通道的运算结果进行相加,得到特征图的结果,如下图。
在这里插入图片描述
针对于多通道多核现象,就是将每个卷积核和多通道进行运算得到多个特征图,如下图所示。
在这里插入图片描述
以上均是步长为1的情况,即卷积核每次移动一个像素。如果步长为2,即卷积核每次移动两个像素。

3. 填充

通过上述介绍,我们发现经过多层卷积之后特征图会变得越来越小,会造成信息的缺失,为了降低影响可以进行填充操作,即在特征图的外层加一圈0,然后和卷积核进行运算,如下图所示。
在这里插入图片描述
这时候卷积核的参数padding为same,不进行填充时候为valid,默认为valid。

4. 池化

有时候特征图很大,网络的参数太多,为了降低网络的参数量,采用池化操作。池化可分为最大池化和平均池化。
最大池化,就是对特征图在每个池化区域内找出最大值作为输出结果,如下图。
在这里插入图片描述
平均池化,就是对特征图在每个池化区域内找进行平均运算得到的结果作为输出结果,如下图。
在这里插入图片描述

5. 卷积神经网络实战-手写数字识别的CNN模型

5.1 导入相关库

以下第三方库是python专门用于深度学习的库

from keras.datasets import mnist
import matplotlib.pyplot as plt
from tensorflow import keras
from keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPool2D
from keras.models import Sequential
from keras.callbacks import EarlyStopping
import tensorflow as tf
from keras import optimizers, losses

5.2 加载数据

把MNIST数据集进行加载

"1.加载数据"
"""
x_train是mnist训练集图片,大小的28*28的,y_train是对应的标签是数字
x_test是mnist测试集图片,大小的28*28的,y_test是对应的标签是数字
"""
(x_train, y_train), (x_test, y_test) = mnist.load_data()  # 加载mnist数据集
print('mnist_data:', x_train.shape, y_train.shape, x_test.shape, y_test.shape)  # 打印训练数据和测试数据的形状

5.3 数据预处理

(1) 将输入的图片进行归一化,从0-255变换到0-1;
(2) 将输入图片的形状(60000,28,28)转换成(60000,28,28,1),便于输入给神经网络;
(3) 将标签y进行独热编码,因为神经网络的输出是10个概率值,而y是1个数, 计算loss时无法对应计算,因此将y进行独立编码成为10个数的行向量,然后进行loss的计算 独热编码:例如数值1的10分类的独热编码是[0 1 0 0 0 0 0 0 0 0,即1的位置为1,其余位置为0。

"2.数据预处理"


def preprocess(x, y):  # 数据预处理函数
    x = tf.cast(x, dtype=tf.float32) / 255.  # 将输入的图片进行归一化,从0-255变换到0-1
    x = tf.reshape(x, [28, 28, 1])
    """
    # 将输入图片的形状(60000,28,28)转换成(60000,28,28,1),
    相当于将图片拉直,便于输入给神经网络
    """
    y = tf.cast(y, dtype=tf.int32)  # 将输入图片的标签转换为int32类型
    y = tf.one_hot(y, depth=10)
    """
    # 将标签y进行独热编码,因为神经网络的输出是10个概率值,而y是1个数,
    计算loss时无法对应计算,因此将y进行独立编码成为10个数的行向量,然后进行loss的计算
    独热编码:例如数值1的10分类的独热编码是[0 1 0 0 0 0 0 0 0 0,即1的位置为1,其余位置为0
    """
    return x, y

5.4 数据处理

数据加载进入内存后,需要转换成 Dataset 对象,才能利用 TensorFlow 提供的各种便捷功能。
通过 Dataset.from_tensor_slices 可以将训练部分的数据图片 x 和标签 y 都转换成Dataset 对象

batchsz = 128  # 每次输入给神经网络的图片数
"""
数据加载进入内存后,需要转换成 Dataset 对象,才能利用 TensorFlow 提供的各种便捷功能。
通过 Dataset.from_tensor_slices 可以将训练部分的数据图片 x 和标签 y 都转换成Dataset 对象
"""
db = tf.data.Dataset.from_tensor_slices((x_train, y_train))  # 构建训练集对象
db = db.map(preprocess).shuffle(60000).batch(batchsz)  # 将数据进行预处理,随机打散和批量处理
ds_val = tf.data.Dataset.from_tensor_slices((x_test, y_test))  # 构建测试集对象
ds_val = ds_val.map(preprocess).batch(batchsz)  # 将数据进行预处理,随机打散和批量处理

5.5 构建网络模型

构建了两层卷积层,两层池化层,然后是展平层(将二维特征图拉直输入给全连接层),然后是三层全连接层。

"3.构建网络模型"
model = Sequential([Conv2D(filters=6, kernel_size=(5, 5), activation='relu'),
                    MaxPool2D(pool_size=(2, 2), strides=2),
                    Conv2D(filters=16, kernel_size=(5, 5), activation='relu'),
                    MaxPool2D(pool_size=(2, 2), strides=2),
                    Flatten(),
                    Dense(120, activation='relu'),
                    Dense(84, activation='relu'),
                    Dense(10,activation='softmax')])

model.build(input_shape=(None, 28, 28, 1))  # 模型的输入大小
model.summary()  # 打印网络结构

5.6 模型编译

模型的优化器是Adam,学习率是0.01,
损失函数是losses.CategoricalCrossentropy,
性能指标是正确率accuracy

"4.模型编译"
model.compile(optimizer=optimizers.Adam(lr=0.01),
                loss=tf.losses.CategoricalCrossentropy(from_logits=False),
                metrics=['accuracy']
                )
"""
模型的优化器是Adam,学习率是0.01,
损失函数是losses.CategoricalCrossentropy,
性能指标是正确率accuracy
"""

5.7 模型训练、保存和评价

模型训练的次数是5,每1次循环进行测试;
以.h5文件格式保存模型;
得到测试集的正确率。

"5.模型训练"
history = model.fit(db, epochs=5, validation_data=ds_val, validation_freq=1)
"""
模型训练的次数是5,每1次循环进行测试
"""
"6.模型保存"
model.save('cnn_mnist.h5')  # 以.h5文件格式保存模型

"7.模型评价"
model.evaluate(ds_val)  # 得到测试集的正确率

5.8 模型测试

对模型进行测试

"8.模型测试"
sample = next(iter(ds_val))  # 取一个batchsz的测试集数据
x = sample[0]  # 测试集数据
y = sample[1]  # 测试集的标签
pred = model.predict(x)  # 将一个batchsz的测试集数据输入神经网络的结果
pred = tf.argmax(pred, axis=1)  # 每个预测的结果的概率最大值的下标,也就是预测的数字
y = tf.argmax(y, axis=1)  # 每个标签的最大值对应的下标,也就是标签对应的数字
print(pred)  # 打印预测结果
print(y)  # 打印标签数字

5.9 模型训练结果的可视化

对模型的训练结果进行可视化

"9.模型训练时的可视化"
# 显示训练集和验证集的acc和loss曲线
acc = history.history['accuracy']  # 获取模型训练中的accuracy
val_acc = history.history['val_accuracy']  # 获取模型训练中的val_accuracy
loss = history.history['loss']  # 获取模型训练中的loss
val_loss = history.history['val_loss']  # 获取模型训练中的val_loss
# 绘值acc曲线
plt.figure(1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()
# 绘制loss曲线
plt.figure(2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()  # 将结果显示出来

6. 手写数字识别的CNN模型可视化结果图

Epoch 1/5
469/469 [==============================] - 12s 22ms/step - loss: 0.1733 - accuracy: 0.9465 - val_loss: 0.0840 - val_accuracy: 0.9763
Epoch 2/5
469/469 [==============================] - 11s 21ms/step - loss: 0.0704 - accuracy: 0.9793 - val_loss: 0.0581 - val_accuracy: 0.9819
Epoch 3/5
469/469 [==============================] - 11s 22ms/step - loss: 0.0566 - accuracy: 0.9833 - val_loss: 0.0576 - val_accuracy: 0.9844
Epoch 4/5
469/469 [==============================] - 11s 22ms/step - loss: 0.0573 - accuracy: 0.9833 - val_loss: 0.0766 - val_accuracy: 0.9784
Epoch 5/5
469/469 [==============================] - 11s 22ms/step - loss: 0.0556 - accuracy: 0.9844 - val_loss: 0.0537 - val_accuracy: 0.9830

在这里插入图片描述
在这里插入图片描述
从以上结果可知,模型的准确率达到了98%。

7. 完整代码

from keras.datasets import mnist
import matplotlib.pyplot as plt
from tensorflow import keras
from keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPool2D
from keras.models import Sequential
from keras.callbacks import EarlyStopping
import tensorflow as tf
from keras import optimizers, losses
"1.加载数据"
"""
x_train是mnist训练集图片,大小的28*28的,y_train是对应的标签是数字
x_test是mnist测试集图片,大小的28*28的,y_test是对应的标签是数字
"""
(x_train, y_train), (x_test, y_test) = mnist.load_data()  # 加载mnist数据集
print('mnist_data:', x_train.shape, y_train.shape, x_test.shape, y_test.shape)  # 打印训练数据和测试数据的形状

"2.数据预处理"


def preprocess(x, y):  # 数据预处理函数
    x = tf.cast(x, dtype=tf.float32) / 255.  # 将输入的图片进行归一化,从0-255变换到0-1
    x = tf.reshape(x, [28, 28, 1])
    """
    # 将输入图片的形状(60000,28,28)转换成(60000,28,28,1),
    相当于将图片拉直,便于输入给神经网络
    """
    y = tf.cast(y, dtype=tf.int32)  # 将输入图片的标签转换为int32类型
    y = tf.one_hot(y, depth=10)
    """
    # 将标签y进行独热编码,因为神经网络的输出是10个概率值,而y是1个数,
    计算loss时无法对应计算,因此将y进行独立编码成为10个数的行向量,然后进行loss的计算
    独热编码:例如数值1的10分类的独热编码是[0 1 0 0 0 0 0 0 0 0,即1的位置为1,其余位置为0
    """
    return x, y


batchsz = 128  # 每次输入给神经网络的图片数
"""
数据加载进入内存后,需要转换成 Dataset 对象,才能利用 TensorFlow 提供的各种便捷功能。
通过 Dataset.from_tensor_slices 可以将训练部分的数据图片 x 和标签 y 都转换成Dataset 对象
"""
db = tf.data.Dataset.from_tensor_slices((x_train, y_train))  # 构建训练集对象
db = db.map(preprocess).shuffle(60000).batch(batchsz)  # 将数据进行预处理,随机打散和批量处理
ds_val = tf.data.Dataset.from_tensor_slices((x_test, y_test))  # 构建测试集对象
ds_val = ds_val.map(preprocess).batch(batchsz)  # 将数据进行预处理,随机打散和批量处理

"3.构建网络模型"
model = Sequential([Conv2D(filters=6, kernel_size=(5, 5), activation='relu'),
                    MaxPool2D(pool_size=(2, 2), strides=2),
                    Conv2D(filters=16, kernel_size=(5, 5), activation='relu'),
                    MaxPool2D(pool_size=(2, 2), strides=2),
                    Flatten(),
                    Dense(120, activation='relu'),
                    Dense(84, activation='relu'),
                    Dense(10,activation='softmax')])

model.build(input_shape=(None, 28, 28, 1))  # 模型的输入大小
model.summary()  # 打印网络结构

"4.模型编译"
model.compile(optimizer=optimizers.Adam(lr=0.01),
                loss=tf.losses.CategoricalCrossentropy(from_logits=False),
                metrics=['accuracy']
                )
"""
模型的优化器是Adam,学习率是0.01,
损失函数是losses.CategoricalCrossentropy,
性能指标是正确率accuracy
"""

"5.模型训练"
history = model.fit(db, epochs=5, validation_data=ds_val, validation_freq=1)
"""
模型训练的次数是5,每1次循环进行测试
"""
"6.模型保存"
model.save('cnn_mnist.h5')  # 以.h5文件格式保存模型

"7.模型评价"
model.evaluate(ds_val)  # 得到测试集的正确率

"8.模型测试"
sample = next(iter(ds_val))  # 取一个batchsz的测试集数据
x = sample[0]  # 测试集数据
y = sample[1]  # 测试集的标签
pred = model.predict(x)  # 将一个batchsz的测试集数据输入神经网络的结果
pred = tf.argmax(pred, axis=1)  # 每个预测的结果的概率最大值的下标,也就是预测的数字
y = tf.argmax(y, axis=1)  # 每个标签的最大值对应的下标,也就是标签对应的数字
print(pred)  # 打印预测结果
print(y)  # 打印标签数字

"9.模型训练时的可视化"
# 显示训练集和验证集的acc和loss曲线
acc = history.history['accuracy']  # 获取模型训练中的accuracy
val_acc = history.history['val_accuracy']  # 获取模型训练中的val_accuracy
loss = history.history['loss']  # 获取模型训练中的loss
val_loss = history.history['val_loss']  # 获取模型训练中的val_loss
# 绘值acc曲线
plt.figure(1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()
# 绘制loss曲线
plt.figure(2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()  # 将结果显示出来

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

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

相关文章

HideSeeker论文阅读

文章目录 3.1 Overview of Our System HideSeeker3.2 Visual Information Extraction3.3 Relation Graph Learning3.4 Hidden Object Inference 4 EVALUATIONS4.7 Summary 6 DISCUSSIONS AND CONCLUSION 3.1 Overview of Our System HideSeeker 我们设计了一种名为“HideSeeke…

【Selenium+Pytest+allure报告生成自动化测试框架】附带项目源码和项目部署文档

目录 前言 【文章末尾给大家留下了大量的福利】 测试框架简介 首先管理时间 添加配置文件 conf.py config.ini 读取配置文件 记录操作日志 简单理解POM模型 简单学习元素定位 管理页面元素 封装Selenium基类 创建页面对象 简单了解Pytest pytest.ini 编写测试…

保护数字世界的壁垒

随着科技的不断发展和互联网的普及,我们的生活日益依赖于数字化的世界。然而,随之而来的是网络安全威胁的不断增加。网络攻击、数据泄露和身份盗窃等问题已经成为我们所面临的现实。因此,网络安全变得尤为重要,我们需要采取措施来…

MySQL常见的几种约束

系列文章目录 后续补充 文章目录 系列文章目录前言一、主键约束二、非空约束三、唯一约束四、检查约束五、默认值约束六、字段值自动增加约束七、外键约束总结 前言 为防止不符合规范的数据存入数据库,在用户对数据进行插入、修改、删除等操作时,MySQL提…

新架构网易云音乐UI风格大变身,更像Apple Music?

继QQ的NT版本出来后,掀起了一番热潮,不少科技资讯的UP开始评测采用全新架构的QQ的性能以及内存占用情况, 文末中,苏音也提到了,是否在QQ新版本的发布下,会有越来越多的产品向Electron架构靠近?…

优雅的使用CLion开发STM32 2023最新版本~

1.下载资料 一共需要的资料如下 ✈代表需要魔法 没有标注可直接访问 Clion下载链接 cubemx下载链接 mingw 下载连接 ✈安装完直接解压到文件夹 并且把bin文件的路径存入path环境变量 gcc下载链接✈安装完直接解压到文件夹 并且把bin文件的路径存入path环境变量 openocd下…

详细解析黑马微信小程序视频--【思维导图知识范围】

其实总目录集链接在此: 如何0元学微信小程序–【浅入深出系列000】 先列前几辑,后面的更新在 系列000里 专辑及链接难度(五星制)详细解析黑马微信小程序视频–【浅入深出系列-001】难度★✫✰✰✰让别人的小程序长成自己的样子…

仿写SpringMVC中的注解和方法映射功能

本项目已开源,欢迎各位大佬访问并指正:仿写SpringMVC中的注解和方法映射功能 文章目录 一、仿写流程1、初始化2、测试 二、代码实现1、自定义注解Controller和RequestMapping2、扫描本项目下Controller下所有的java文件3、识别注解,完成映射4…

【算组合数】CF1833 F

少见地秒了这道1700,要是以后都这样就好了.... Problem - F - Codeforces 题意: 给定一个数列,让你在这个数列里找一个大小为M的子集,使得极差不超过M 思路: 子集,不是子序列,说明和顺序无…

【算法与数据结构】101、LeetCode对称二叉树

文章目录 一、题目二、递归法三、迭代法三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、递归法 思路分析:这道题目标就是要对比左右两半的树是否对称,因此对比不是左右节点是否相等&…

ThreadPoolExecutor自定义线程池|拒绝策略|线程工厂|统一捕获异常

线程池的7大参数含义介绍 corePoolSize:池中一直保持的线程的数量。 maximumPoolSize:池中允许的最大的线程数。 keepAliveTime:当线程数大于核心线程数的时候,线程在最大多长时间没有接到新任务就会终止释放, 最终…

点击加号添加新的输入框

实现如上图的效果 html部分&#xff1a; <el-form-item class"forminput" v-for"(item,index) in formdata.description" :key"index" :label"描述(index1)" prop"description"><el-input v-model"formdata…

STM32入门之创建工程模板

1.STM32固件库的结构图如下。从图中可以看出&#xff0c;我们在配置STM32的固件库时需要配置用户层、CMSIS层的文件。配置库文件即正确的配置这些函数的文件。CMSIS(Cortex Microcontroller Software Interface Standard)是ARM公司提供的微控制器软件接口标准&#xff0c;所有使…

栈和队列(基础知识和基本操作)

栈&#xff1a; 1.栈&#xff1a;在表尾进行插入和删除的操作受限的线性表。 2.逻辑结构&#xff1a;线性结构【一对一的关系】 3.存储结构&#xff1a;顺序存储【顺序栈】、链式存储【链栈】 4.栈的特点&#xff1a;先进后出【first in last out FILO表】 后进先出【last…

消息队列 CKafka 跨洋数据同步性能优化

导语 本文主要介绍了 CKafka 在跨洋场景中遇到的一个地域间数据同步延时大的问题&#xff0c;跨地域延时问题比较典型&#xff0c;所以详细记录下来做个总结。 一. 背景 为了满足客户跨地域容灾、冷备的诉求&#xff0c;消息队列 CKafka 通过连接器功能&#xff0c;提供了跨…

5.4.tensorRT基础(2)-学习第一个插件的编写

目录 前言1. 插件2. 补充知识总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 基础-学习第一个插件的编写 课程大…

python sorted函数

python列表排序 简单记一下python中List的sort方法&#xff08;或者sorted内建函数&#xff09;的用法。 关键字&#xff1a; python列表排序 python字典排序 sorted List的元素可以是各种东西&#xff0c;字符串&#xff0c;字典&#xff0c;自己定义的类等。 sorted函数用法如…

【项目 进程6】 2.13 匿名管道通信案例 2.14管道的读写特点和管道设置为非阻塞

文章目录 2.13 匿名管道通信案例匿名管道的使用实现 ps aux | grep xxx 父子进程间通信 2.14管道的读写特点和管道设置为非阻塞管道的读写特点&#xff1a;总结设置管道非阻塞 2.13 匿名管道通信案例 匿名管道的使用 一般匿名管道不推荐父进程与子进程交叉读写数据&#xff0c…

nginx 配置 wss加密访问 mqtt

1. 在服务器上部署mqtt服务 2.在宝塔上配置域名证书 3.nginx配置websocket server {listen 80;listen 443 ssl http2;server_name ws-xx.example.com;index index.php index.html index.htm default.php default.htm default.html;root /www/wwwroot/ws-xx.example.com;loca…

金融软件技术:创新与安全并行驶

随着科技的迅速发展&#xff0c;金融行业正经历着一场前所未有的数字化转型。金融机构需要不断创新和提升效率&#xff0c;以满足客户需求&#xff0c;并保持竞争优势。在这个数字时代中&#xff0c;金融软件技术成为了实现这一目标的关键要素。本文将从两个方面探讨金融软件技…