今儿准备和大家一起实现一个开源且重要的项目:MNIST数字分类机器学习。
大概介绍下:MNIST数字分类项目旨在使用机器学习技术来构建一个模型,能够自动识别手写数字的图像。这个项目是一个经典的图像分类任务,常用于入门级机器学习和深度学习示例。我们会使用MNIST数据集,这个数据集包含了一系列28x28像素的手写数字图像,从0到9。项目的目标是训练一个模型,能够准确地将这些手写数字图像分类到正确的数字标签。
老规矩:大家伙如果觉得近期文章还不错!欢迎大家点个赞、转个发,让更多的朋友看到。
数据集
简单介绍一下MNIST数据集,它是机器学习领域中最常用的数据集之一。
包含了60000张训练图像和10000张测试图像,每张图像都是28x28像素的灰度图像。每个图像都与一个0到9的数字标签相关联,表示图像中包含的手写数字。
这个数据集是一个非常适合用于图像分类任务的基准数据集。
涉及的算法
手写数字识别是一个典型的图像分类任务,常用于演示和教学机器学习和深度学习的基本概念。
对于使用 MNIST 数据集进行手写数字识别,以下几种算法是最合适的:
- 卷积神经网络 (CNN):这是最适合图像分类任务的算法之一。CNN通过学习图像中的局部模式(如边缘和纹理)逐渐构建出更复杂的图像特征,使其在图像识别任务中表现出色。
- 多层感知器 (MLP):这是一种基本的前馈神经网络,由多个层次的全连接层组成。虽然它不如 CNN 专门化,但对于 MNIST 这种相对简单的图像数据集而言,MLP 通常可以达到相当不错的效果。
- 支持向量机 (SVM):在深度学习兴起之前,SVM 是图像分类任务中的常用方法。对于 MNIST 这样的低分辨率、高对比度的图像,SVM 可以实现令人满意的效果。
- K-最近邻 (K-NN):这是一种简单的机器学习算法,基于在特征空间中查找最近邻的原理。虽然它在大型数据集上的效率不高,但对于 MNIST 这种规模较小的数据集来说,K-NN 是一个不错的选择。
- 随机森林:尽管不是图像处理的传统选择,但随机森林作为一个强大的集成学习方法,在 MNIST 数据集上也能获得不错的效果。
其中,CNN 由于其对图像数据的特殊适应性和优异的性能,通常被认为是解决 MNIST 手写数字识别问题的首选算法。随着深度学习技术的发展,使用 CNN 处理此类图像识别任务已成为业界标准。
模型训练
在MNIST数字分类项目中,模型训练通常包括以下步骤:
- 数据加载:加载MNIST数据集,将其分为训练集和测试集。
- 数据预处理:对图像数据进行必要的预处理,包括标准化像素值、降低维度、或者进行特征提取。
- 模型训练:使用训练数据集来训练不同的机器学习算法或深度学习模型。调整模型的超参数以获得最佳性能。
- 性能评估:使用测试数据集对模型的性能进行评估,包括准确度、精确度、召回率等指标。
数据预处理
数据预处理是项目的关键步骤之一。在MNIST数字分类项目中,可能会进行以下数据预处理操作:
- 图像标准化:将图像像素值标准化为[0, 1]范围内的值,以便训练过程更稳定。
- 特征工程:对图像进行特征提取,例如局部二值模式 (LBP) 或主成分分析 (PCA)。
代码案例
下面咱们,就用 CNN 来完完整整地实现这个案例。
实现过程使用 TensorFlow 和 Keras 构建和训练了一个用于手写数字识别的卷积神经网络(CNN),并在 MNIST 数据集上进行了测试。
1. 导入库
- 导入 TensorFlow 和 Keras 相关模块,用于构建和训练模型。
2. 加载数据集
mnist.load_data()
:加载 MNIST 数据集,包含 60,000 个训练图像和 10,000 个测试图像。
3. 数据预处理
reshape((60000, 28, 28, 1))
:将训练图像从 (60000, 28, 28) 重塑为 (60000, 28, 28, 1),增加一个维度表示颜色通道(灰度图为 1)。astype('float32') / 255
:将像素值从整数转换为浮点数,并标准化到 [0, 1] 范围。to_categorical
:将标签转换为 one-hot 编码形式。
4. 构建模型
Sequential()
:初始化一个序贯模型。Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1))
:添加一个卷积层,32 个滤波器,每个滤波器大小 3x3,使用 ReLU 激活函数,输入形状为 28x28x1。MaxPooling2D((2, 2))
:添加一个最大池化层,池化窗口大小 2x2,用于降低特征图的维度。Flatten()
:将特征图展平成一维数组。Dense(128, activation='relu')
:添加一个全连接层,128 个神经元,使用 ReLU 激活函数。Dense(10, activation='softmax')
:添加一个输出层,10 个神经元对应 10 个类别,使用 softmax 激活函数输出概率分布。
5. 编译模型
optimizer='adam'
:使用 Adam 优化器。loss='categorical_crossentropy'
:多分类问题,使用交叉熵损失函数。metrics=['accuracy']
:评估指标为准确率。
6. 训练模型
model.fit
:在训练数据上训练模型,设定 epochs 为 5(训练周期),batch_size 为 64(每批处理 64 个样本),并在训练集的 10% 上进行验证。
7. 保存模型
model.save('mnist_model.h5')
:将训练好的模型保存为 H5 文件。
8. 评估模型
model.evaluate
:在测试数据上评估模型。- 打印测试准确率。
详细Python代码
代码语言:javascript复制import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
from tensorflow.keras.utils import to_categorical
# 加载MNIST数据集
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
# 数据预处理
train_images = train_images.reshape((60000, 28, 28, 1))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28, 28, 1))
test_images = test_images.astype('float32') / 255
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
# 构建卷积神经网络模型
model = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(MaxPooling2D((2, 2)))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(10, activation='softmax'))
# 编译模型
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
# 训练模型
model.fit(train_images, train_labels, epochs=5, batch_size=64, validation_split=0.1)
# 保存模型
model.save('mnist_model.h5')
# 评估模型
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print(f'Test accuracy: {test_accuracy}')
通过卷积层提取空间特征,池化层降低特征维度,全连接层进行分类。ReLU 激活函数增加非线性,避免模型过于简单。Softmax 函数用于输出预测类别的概率分布。整个模型的训练目的是最小化损失函数,提高在未见数据上的准确性。
输出结果:
代码语言:javascript复制Test accuracy: 0.988099992275238
当涉及到MNIST数字分类项目的测试展示时,可以使用已经训练好的模型来进行实际图像分类。
下面是如何使用训练好的模型对一个手写数字图像进行分类的示例:
代码语言:javascript复制import numpy as np
import matplotlib.pyplot as plt
# 加载训练好的模型
from tensorflow import keras
model = keras.models.load_model('mnist_model.h5')
# 加载并显示一个手写数字图像(可以自己手写一个数字图像,或从测试集中选取)
image_index = 256 # 随机选择一个测试图像
image = test_images[image_index] # 从测试集中获取图像
# 使用模型进行预测
predictions = model.predict(np.array([image]))
predicted_label = np.argmax(predictions)
# 显示图像和预测结果
plt.imshow(image.reshape(28, 28), cmap='gray')
plt.title(f'Predicted Label: {predicted_label}')
plt.show()
上述示例代码加载了已经训练好的模型(确保'mnist_model.h5'
文件存在,并包含已经训练好的模型),然后选择一个测试图像(在测试集中选择一个图像或者手写一个数字图像),使用模型进行预测,并在图像上显示预测的结果。
这个示例将显示一个手写数字图像以及模型对该图像的预测标签。
其中,可以替换image_index
以选择不同的测试图像。
这仅仅是一个简单的测试展示示例,可以验证模型的性能。
接下来,咱们简单修改一下代码,实现预测10个测试图片,生成2行5列的一个图片。
再看看结果。
代码语言:javascript复制import numpy as np
import matplotlib.pyplot as plt
from tensorflow import keras
# 加载训练好的模型
model = keras.models.load_model('mnist_model.h5')
# 选择要显示的测试图像数量
num_images_to_display = 10
# 随机选择10个测试图像的索引
image_indices = np.random.choice(len(test_images), num_images_to_display, replace=False)
# 创建一个2行5列的图像显示窗口
plt.figure(figsize=(10, 4))
# 遍历选择的图像索引
for i, image_index in enumerate(image_indices, 1):
image = test_images[image_index] # 从测试集中获取图像
predictions = model.predict(np.array([image]))
predicted_label = np.argmax(predictions)
plt.subplot(2, 5, i)
plt.imshow(image.reshape(28, 28), cmap='gray')
plt.title(f'Predicted: {predicted_label}')
plt.axis('off')
plt.show()