机器学习中的手写字符识别

2025 年 8 月 27 日 | 阅读 8 分钟

手写数字识别是机器学习和计算机视觉领域中的一个老问题。它要求能够准确识别手写图像中的数字(0123456789);因此,它被选作测试模型性能的广泛使用的基准,而信息技术(IT)公司一直在努力研究它,以判断模型是否有效。神经网络在这方面一直发挥着作用。

在现实生活中可以应用的任务包括邮政编码识别和银行支票处理。本教程将开发一个基于神经网络的手写数字识别系统。

第一步:导入库

首先,我们将导入数据、可视化和模型开发所需的必要库。为了数值求解方程,我们将使用 numpy,使用 matplotlib 绘制结果,使用 scikit-learn 进行一些数据预处理,并使用 tensorflowkeras 构建和训练神经网络。

第二步:打开并浏览数据集

在这里,我们将读取数据集并检查数据的可用结构,以更好地理解数据。在将数据输入 机器学习 模型之前执行此操作至关重要,因为它将有助于定义特征和目标变量,并规划任何所需的预处理。

它的规模包括 42,000 行,每行都是一张手写数字图像。这是一张 28x28 的图像,被展平为一行 784 个像素值。灰度强度表示像素值,其值在 0 到 255 之间。

标签是数据集中的第一列,它是图像中实际书写的数字(0 到 9)。其余 784 列包含我们图像像素的值。我们将数据集分为 X(包含像素数据)和 y(包含与像素对应的标签)。这个划分使我们能够在特征 (X) 上进行模型训练,并用实际结果 (y) 进行测试。

输出

Shape of train_data: (42000, 785)
Shape of X after separating features: (42000, 784)

第三步:数据预处理

数据准备。在训练神经网络之前,我们需要转换和清理原始数据,以便可以用于建模。正确的预处理可以提高模型的性能和训练效果。

我们首先检查 X 是否已正确地以 DataFrame 的形式传输到 Pandas 中。然后,我们将所有像素值转换为数值数据类型,并用 0 填充任何空白数据,以确保数据处于干净完整状态。

然后,我们将像素除以 255.0 进行归一化,将它们的取值范围缩小到 0 到 1 之间。这种归一化将有助于神经网络快速收敛训练。

最后,我们重塑数据,使其包含通道维度,将形状从 (num_samples, 784) 变为 (num_samples, 28, 28, 1)。这是为卷积层准备数据,卷积层需要四维输入张量。

输出

Shape of X after reshaping: (42000, 28, 28, 1)

第四步:标签独热编码

对于神经网络而言,目标标签最好以一种称为独热编码的形式表示。在当前格式下,所有标签都经过二元编码,该编码是一个长度等于类别数量的向量。

在这种情况下,数字 3 将被表示为 [0,0,0,1,0,0,0,0,0,0],这样只有与该数字对应的索引被记录为 1,其他索引为 0。这种更改有助于模型将分类过程视为对属于不同类别的概率的预测。现在我们将对标签数组 y 进行二元化,或者更准确地说,进行独热编码。

输出

Shape of y after one-hot encoding: (42000, 10)

第五步:划分数据

为了正确评估模型性能,我们应该通过将数据集分为两部分:训练集和验证集来测试我们的模型。模型在训练集上进行训练,而验证集旨在帮助确定模型在多大程度上泛化到未见过的数据。

在这里,我们将 80% 的数据用作训练集,20% 的数据用作验证集。这种划分可以确保模型的有效学习,并能够可靠地衡量性能。

输出

X_train shape: (33600, 28, 28, 1)

第六步:构建神经网络模型

然后,我们将指定神经网络的结构。从一个简单的前馈神经网络开始,包含三个主要层:

第一个是 Flatten 层,它将每个 28x28 的图像转换为一个一维的 784 个元素的向量,该向量可以正确地用于密集层。

然后,我们添加了两个隐藏层,分别有 128 和 64 个神经元。这两个层都配备了 ReLU 激活函数,它增加了非线性,并促进模型学习复杂模式。

最后,输出层包含 10 个神经元(每个数字 0-9 一个)并采用 softmax 激活函数,该函数将概率分布映射到所有数字类别。

输出

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten (Flatten)           (None, 784)               0         
                                                                 
 dense (Dense)               (None, 128)               100480    
                                                                 
 dense_1 (Dense)             (None, 64)                8256      
                                                                 
 dense_2 (Dense)             (None, 10)                650       
                                                                 
=================================================================
Total params: 109,386
Trainable params: 109,386

第七步:模型训练

在准备好模型架构后,就可以用训练数据拟合该模型架构了。训练过程基于多次迭代(称为 epoch)地向模型输入数据的原理进行。

我们将使用 10 个 epoch 来训练模型,即让模型完整地遍历训练数据集 10 次。为了提高效率和性能,数据以每 epoch 32 个样本的批次进行处理。这为模型更好地在小批次中进行训练并减少内存占用增加了层次。

输出

Epoch 1/10
1050/1050 [==============================] - 5s 4ms/step - loss: 0.3381 - accuracy: 0.8982 - val_loss: 0.1827 - val_accuracy: 0.9486
Epoch 2/10
1050/1050 [==============================] - 4s 4ms/step - loss: 0.1472 - accuracy: 0.9564 - val_loss: 0.1345 - val_accuracy: 0.9618
Epoch 3/10
1050/1050 [==============================] - 4s 4ms/step - loss: 0.1014 - accuracy: 0.9693 - val_loss: 0.1127 - val_accuracy: 0.9662
Epoch 4/10
1050/1050 [==============================] - 4s 4ms/step - loss: 0.0759 - accuracy: 0.9767 - val_loss: 0.1115 - val_accuracy: 0.9655
Epoch 5/10
1050/1050 [==============================] - 4s 4ms/step - loss: 0.0597 - accuracy: 0.9815 - val_loss: 0.1042 - val_accuracy: 0.9686
Epoch 6/10
1050/1050 [==============================] - 4s 4ms/step - loss: 0.0480 - accuracy: 0.9851 - val_loss: 0.1022 - val_accuracy: 0.9707
Epoch 7/10
1050/1050 [==============================] - 4s 4ms/step - loss: 0.0387 - accuracy: 0.9880 - val_loss: 0.1103 - val_accuracy: 0.9683
Epoch 8/10
1050/1050 [==============================] - 4s 4ms/step - loss: 0.0315 - accuracy: 0.9902 - val_loss: 0.1096 - val_accuracy: 0.9704
Epoch 9/10
1050/1050 [==============================] - 4s 4ms/step - loss: 0.0271 - accuracy: 0.9912 - val_loss: 0.1137 - val_accuracy: 0.9695
Epoch 10/10
1050/1050 [==============================] - 4s 4ms/step - loss: 0.0217 - accuracy: 0.9935 - val_loss: 0.1235 - val_accuracy: 0.9689

第八步:测试模型

训练完成后,接下来的步骤包括在验证集上评估模型性能。这为我们提供了模型学习情况的衡量标准,以及它是否能泛化到它从未见过的数据。

我们还会在每个 epoch 跟踪训练和验证的准确率,并将其绘制出来。这将使我们能够监控模型学习的进度,并可以识别潜在问题,例如过拟合,即模型在训练数据上表现良好,但在验证数据上表现不佳。

输出

263/263 [==============================] - 1s 3ms/step - loss: 0.1235 - accuracy: 0.9689
Validation Accuracy: 96.89%

第九步:进行预测

在训练和测试完模型后,我们就可以对模型未曾接触过的新数据进行预测了。为此,我们需要加载测试数据,并以与训练数据相同的方式进行预处理,以确保格式和缩放的一致性。

有了要运行测试的数据后,我们将其输入到训练好的模型中以生成预测。这些猜测是模型对测试图像中数字的最有可能的答案。测试数据集可以从给定来源获取,同样,也可以进行准备以供预测。

输出

1313/1313 [==============================] - 2s

我们使用神经网络架构和高精度,成功地训练了一个包含 42,000 个手写数字的数据集上的模型。该模型泛化良好,因此能够准确地识别以前未见过的数字。整个过程体现了机器学习在解决现实问题,尤其是图像识别方面的强大能力。

示例

输出

Handwritten Character Recognition using Machine Learning Handwritten Character Recognition using Machine Learning