飞道的博客

TensorFlow2 入门指南 | 04 分类问题实战之手写数字识别

314人阅读  评论(0)

前言:

本专栏在保证内容完整性的基础上,力求简洁,旨在让初学者能够更快地、高效地入门TensorFlow2 深度学习框架。如果觉得本专栏对您有帮助的话,可以给一个大大的三连,各位的支持将是我创作的最大动力!

一、分类问题简介

在前面两篇博客中已经介绍了用于连续值预测的线性回归模型,这一讲我们来学习分类问题。图像分类问题就是一个典型的分类问题,这也是计算机视觉中的基本任务之一。它的目标就是教会机器或者电脑学习如何去自动识别图像中物体的种类。

二、手写数字识别简介

手写数字识别是一个非常经典的图像分类任务,经常被作为深度学习入门的第一个指导案例。相当于我们学编程语言时,编写的第一个程序“Hello World !”。手写数字识别是基于MNIST数据集的一个图像分类任务,目的是通过搭建深度神经网络,实现对手写数字的识别(分类)。

MNIST数据集是由Lecun等人在1998年创建的,它包含了 0~9 共 10 种数字的手写图片,每种数字一共有 7000 张图片,采集自不同书写风格的真实手写图片,一共 70000 张图片。其中60000张图片作为训练集,用来训练模型。10000张图片作为测试集,用来训练或者预测。训练集和测试集共同组成了整个 MNIST 数据集。

MINIST数据集中的每张图片,大小为28 × 28,同时只保留灰度信息(即单通道)。下图是MNIST数据集中的部分图片:

三、面对初学者的实现方法

为了大家更快的入门,下面我将展示一个简单的入门案例——用TensorFlow2实现手写数字识别。对于初学者,我建议使用tf.keras的高层API接口进行实现,这样代码会更简洁,更容易上手。具体步骤如下:

(1)导入库

import tensorflow as tf  # 导入TF库
from tensorflow.keras import datasets, Sequential, layers  # 导入TF子库

(2)数据集准备

(x_train, y_train), (x_test, y_test) = datasets.mnist.load_data()   # 加载数据集,返回的是两个元组,分别表示训练集和测试集
x_train, x_test = x_train / 255.0, x_test / 255.0  # 归一化,将像素值缩放到0~1

(3)模型搭建

network = Sequential([
    layers.Flatten(input_shape=(28, 28)),
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.2),
    layers.Dense(10, activation='softmax')
])

(4)模型装配与训练,并验证模型

# 模型装配
network.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# 模型训练
network.fit(x_train, y_train, epochs=5)
# 验证模型
network.evaluate(x_test, y_test, verbose=2)

训练过程以及测试结果:


结果分析:
对mnist数据集训练完5个epos后,模型在验证集上的分类准确度达到97.68%。


这里是一段防爬虫文本,请读者忽略。 本文原创首发于 CSDN,作者【AI 菌】。
博客首页:https://blog.csdn.net/wjinjie
本文链接:https://ai-wx.blog.csdn.net/article/details/115587155
未经授权,禁止转载!恶意转载,后果自负!尊重原创,远离剽窃!


四、面对进阶者的实现方法

对于已有一定TensorFlow基础的同学,我建议使用相对底层的方式去实现。这样代码虽然显得冗长,但是操作会更灵活,更有助于我们进行更深入的学习。具体步骤如下:

(1)导入库

import tensorflow as tf  # 导入TF库
from tensorflow.keras import datasets, layers, Model, losses, optimizers, metrics # 导入TF子库

(2)数据集准备

# 加载数据集,返回的是两个元组,分别表示训练集和测试集
(x_train, y_train), (x_test, y_test) = datasets.mnist.load_data()  
# 归一化,将像素值缩放到0~1
x_train = tf.convert_to_tensor(x_train, dtype=tf.float32)/255.  
x_test = tf.convert_to_tensor(x_test, dtype=tf.float32)/255.
# 使用 tf.data 来将数据集切分为 batch个一组,并对数据集进行打乱
train_ds = tf.data.Dataset.from_tensor_slices((x_train, y_train)).shuffle(10000).batch(32)
test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)

(3)使用类构建网络模型

class Network(Model):
    def __init__(self):
        super(Network, self).__init__()
        self.conv1 = layers.Conv2D(32, 3, activation='relu')
        self.flatten = layers.Flatten()
        self.fc1 = layers.Dense(128, activation='relu')
        self.fc2 = layers.Dense(10, activation='softmax')

    def call(self, x):
        x = tf.reshape(x, (-1, 28, 28, 1))
        x = self.conv1(x)
        x = self.flatten(x)
        x = self.fc1(x)
        y = self.fc2(x)
        return y
network = Network()  # 实例化

(4)模型的装配

这个部分主要涉及损失函数、优化器、评价标准的选择和构建

# 确定目标损失函数、优化器、评价标准
loss_object = losses.SparseCategoricalCrossentropy()
optimizer = optimizers.Adam()
# 训练集上的损失值、精确度
train_loss = metrics.Mean(name='train_loss')
train_accuracy = metrics.SparseCategoricalAccuracy(name='train_accuracy')
# 测试集上的损失值、精确度
test_loss = metrics.Mean(name='test_loss')
test_accuracy = metrics.SparseCategoricalAccuracy(name='test_accuracy')

(5)训练与测试函数的构建

# 训练
def train_step(images, labels):
    with tf.GradientTape() as tape:  # 建立梯度环境
        predictions = network(images)  # 前向计算
        loss = loss_object(labels, predictions)  # 计算损失
    gradients = tape.gradient(loss, network.trainable_variables)  # 计算网络中各个参数的梯度
    optimizer.apply_gradients(zip(gradients, network.trainable_variables))  # 更新网络参数
    train_loss(loss)  # 计算训练损失
    train_accuracy(labels, predictions)  # 计算训练精确度

# 测试
def test_step(images, labels):
    predictions = network(images)  # 前向计算
    t_loss = loss_object(labels, predictions)  # 计算当前轮上的损失
    test_loss(t_loss)  # 计算测试集上的损失
    test_accuracy(labels, predictions)  # 计算测试集上的准确率

(6)迭代训练并验证模型

for epoch in range(EPOCHS):
    # 在下一个epoch开始时,重置评估指标:所有损失值、精确度清零
    train_loss.reset_states()
    train_accuracy.reset_states()
    test_loss.reset_states()
    test_accuracy.reset_states()
    # 训练
    for images, labels in train_ds:
        train_step(images, labels)
    # 测试
    for test_images, test_labels in test_ds:
        test_step(test_images, test_labels)
        print('Accuracy:{}'.format(test_accuracy.result()))
    # 打印训练结果
    template = 'Epoch {}, Loss: {}, Accuracy: {}, Test Loss: {}, Test Accuracy: {}'
    print(template.format(epoch+1,
                          train_loss.result(), train_accuracy.result(),
                          test_loss.result(), test_accuracy.result()))

训练过程以及测试结果:


结果分析:
对mnist训练集玩5个epos后,模型在训练集上的分类准确度达到99.69%,测试集上的分类准确度达到98.43%。


完整代码已经上传github仓库:https://github.com/Keyird/TensorFlow2-for-beginner
如果对你有帮助的话,欢迎star收藏~

最好的关系是互相成就,各位的「三连」就是【AI 菌】创作的最大动力,我们下期见!


转载:https://blog.csdn.net/wjinjie/article/details/115587155
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场