matlab代码--卷积神经网络的手写数字识别
1.cnn介绍
卷积神经网络(Convolutional Neural Network, CNN)是一种深度学习的算法,在图像和视频识别、图像分类、自然语言处理等领域有着广泛的应用。CNN的基本结构包括输入层、卷积层、池化层(Pooling Layer)、全连接层(Fully Connected Layer)和输出层。其中,卷积层通过一系列可学习的滤波器(或称核)扫描输入数据,旨在检测特定的局部特征。这些滤波器能够自动学习并提取图像中的边缘、纹理和形状等低层次特征,以及更复杂的高层次特征。
卷积神经网络的核心特性包括局部连接、权值共享和池化。局部连接意味着每个神经元只与输入数据的局部区域相连,这有助于捕捉图像的局部特征。权值共享则大大减少了网络参数的数量,降低了模型的复杂度和计算量,同时提高了模型的泛化能力。池化层则通过下采样操作(如最大池化或平均池化)进一步减少数据的维度,保留重要特征并减少过拟合的风险。这些特性使得CNN在处理高维数据(如图像)时具有显著的优势和效率。
卷积神经网络在诸多领域都取得了显著的成果。在图像分类任务中,CNN能够准确识别并分类各种物体和场景。在目标检测领域,基于CNN的方法如YOLO(You Only Look Once)和Faster R-CNN等实现了高效且准确的目标检测。此外,CNN还在人脸识别、语音识别、自动驾驶和医疗影像分析等领域展现出了巨大的潜力。随着深度学习技术的不断发展,卷积神经网络也在持续演进,如引入残差网络(ResNet)、卷积神经网络与循环神经网络的结合(如CRNN)等新型网络结构,以及通过迁移学习、深度学习框架优化等技术进一步提升其性能和应用范围。
2.cnn介绍
手写数字MNIST数据库由60000个示例的训练集和10000个示例的测试集组成。这些数字已进行归一化,每个示例是28*28像素的图片,图片是黑底白字,每个图片的标签就是图片上的数字,数字范围是0~9,总共10各分类标签。对于那些想在真实世界的数据上尝试学习模式识别方法,同时在预处理和格式化上花费最少精力的人来说,这是一个很好的数据库。其下载网址为附官网网址:http://yann.lecun.com/exdb/mnist/
在官网上下载的mnist数据集格式是这样的,包含4个文件:
train-images-idx3-ubyte.gz: training set images (9912422 bytes)
train-labels-idx1-ubyte.gz: training set labels (28881 bytes)
t10k-images-idx3-ubyte.gz: test set images (1648877 bytes)
t10k-labels-idx1-ubyte.gz: test set labels (4542 bytes)
这里,4个文件分别表示训练图像集(预测变量)、训练标签集(响应变量)、测试图像集、测试标签集。
简单来说,这是一种类似二进制格式的数据,为什么使用这种格式,我想可能是为了压缩数据大小,方便下载和传输吧,如果直接使用图片存储格式,7万张图片的压缩包有多大。
将原始格式转换为常用的图片格式,代码如下,
clear,clc,close all
%% 01 首先提取训练图片集
filename='train-images-idx3-ubyte';
%读取文件头信息,并转换
fid=fopen(filename);
magic1=fread(fid,4);
num1=fread(fid,4);
row1=fread(fid,4);
colomn1=fread(fid,4);
magic1=zhuanhuan(magic1)
num1=zhuanhuan(num1)
row1=zhuanhuan(row1)
colomn1=zhuanhuan(colomn1)
%读取图片像素单点数据,并重构图片数据结构
trainimages=cell(num1,1);
for i=1:num1
temp=fread(fid,row1*colomn1);
temp=reshape(temp,[row1,colomn1]);
trainimages {i}=temp';
end
fclose(fid);
%读取完毕,读取后的图片数据存储在trainimages变量中
%随便查看一下第5张图片,确认提取无误
for i=1:5
imshow(trainimages{i})
hold on
end
%% 02 读取训练标签集
filename='train-labels-idx1-ubyte';
%读取文件头信息,并转换
fid=fopen(filename);
magic2=fread(fid,4);
num2=fread(fid,4);
magic2=zhuanhuan(magic2)
num2=zhuanhuan(num2)
%读取标签数据,不需要数据重构,直接赋值和存储到trainlabels变量中即可
trainlabels=zeros(num2,1);
for i=1:num2
trainlabels(i)=fread(fid,1);
end
fclose(fid);
%查看下前面5个标签数据,确认提取无误
trainlabels(1:5)
%% 03 把上面提取好的trainimages存储成外部图片文件
%总共6万个图片,使用for循环读取和存出,注意,相同类别的图片存储到相同命名文件下面。例如标签0的所有图片存储到子文件0下面。最终形成0~9共10个子文件夹。
for index=1:num1
img=trainimages{index};
label=num2str(trainlabels(index));
path=fullfile('./','bmp',label,...
['img',label,num2str(index),'.png']);
%imwrite(img,path);
end
%% 04 把上面提取好的trainimages和trainlabels存储成外部mat文件,命名为mnist0。
% save mnist0.mat trainimages trainlabels
% 转换的函数,上面程序代码调用
function y=zhuanhuan(data)
b=dec2bin(data,8);
c=[b(1,:),b(2,:),b(3,:),b(4,:)];
y=bin2dec(c);
end
matlab实现
CNN基本组成:输入层、隐藏层、输出层。但隐藏层分为:卷积层 + 池化层
1.输入层
为一张原始的图片,尺寸为28*28
2.卷积层
通过使用一系列可学习的滤波器(或称为卷积核)来扫描输入图像,提取图像的局部特征。这些滤波器能够捕捉到图像中的边缘、纹理等基本特征。用于提取图像的局部特征.
3.池化层
用于降低特征的空间维度,减少参数数量和计算量,提高网络的鲁棒性。常见的池化操作有最大池化(Max Pooling)和平均池化(Average Pooling)、
4.全连接层
在卷积和池化层之后,网络会包含一个或多个全连接层,将卷积层和池化层提取的特征映射到高维空间,以便进行分类。最后一层将学习到的特征映射到最终输出,如分类标签。.
5输出层
是一个softmax层,用于将全连接层的输出转换为概率分布,从而实现多类别分类,这里我们需要实现10个目标的分类。
首先,使用MATLAB自带的神经网络工具箱,对手写数字识别问题进行分类识别,训练中设置不同的最小批次参数。
使用的卷积网络结构如下
部分代码:
%卷积层
layers = [
imageInputLayer([28 28 1],"Name","imageinput")
convolution2dLayer([5 5],10,"Name","conv_1","Padding","same")
batchNormalizationLayer("Name","batchnorm_1")
tanhLayer("Name","tanh_1")
averagePooling2dLayer([5 5],"Name","avgpool2d_1","Padding","same")
convolution2dLayer([5 5],10,"Name","conv_2","Padding","same")
batchNormalizationLayer("Name","batchnorm_2")
tanhLayer("Name","tanh_2")
averagePooling2dLayer([5 5],"Name","avgpool2d_2","Padding","same")
fullyConnectedLayer(10,"Name","fc")
softmaxLayer("Name","softmax")
classificationLayer("Name","classoutput")];
训练参数如下所示
% 设置训练参数
opts = trainingOptions('sgdm', ...
'InitialLearnRate',0.01, ...%初始学习率
'Shuffle','every-epoch', ...
'MaxEpochs',3,...%最大训练轮数
'ValidationData', test, ...
'ValidationFrequency',150,...%测试频率
'MiniBatchSize',200,... %minibatch大小
'Verbose',false, ...
'Plots','training-progress');
通过自己手动实现卷积神经网络的过程,其过程包括,
1.定义网络结构
卷积层:定义卷积核的大小、数量和步长。卷积层通过滑动窗口的方式对输入图像进行特征提取。
激活函数:在卷积层之后,通常会应用一个非线性激活函数,本文使用ReLU函数,这有助于增加网络的非线性特性。
池化层:池化层(如最大池化)用于减少特征图的维度,降低计算复杂度,并提高模型的平移不变性。
全连接层:在卷积层和池化层之后,通常会添加一到两层全连接层,用于对提取的特征进行高级别的推理。
2.前向传播
卷积操作:对于输入图像和每个卷积核,执行卷积操作以生成特征图。
激活函数:将卷积层的输出通过激活函数。
池化操作:对激活后的特征图进行池化操作。
全连接层:将池化层的输出展平成一个向量,并输入到全连接层中进行计算。
3.损失函数和优化器
损失函数:定义损失函数,本文使用交叉熵损失函数,用于衡量模型的预测结果与真实标签之间的差距。
优化器:选择优化器,本文使用随机梯度下降(SGD)优化器,用于更新模型的权重和偏置,以最小化损失函数。
4. 反向传播
计算梯度:根据损失函数,计算每一层参数的梯度。
更新参数:使用优化器更新模型的权重和偏置。
5. 训练模型
迭代训练:将数据集分成训练集和测试集,使用训练集进行多次迭代训练。在每次迭代中,执行前向传播、计算损失、反向传播和更新参数的步骤。
6.验证性能:在每次迭代或每几个迭代后,使用测试集评估模型的性能。
自己手写cnn,得到的训练效果如下
完整代码获取:这里