卷积神经网络(CNN)实现mnist手写数字识别学习

活动地址:CSDN21天学习挑战赛

一、前期工作

我的环境

语言环境:python 3.7
编译器:pycharm + jupyter notebook
深度学习环境: tensorflow2

1、设置GPU(使用CPU可以忽略这一步)**

import tensorflow as tf
gpus = tf.config.list_physical_devices("GPU")

if gpus:
    gpu0 = gpus[0] #如果有多个GPU,仅使用第0个GPU
    tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpu0],"GPU")

2、导入数据

import tensorflow as tf
from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt

(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()
# 数据存放在 C:\Users\用户名\.keras\datasets
# 或者指定路径存放
# path = r"E:\practice\tf2\mnist.npz" # 修改为数据实际路径
# (train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data(path)

数据集简介:

Mnist数据集分为两部分,分别含有60000张训练图片和10000张测试图片。

图像是28像素 * 28像素,Mnist数据集把代表一张图片的二维数据转开成一个向量,长度为28*28=784。因此在Mnist的训练数据集中mnist.train.images是一个形状为[60000, 784]的张量,第一个维度数字用来索引图片,第二个维度数字用来索引每张图片中的像素点,图片里的某个像素的强度值介于0-1之间。

Mnist数据集中的标签是介于0~9的数字,Mnist中的标签是用独热编码(one-hot-vectors)表示的,一个one-hot向量除了某一位数字是1以外,其余维度的数组都是0,比如标签0用独热编码表示为([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]),标签3用独热编码表示为([0, 0, 0, 1, 0, 0, 0, 0, 0, 0])。所以,Mnist数据集中所有的标签mnist.train.labels是一个[60000, 10]的数字矩阵。

3、归一化

# 将像素的值标准化至0到1的区间内。
train_images, test_images = train_images / 255.0, test_images / 255.0

train_images.shape,test_images.shape,train_labels.shape,test_labels.shape
"""
输出:((60000, 28, 28), (10000, 28, 28), (60000,), (10000,))
"""

归一化的意义:

  • 经过标准化处理后,原始数据转化为无量纲化指标测评值,各指标值处于同一数量级别,可进行综合测评分析。

  • 如果直接用原始指标值进行分析,就会突出数值较高的指标在综合分析中的作用,相对削弱数值水平较低指标的作用。

  • 避免数值问题:太大的数会引发数值问题。

  • 平衡各特征的贡献

归一化的方法:

  • Min-Max标准化

x = (x - min)/(max - min)

通过对数据的每一个维度的值进行重新调节,使得最终的数据向量落在 [0,1]区间内。

对于图片来说,由于max是255,min是0,也就是直接除以255就可以完成归一化。
代码实现:

# 将像素的值标准化至0到1的区间内。
train_images, test_images = train_images / 255.0, test_images / 255.0

  • 标准差标准化,也叫z-score标准化

x =(x - u)/σ
u是均值 σ是标准差

将数据变换成均值为0,标准差为1的分布(但不一定为正态)。

代码实现:

transforms.Normalize(mean = (0.485, 0.456, 0.406), std = (0.229, 0.224, 0.225))

4、可视化图片

plt.figure(figsize=(20,10))
for i in range(20):
    plt.subplot(5,10,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(train_labels[i])
plt.show()

在这里插入图片描述

5、调整图片格式

#调整数据到我们需要的格式
train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))

train_images.shape,test_images.shape,train_labels.shape,test_labels.shape
"""
输出:((60000, 28, 28, 1), (10000, 28, 28, 1), (60000,), (10000,))
"""

调整数据格式的标准:查看所需模型介绍,查看输入数据的结构即可

二、构建CNN模型

model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),#卷积层1,卷积核3*3
    layers.MaxPooling2D((2, 2)),                   #池化层1,2*2采样
    layers.Conv2D(64, (3, 3), activation='relu'),  #卷积层2,卷积核3*3
    layers.MaxPooling2D((2, 2)),                   #池化层2,2*2采样
    
    layers.Flatten(),                              #Flatten层,连接卷积层与全连接层
    layers.Dense(64, activation='relu'),		   #全连接层,特征进一步提取
    layers.Dense(10)                               #输出层,输出预期结果
])
# 打印网络结构
model.summary()

在这里插入图片描述
conv2d 表示卷积层
MaxPooling2D 表示池化层
dense 表示全连接层
Param 表示每个层数的个数

Param的计算方法如下:

  • (卷积核长度卷积核宽度通道数+1)*卷积核个数

所以:
第一个CONV层,Conv2D(32, kernel_size=(3, 3), input_shape=(28,28,1)),Param=(3 * 3 * 1+1)*32 = 320
第二个CONV层,Conv2D(64, (3, 3), activation=‘relu’),经过第一个层32个卷积核的作用,第二层输入数据通道数为32,Param=(3 * 3 * 32+1)64 = 18496.
dense:因为flatten的作用,输出变成了1600,Dense中有64个卷积核,所以Param=64
(1600+1)= 102464

神经网络结构
在这里插入图片描述
CNN模型结构引自:https://mtyjkh.blog.csdn.net/article/details/116920825

三、编译模型

"""
这里设置优化器、损失函数以及metrics
"""
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

四、训练模型

"""
这里设置输入训练数据集(图片及标签)、验证数据集(图片及标签)以及迭代次数epochs
"""
history = model.fit(train_images, train_labels, epochs=10, 
                    validation_data=(test_images, test_labels))

在这里插入图片描述

五、预测

plt.imshow(test_images[1])

在这里插入图片描述

pre = model.predict(test_images) # 对所有测试图片进行预测
pre[1] # 输出第一张图片的预测结果

在这里插入图片描述
或者

pre = model.predict(test_images)
pre.argmax(1) # 利用argmax函数直接调出预测值

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值