基于卷积神经网络的手写数字识别(matlab实现) 基于CNN的matlab手写数字识别 可以加Lenet-5模型 数据集自制 数字大小5*5 训练过程良好,识别准确率在95%以上(数值+图像) 主成分分析提取像素点 包含图片输入和手写板输入两种方式加50

在机器学习领域,手写数字识别是一个经典的项目。今天,咱们就来聊聊如何用 Matlab 基于卷积神经网络(CNN)实现手写数字识别,并且会用到 Lenet - 5 模型,还会涉及自制数据集以及多种输入方式等有趣的内容。
一、数据集自制
这次我们自己制作数据集,设定数字大小为 5 * 5。自制数据集的好处是能更好地贴合我们的需求。下面是简单生成一些示例数据的代码:
matlab
% 生成 5*5 手写数字 0 的示例数据
digit_0 = [0 0 0 0 0;
0 1 1 1 0;
0 1 0 1 0;
0 1 1 1 0;
0 0 0 0 0];
% 生成 5*5 手写数字 1 的示例数据
digit_1 = [0 0 1 0 0;
0 1 1 0 0;
0 0 1 0 0;
0 0 1 0 0;
0 1 1 1 0];
% 以此类推生成其他数字的数据
% 将数据整理成训练集格式
training_data = [];
training_labels = [];
% 假设已经生成了 0 - 9 的数据,将其加入训练集
for i = 1:10
% 假设 digit_i 为数字 i 的 5*5 数据
training_data = cat(3, training_data, digit_i);
training_labels = [training_labels; i];
end
在这段代码里,我们先分别定义了数字 0 和 1 的 5 * 5 矩阵表示,实际应用中要生成 0 - 9 所有数字的数据。然后通过 cat 函数将这些数据按第三个维度拼接起来组成训练数据,同时记录对应的标签。
二、主成分分析提取像素点
主成分分析(PCA)能帮助我们从数据中提取主要特征,减少数据维度的同时保留关键信息。Matlab 里实现 PCA 提取像素点特征很方便:
matlab
% 将训练数据转换为二维矩阵,每一行是一个样本
data_matrix = reshape(training_data, 25, []);
% 进行 PCA 分析
[coeff, score, latent] = pca(data_matrix');
% 选择前几个主成分(这里假设选 10 个)
num_components = 10;
selected_coeff = coeff(:, 1:num_components);
% 对训练数据进行降维
reduced_training_data = data_matrix' * selected_coeff;
这段代码首先把三维的训练数据重塑成二维矩阵,每一行代表一个样本。然后通过 pca 函数进行主成分分析,得到主成分系数 coeff、得分 score 和方差 latent。我们选择前 10 个主成分,用这些主成分系数对训练数据进行降维,得到降维后的训练数据 reducedtrainingdata。
三、Lenet - 5 模型搭建
Lenet - 5 是经典的 CNN 模型,在手写数字识别上表现出色。在 Matlab 里搭建 Lenet - 5 模型如下:
matlab
layers = [
imageInputLayer([5 5 1])
convolution2dLayer(5,20,'Padding','same')
reluLayer()
maxPooling2dLayer(2,'Stride',2)
convolution2dLayer(5,50,'Padding','same')
reluLayer()
maxPooling2dLayer(2,'Stride',2)
fullyConnectedLayer(500)
reluLayer()
fullyConnectedLayer(10)
softmaxLayer()
classificationLayer()];
imageInputLayer 定义了输入图像的大小,这里是 5 5 的单通道图像。接着是卷积层 convolution2dLayer,使用 5 5 的卷积核,分别输出 20 个和 50 个特征图,Padding 设置为 same 保证输出尺寸和输入一样。reluLayer 加入激活函数,增强模型的非线性表达能力。maxPooling2dLayer 进行池化操作,减少数据维度。最后通过全连接层 fullyConnectedLayer 将特征映射到 10 个类别(对应 0 - 9 数字),softmaxLayer 输出概率分布,classificationLayer 用于分类。
四、训练模型
matlab
options = trainingOptions('adam',...
'MaxEpochs',50,...
'InitialLearnRate',0.001,...
'ValidationData',{validation_data, validation_labels},...
'ValidationFrequency',10,...
'Verbose',false,...
'Plots','training-progress');
net = trainNetwork(reduced_training_data, training_labels, layers, options);
这里使用 adam 优化器,设置最大训练轮数 MaxEpochs 为 50,初始学习率 InitialLearnRate 为 0.001。我们还指定了验证数据 validationdata**和验证标签 validation labels,每 10 轮进行一次验证。Verbose 设置为 false 不显示详细训练信息,同时开启训练进度图 Plots。通过 trainNetwork 函数进行模型训练。
五、识别准确率与可视化
训练完成后,我们来看看模型的识别准确率。
matlab
predicted_labels = classify(net, test_data);
accuracy = sum(predicted_labels == test_labels) / numel(test_labels);
fprintf('识别准确率: %.2f%%\n', accuracy * 100);
这段代码用训练好的模型 net 对测试数据 testdata**进行分类预测,得到预测标签 predicted labels。通过比较预测标签和真实标签 test_labels,计算出识别准确率并打印出来。在实际训练过程中,我们得到的识别准确率在 95% 以上。

为了更直观地感受模型的效果,我们可以绘制混淆矩阵。
matlab
confusionmat(test_labels, predicted_labels);
这行代码能生成混淆矩阵,通过可视化混淆矩阵,我们能清楚看到模型在不同数字类别上的预测情况,比如哪些数字容易被误判等。
六、输入方式
图片输入
Matlab 可以很方便地处理图片输入。假设我们有一张 5 * 5 的手写数字图片:
matlab
img = imread('handwritten_digit.png');
% 转换为灰度图(如果是彩色图)
if size(img, 3) == 3
img = rgb2gray(img);
end
% 调整图像大小为 5*5
img = imresize(img, [5 5]);
% 将图像转换为模型可接受的格式
input_img = im2double(img);
input_img = reshape(input_img, [5 5 1]);
% 进行预测
predicted_digit = classify(net, input_img);
这段代码先读取图片,判断是否为彩色图并转换为灰度图,然后调整图像大小为 5 * 5,再转换为双精度类型并重塑成模型输入格式,最后用训练好的模型进行预测。
手写板输入
Matlab 本身没有直接的手写板输入功能,但可以结合一些外部工具或者通过模拟实现。这里简单说一种思路,通过获取鼠标在图形界面上的轨迹,模拟手写过程,将轨迹数据转换为 5 * 5 的图像数据,再按照图片输入的方式进行处理和预测。

通过以上步骤,我们成功地基于卷积神经网络在 Matlab 中实现了手写数字识别,利用自制数据集和 Lenet - 5 模型达到了较高的识别准确率,同时也探索了多种输入方式,为手写数字识别应用提供了更多可能。希望大家对这个有趣的项目有更深入的了解,一起在机器学习的世界里探索更多精彩。


