基于CNn的MINIST手写体识别

深度学习的上机作业:

        基于CNN卷积神经网络的MINIST手写体识别

        版本:python-3.9,tensorflow-2.9

目录

MINIST数据集

训练CNN卷积神经网络

使用训练好的模型进行预测

识别自己手写的数字


写这篇文章为了讲一个故事:

        老师布置了一个上机作业,建议参照着书上的代码进行完成,但书上的代码是四年前的,tensorflow已经大变样了,然后我浪费了两天的时间来改Bug与兼容,最终选择照着官方文档写2.0-tensorflow的故事。


MINIST数据集

由很多人手写的数字构成,分为训练集与测试集

训练集: 有6万张图片,每张图片大小28x28,同时有对应数量的标签(就是每张图片对应的数字)

测试集: 与训练集相比,其他一样,就是图片只有1万张

我们可以看看测试集的大小与部分图片

代码:

import tensorflow as tf
import matplotlib.pyplot as plt

# 导入数据集
mnist = tf.keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
print("训练集样本及标签", train_images.shape, train_labels.shape)
print("测试集样本及标签", test_images.shape, test_labels.shape)
train_images, test_images = train_images / 255.0, test_images / 255.0  # 归一化,不然梯度爆炸
# 进行绘画
for i in range(15):
    plt.subplot(3, 5, i + 1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(test_images[i])
    plt.xlabel(test_labels[i])
plt.show()

数据集大小:

MNIST数据集大小
MNIST数据集大小

图像:

部分MNIST图片
运行结果:图像


训练CNN卷积神经网络

如果看这篇文章是为了完成实验报告,就用这里的代码就行

        这个代码是不是看着比书(深度学习之美)上的示例代码简洁?这就是tensorflow在四年的发展,它从原来的偏向底层的代码变成现在这种高度集成的框架,但没有书上那样可以清楚的知道底层是如何实现的。

        我将讲解这个代码所定义的神经网络模型,

        (与书上唯一不同的就是全连接层的神经元为64个)。

  1. 第一层为卷积层,32卷积核(即32输出通道),卷积核大小5x5,激活函数Relu,零值等大填充
  2. 第二层为池化层,2x2最大值池化
  3. 第三层为卷积层,卷积核大小5x5,64个输出通道
  4. 第四层为池化层,仍为2x2最大池化
  5. 第五层为扁平化层,将输入的二维张量拉成一维,便于输入给全连接层
  6. 第六层为全连接层,与书上不同,这里是64个神经元(因为我的电脑内存不大)
  7. 第七层为Dropout层,随机丢掉一些全连接层的神经元,以避免过拟合
  8. 第八层,即最后一层,为输出层,输出独热编码

代码:(最后一行是自己的文件路径)

import tensorflow as tf

"""
教材(深度学习之美)上所使用的tensorflow十分的古老,
其版本是Python-3.6,tensorflow-1.7,
许多api现已不支持,而我们要拥抱新技术

当前版本:python-3.9,tensorflow-2.9
"""

# 导入数据集
mnist = tf.keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
print("训练集样本及标签", train_images.shape, train_labels.shape)
print("测试集样本及标签", test_images.shape, test_labels.shape)
train_images, test_images = train_images / 255.0, test_images / 255.0  # 归一化,不然梯度爆炸

# 建立各层神经网络
model = tf.keras.models.Sequential()  # 建立一个堆叠层的神经网络
# 第一卷积层,32卷积核(即32输出通道),卷积核大小5x5,使用Relu激活函数,零值等大填充,输入张量形状28x28,色彩通道为1(即黑白图片)
model.add(tf.keras.layers.Conv2D(32, (5, 5), activation='relu', padding='same', input_shape=(28, 28, 1)))
# 2x2的最大值池化
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
# 第二卷积层,64个输出通道,输入通道这里就不用指定,可以自动承接前一层的
model.add(tf.keras.layers.Conv2D(64, (5, 5), activation='relu', padding='same'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
# 扁平化,将二维的张量变成一维,这里28x28经过两次2x2池化,已是7x7大小,现在变成49
model.add(tf.keras.layers.Flatten())
# 全连接层,64个神经元
model.add(tf.keras.layers.Dense(64, activation='relu'))
# dropout层,损失函数0.5
model.add(tf.keras.layers.Dropout(0.5))
# Readout层,输出独热编码
model.add(tf.keras.layers.Dense(10))  # 最后输出10个数

# 编译模型
model.compile(optimizer='adam',  # Adam优化器
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),  # 损失函数
              metrics=['accuracy'])  # 监控指标:精度
# 开始训练,训练周期8,即将所有训练样本(6万个),遍历八遍,因为输入通道是32个,所以每遍训练1875次,每次32个
model.fit(train_images, train_labels, epochs=8, validation_data=(test_images, test_labels))

# 训练完毕,使用测试集来评估模型精度
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\n最终测试集上的精度为:', test_acc)

# 保存模型
model.save("../兼收并蓄/CNN模型")  # 这是自定义的路径,删除"/兼收并蓄"即可直接运行

运行结果:

在训练集上训练了15000次,每次32张图片,最终在测试集上的精度为: 0.9934


使用训练好的模型进行预测

好不容易将模型训练完了,怎么能够不去使用?

从文件夹读取出模型,开始预测,看看自己亲手训练出的成果如何。

(这里应该将图片给显示出来才直观,但是那样意义不大,只看标签也够了)

代码:

import tensorflow as tf

# 导入数据集
mnist = tf.keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
# 加入待预测的图像及其标签
show_images, show_labels = test_images[0:20], test_labels[0:20]
print("所选取的测试集图片的标签is:", show_labels)
# 引入模型
model = tf.keras.models.load_model("../兼收并蓄/CNN模型")
# 开始预测
predictions = model.predict(show_images)
# 预测完成
predictions_num = tf.argmax(predictions, 1)
# 输出预测标签
print("所预测的标签为:", predictions_num)

运行结果:

(可以看到训练20个图像,全部都预测对了)

模型预测结果


识别自己手写的数字

好不容易训练的模型,应该自己体验一番,自己画一个数字,看看是否能够识别

 首先打开画图,将图像设置为28x28的黑白图像(打开画图-->文件-->图像属性)

(其实不设也行,但那样不能保证精度)

画图设置
画图设置

 然后画一个黑底白字的数字,保存为png文件(我这里起名“御笔亲题之作”)

(这个时候可能看不清画布,用画图的放大镜点几下就好了)

所画图像
御笔亲题之作

然后通过tf.io进行读取,并转化成numpy数组

代码

import tensorflow as tf

# 读取一张自己手写的图片
img_01 = tf.io.read_file("../兼收并蓄/御笔亲题之作.png")  # 要黑白图片
img02 = tf.io.decode_png(img_01, channels=1)
img03 = tf.image.resize(img02, [28, 28])
img = (img03.numpy()).reshape([1, 28, 28])
print("图片转化之后的形状为:", img.shape)
# 运用模型进行预测
model = tf.keras.models.load_model("../兼收并蓄/CNN模型")
predictions = model.predict(img)
predictions_num = tf.argmax(predictions, 1)
print("你的模型认为该数字为:", predictions_num.numpy())

 运行结果

运行结果
运行结果


  • 21
    点赞
  • 144
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
TensorFlow是一个广泛应用于机器学习和深度学习的开源框架,也可以用于手写字体识别任务。手写字体识别是指将手写的字符转换为可识别的文本形式,常用于识别手写字体的数字、字母和汉字等。 在TensorFlow中,可以使用卷积神经网络CNN)来进行手写字体识别。首先,需要准备一个手写字体数据集,包含大量的手写字符样本。然后,使用TensorFlow的图像处理功能将手写字符样本进行预处理,将其转换为标准大小的图像。 接下来,可以利用TensorFlow的深度学习模型构建和训练一个卷积神经网络。卷积神经网络是一种专门用于处理图像识别任务的神经网络模型,通过多层的卷积、池化和全连接层,可以高效地提取并学习图像的特征。 在训练过程中,可以使用TensorFlow提供的优化算法和损失函数来使得模型逐渐收敛,并能够正确地识别手写字体。通过反复迭代和不断调整模型参数,可以提高模型在手写字体识别任务上的准确率。 最后,当模型训练完成后,就可以将其应用于实际的手写字体识别场景中。只需将待识别手写字符输入到经过训练的模型中,即可输出对应的文本标识,实现手写字体识别的功能。 总而言之,利用TensorFlow进行手写字体识别可以通过构建和训练卷积神经网络模型实现。这种方法可以提高手写字体识别的准确率和效率,并可以应用于各种实际场景中。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值