一个超强算法模型,CNN !!

2023-12-05 18:00:02 浏览数 (1)

今儿准备和大家一起实现一个开源且重要的项目:MNIST数字分类机器学习。

大概介绍下:MNIST数字分类项目旨在使用机器学习技术来构建一个模型,能够自动识别手写数字的图像。这个项目是一个经典的图像分类任务,常用于入门级机器学习和深度学习示例。我们会使用MNIST数据集,这个数据集包含了一系列28x28像素的手写数字图像,从0到9。项目的目标是训练一个模型,能够准确地将这些手写数字图像分类到正确的数字标签。

老规矩大家伙如果觉得近期文章还不错!欢迎大家点个赞、转个发,让更多的朋友看到。

数据集

简单介绍一下MNIST数据集,它是机器学习领域中最常用的数据集之一。

包含了60000张训练图像和10000张测试图像,每张图像都是28x28像素的灰度图像。每个图像都与一个0到9的数字标签相关联,表示图像中包含的手写数字。

这个数据集是一个非常适合用于图像分类任务的基准数据集。

涉及的算法

手写数字识别是一个典型的图像分类任务,常用于演示和教学机器学习和深度学习的基本概念。

对于使用 MNIST 数据集进行手写数字识别,以下几种算法是最合适的:

  1. 卷积神经网络 (CNN):这是最适合图像分类任务的算法之一。CNN通过学习图像中的局部模式(如边缘和纹理)逐渐构建出更复杂的图像特征,使其在图像识别任务中表现出色。
  2. 多层感知器 (MLP):这是一种基本的前馈神经网络,由多个层次的全连接层组成。虽然它不如 CNN 专门化,但对于 MNIST 这种相对简单的图像数据集而言,MLP 通常可以达到相当不错的效果。
  3. 支持向量机 (SVM):在深度学习兴起之前,SVM 是图像分类任务中的常用方法。对于 MNIST 这样的低分辨率、高对比度的图像,SVM 可以实现令人满意的效果。
  4. K-最近邻 (K-NN):这是一种简单的机器学习算法,基于在特征空间中查找最近邻的原理。虽然它在大型数据集上的效率不高,但对于 MNIST 这种规模较小的数据集来说,K-NN 是一个不错的选择。
  5. 随机森林:尽管不是图像处理的传统选择,但随机森林作为一个强大的集成学习方法,在 MNIST 数据集上也能获得不错的效果。

其中,CNN 由于其对图像数据的特殊适应性和优异的性能,通常被认为是解决 MNIST 手写数字识别问题的首选算法。随着深度学习技术的发展,使用 CNN 处理此类图像识别任务已成为业界标准。

模型训练

在MNIST数字分类项目中,模型训练通常包括以下步骤:

  1. 数据加载:加载MNIST数据集,将其分为训练集和测试集。
  2. 数据预处理:对图像数据进行必要的预处理,包括标准化像素值、降低维度、或者进行特征提取。
  3. 模型训练:使用训练数据集来训练不同的机器学习算法或深度学习模型。调整模型的超参数以获得最佳性能。
  4. 性能评估:使用测试数据集对模型的性能进行评估,包括准确度、精确度、召回率等指标。

数据预处理

数据预处理是项目的关键步骤之一。在MNIST数字分类项目中,可能会进行以下数据预处理操作:

  1. 图像标准化:将图像像素值标准化为[0, 1]范围内的值,以便训练过程更稳定。
  2. 特征工程:对图像进行特征提取,例如局部二值模式 (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()

0 人点赞