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

目录

  • 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()  # 将结果显示出来

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数学建模学习(2):数学建模各类常用的算法全解析

一、评价类算法 常见的评价算法 1.层次分析法 基本思想 是定性与定量相结合的多准则决策、评价方法。将决策的有关元素分解成 目标层、准则层和方案层 ,并通过人们的 判断对决策方案的 优劣进行排序 ,在此基础上进行定性和定量分析。它把人的思维过程…

AWS IAM介绍

前言 AWS是世界上最大的云服务提供商,它提供了很多组件供消费者使用,其中进行访问控制的组件叫做IAM(Identity and Access Management), 用来进行身份验证和对AWS资源的访问控制。 功能 IAM的功能总结来看,主要分两种&#xff1…

【代码随想录day20】二叉搜索树的最小绝对差

题目 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数,其数值等于两值之差的绝对值。 思路 最简单的一个思路是使用中序遍历,从二叉排序树中得到有序序列,存储到self.elem中&…

Mac苹果系统安装双系统Windows10 Windows11 BOOTCAMP

Mac系统安装双系统Windows10 BOOTCAMP详细 1.下载Windows系统2.开始安装3.安装驱动4.默认启动5.备注 1.下载Windows系统 注意一下所有安装全程接充电器操作,以免安装过程中电脑断电带来不必要影响。 从下列方式选择合适的系统进行下载。 MSDN https://msdn.itelly…

【code】使用git将本地代码托管至码云

创建远程仓库 在码云(gitee.com)网站上登录你的账号,然后点击页面右上角的加号图标,选择"新建仓库",填写仓库名称、描述等信息,创建一个新的远程仓库。 生成SSH密钥 在Git上传代码到远程仓库…

p7付费课程笔记5:串行gc以及并行gc

前言 前段时间我们学习jvm的基础结构和gc相关的基础知识,今天我们详细讲讲几大gc。 串行gc 串行 GC 对年轻代使用 mark-copy (标记-复制) 算法,对老年代使用 mark-sweep-compact (标记-清除-整理) 算法。 两者都是单线程的垃圾收集器,不能…

windows 系统安装sonarqube

SonarQube是一种自动代码审查工具,用于检测代码中的错误,漏洞和代码异味。它可以与您现有的工作流程集成,以便在项目分支和拉取请求之间进行连续的代码检查。 官方网站: https://www.sonarqube.org/ 1. 使用前提条件 运行SonarQ…

FCPX插件-15组金色华丽粒子特效闪耀动画 Awards Backgrounds

Awards Backgrounds是fcpx上一个很棒的电影级效果插件,Awards Backgrounds 包含15组金色华丽粒子特效闪耀动画,可以为您的作品创建豪华的背景或叠加特效!包含各种带有可编辑颜色的下落闪闪发光粒子的场景。用于展示奖项提名者、优雅的表演、祝…

【历史上的今天】7 月 24 日:Caldera 诉微软案;AMD 宣布收购 ATI;谷歌推出 Chromecast

整理 | 王启隆 透过「历史上的今天」,从过去看未来,从现在亦可以改变未来。 今天是 2023 年 7 月 24 日,在 1951 年的今天,晶体管发明家 John Bardeen 通知 AT&T 贝尔实验室,他将离开公司,与 Walter B…

数据结构【数组、串、广义表】

第四章 数组、串、广义表 一、数组 1.概念:线性表是通过数组实现的,数组是线性表的推广,数组只有存取元素和修改元素的操作(除了初始化和销毁); 2.数组的存储结构:一个数组的所有元素在内存中占…

动手学DL——深度学习预备知识随笔【深度学习】【PyTorch】

文章目录 2、预备知识2.1、数据操作2.2、线性代数&矩阵计算2.3、导数2.4、基础优化方法 2、预备知识 2.1、数据操作 batch:以图片数据为例,一次读入的图片数量。 小批量样本可以充分利用GPU进行并行计算提高计算效率。 数据访问 数组:np…

Java运算符

大体上,与C语言差不多,不同的地方,我用红色字体标注了 算术运算符 1. 基本四则运算符:加减乘除模 ( - * / %) int a 10 ; int b 20 ; System . out . println ( a b ); // 30 System . out . println ( a - b…

二十三种设计模式第十八篇--责任链模式

责任链模式是一种行为型设计模式,它允许你将请求沿着处理者链传递,直到有一个处理者能够处理该请求为止。责任链模式将请求发送者和请求处理者解耦,从而使得多个处理者都有机会处理同一个请求。 该模式包含以下几个关键角色: 抽象…

macOS 源码编译 qpress

╰─➤ git clone https://github.com/PierreLvx/qpress.git ╰─➤ cd qpress ╰─➤ make g -O3 -o qpress -x c quicklz.c -x c qpress.cpp aio.cpp utilities.cpp -lpthread -Wall -Wextra -Werror ╰─➤ sudo make install …

k8s deployment(k8s经典版)|PetaExpress

Deployment是什么? Deployment是指在软件开发中将应用程序或系统部署到目标环境中的过程。它包括将代码编译、配置、打包并安装到目标服务器或设备上的步骤。k8s deployment是(k8s经典版)中用来管理发布的控制器,在开发的过程中使…

Ubuntu18.04系统安装视频剪辑软件shotcut

Snap Store安装 使用的是最新的Ubuntu 18.04 LTS(Bionic Beaver),其本身已安装Snap 如果没有安装,则可以使用以下命令安装SNAP $ sudo apt-get install snapd安装shotcut $ sudo snap install shotcut --classic启动shotcut $…

读kafka生产端源码,窥kafka设计之道(下)

背景 在上一篇文章《读kafka生产端源码,窥kafka设计之道(上)》 留下了kafka设计上比较优秀的一个点;内存的循环使用。本篇文章准备盘盘它。 好奇 为什么 kafka减少发送消息时向JVM频繁申请内存,就可以降低JVM GC的执…

【深度学习之YOLO8】视频流推断

官方V8模型下载 需要准备两个东西 simsun.ttc字体包YOLOv8官方模型成品 ScreenCapture屏幕图像类 import cv2 import mss import numpy as npclass ScreenCapture:"""parameters----------screen_resolution : Tuple[int, int]屏幕宽高,分别为x&a…

最新基于Citespace、vosviewer、R语言的文献计量学可视化分析技术及全流程文献可视化SCI论文高效写作方法

文献计量学是指用数学和统计学的方法,定量地分析一切知识载体的交叉科学。它是集数学、统计学、文献学为一体,注重量化的综合性知识体系。特别是,信息可视化技术手段和方法的运用,可直观的展示主题的研究发展历程、研究现状、研究…

2023年Q2京东小家电市场数据分析(京东数据运营)

伴随人们对生活品质追求的提高,以及拥有新兴消费理念的年轻人逐渐成为消费主力,功能新潮、外观精致的小家电经常在电商平台销售榜单里“榜上有名”。本期我们便一起来分析Q2京东小家电市场中,一些较为热门的精致生活小电的行业大盘变动情况。…