MATLAB--基于BP神经网络的手写数字识别

MATLAB–基于BP神经网络的手写数字识别

在干活的过程中整理下来的,希望对大家有帮助。
手写数字识别技术作为图像处理和模式识别中的研究热点,在大规模数据统计(如行业年检、人口普查等)、票据识别、财务报表、邮件分拣等方面有着广泛的应用。目前手写数字识别技术也有很多种实现方法,这里介绍与本章内容相关的一种基于BP神经网络的手写数字识别方法。该方法的基本思想来源于以下两方面:一是手写数字图片中黑色像素点和白色像素点之间的空间编排关系构成了我们看到的数字,也就是说图片像素点的空间排布和输出的识别结果之间存在着非线性的映射关系。二是BP神经网络刚好就能解决非线性映射的数学建模问题。如果对像素点空间排布与输出数字之间的关系进行学习、训练,建立有效的人工神经网络,就可对再次给出的手写数字图片进行识别,输出识别结果。
手写数字的识别就是利用计算机自动识别人手写在纸张上的阿拉伯数字,如果输入以下手写数字图片,则计算机输出对应识别结果为:0、1、2、3、4、5、6、7、8、9。
手写数字图片截图
进行手写数字识别时,先要对读取图片进行预处理,包括去噪、二值化等,再进行特征提取。特征提取的方法很多,这里采用一种简单的特征提取方法,即统计每个小区域中图像像素所占百分比作为特征数据。提取特征后再创建、训练BP神经网络模型,最后用测试数据进行测试。
要进行手写数字识别这个实际问题,第一步就是建立手写数字的模型。

1.手写数字识别非线性数学的模型建立

BP神经网络即误差反向传播神经网络,可解决有教师训练的非线性数学建模问题。模型的建立主要包括:BP神经网络的创建、BP神经网络的训练以及BP神经网络的测试三步。
创建BP神经网络前首先要确定网络的输入、输出。

(1)BP神经网络的输入、输出

BP神经网络的输入数据是手写数字样本经过预处理和特征提取后的数据。而为了BP神经网络的输入,我们肯定要先读入手写数字的样本,这里我们使用最通用的MNIST手写数字库,这个数据库直接在百度上就能下载到,该数据库包含0-9这10个数字的手写体,放在10个文件夹里,文件夹的名称对应存放的手写数字图片的数字,每个数字500张,每张图片的像素统一为28×28。
下面介绍用MATLAB程序实现读入手写数字的样本,这里注意,我将手写数字的样本放在和MATLAB 程序同根目录的文件夹里,文件夹的名称对应存放的手写数字图片的数字,也就是说当前文件夹如下图所示。画红线的文件夹就是我们要读入的手写数字的样本,以数字0为例,数据库中图片的名称如下图所示。
来自我的MATLAB截图
来自我的MATLAB截图
这样就可以用在主程序中调用read_train子函数读入手写数字的样本了。

这里需要说明的是,我的MATLAB程序来自于:
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zxm_jimin/article/details/87937652
————————————————
版权声明:本文为CSDN博主「zxm_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zxm_jimin/article/details/87937652
这里主要介绍我在学习这段MALTLAB程序的时候,学到的内容。

main.m的MATLAB如下。

clc;
clear all;
close all;
%% 读取图像
root='./data';
img=read_train(root);
%% 提取特征
img_feature=feature_lattice(img);
%% 构造标签
class=10;
numberpclass=500;
ann_label=zeros(class,numberpclass*class);
ann_data=img_feature;
for i=1:class
 for j=numberpclass*(i-1)+1:numberpclass*i
     ann_label(i,j)=1;
 end
end

%% 选定训练集和测试集
k=rand(1,numberpclass*class);  
[m,n]=sort(k);  
ntraindata=4500;
ntestdata=500;
train_data=ann_data(:,n(1:ntraindata));
test_data=ann_data(:,n(ntraindata+1:numberpclass*class));
train_label=ann_label(:,n(1:ntraindata));
test_label=ann_label(:,n(ntraindata+1:numberpclass*class));
%% BP神经网络创建,训练和测试
net=network_train(train_data,train_label);
predict_label=network_test(test_data,net);
%% 正确率计算
[u,v]=find(test_label==1);
label=u';
error=label-predict_label;
accuracy=size(find(error==0),2)/size(label,2)

read_train子函数的MATLAB如下。

function [imglist] = read_train(root)
% ni为读取图片张数,n为文件夹数目
%========读取文件夹========%
out_Files = dir(root);%展开
tempind=0;
imglist=cell(0);
n=length(out_Files);
%========读取文件========%
for i = 1:n
    if strcmp(out_Files(i).name,'.')|| strcmp(out_Files(i).name,'..')
    else
        rootpath=strcat(root,'/',out_Files(i).name);
        in_filelist=dir(rootpath);
        ni=length(in_filelist);
        for j=1:ni
            if strcmp(in_filelist(j).name,'.')|| strcmp(in_filelist(j).name,'..')|| strcmp(in_filelist(j).name,'Desktop_1.ini')|| strcmp(in_filelist(j).name,'Desktop_2.ini')
            else
                tempind=tempind+1;
                imglist{tempind}=imread(strcat(rootpath,'/',in_filelist(j).name));
            end
        end
    end
end
end

在这个子程序的4行dir函数可以获得指定文件夹下的所有子文件夹和文件,并存放在文件结构体数组中。返回值out_Files是一个struct—结构体,我们可以在工作区查看它,如下图。来自我的MATLAB截图
在第10行函数strcmp()用于做字符串的比较,
如调用格式为:TF=strcmp(s1,s2);
则如果字符串s1和s2是一致的,则返回值TF=1,否则,TF=0。
在第12行函数strcat(),用于横向连接字符串。如调用格式为:combinedStr= strcat(s1, s2, …, sN),就是将数组 s1,s2,…,sN 水平地连接成单个字符串,并保存于变量combinedStr中。在这里就是讲文件夹的路径和文件夹名横向连接。
也就是说从10到13行,就是对于每一个文件夹中文件读入in_filelist这个结构体。而在n_filelist这个结构体中,比如对于”9”这个文件夹,每个图片的名称就是9_1,9_2,等等,从下边的一小块截图就可以看出来。
来自我的MATLAB截图
从15到21行,同样用到了函数strcmp()和函数strcat(),然后调用imread,也就是根据每个文件的路径及文件名,依次读入到imglist这个cell-元胞数组中,从而完成5000张图片的读入。

在我们这个例子预处理主要是图像的二值化,特征提取方法主要采用粗网格特征提取。粗网格特征提取方法是指将二值化后的图像大小统一为50×50,再等分成5×5个网格,每个网格包含100像素,然后依次统计每个网格中黑色像素点的数量,从而得到一个1×25的特征向量。
也就是说5000张手写数字图片的特征向量即为BP神经网络的输入(一个5000×25的矩阵),而其对应的真实数字为BP神经网络的输出(一个5000×1的向量)。
图像预处理及特征提取的MATLAB通过在主程序中调用feature_lattice子函数来实现,其MATLAB如下。

function feature = feature_lattice(img)
% 输入:黑底白字的二值图像。输出:25维的网格特征
% ======提取特征,转成5*5的特征矢量,把图像中每10*10的点进行划分相加,进行相加成一个点=====%
%======即统计每个小区域中图像象素所占百分比作为特征数据====%
for i=1:length(img);
bw2=im2bw(img{i},graythresh(img{i}));
bw_7050=imresize(bw2,[50,50]);
for cnt=1:5
    for cnt2=1:5
        Atemp=sum(bw_7050(((cnt*10-9):(cnt*10)),((cnt2*10-9):(cnt2*10))));%10*10box
        lett((cnt-1)*5+cnt2)=sum(Atemp);
    end
end
lett=((100-lett)/100);
lett=lett';
feature(:,i)=lett;
end

首先该子程序的第5行,在MATLAB中将图像转换为二值图像,调用MATLAB中的im2bw函数。
对于灰度图像,调用的格式如下。
bw=im2bw(I,level);
level空着的话,默认是0.5。level一般使用graythresh函数来计算,graythresh函数是MATLAB中自带的,函数功能:使用最大类间方差法找到图片的一个合适的阈值–level,
第6行,调用imresize将图像大小统一为50×50。
接着,从8-13行,用嵌套的for循环语句,将图像分成5×5个网格,也就是说每个网格是10×10个像素点,然后统计每个网格中不为0的像素点的数量。
15行100-left就是每个网格中为0的像素点(黑色)的数量
第16行通过一个转置操作,保证每个图像的特征是一个列向量。
这样通过调用feature_lattice子函数,每一张图片都有1×25的特征向量。

提取完特征后,将数据打上标签,这段程序是主程序的10-18行。
因为数据一共10类,每类500张图片,先初始化一个用于存放标签的矩阵,这个矩阵大小就是10×(10×500)。
我用图画了一下这个存放标签的矩阵是什么样。
自己画的
如果一个图片的标签是[1;0;0;0;0;0;0;0;0;0],那么这张图片上的数字是1,如果标签是[0;1;0;0;0;0;0;0;0;0], 那么这张图片上的数字是2,以此类推。
因为我们数字图片是根据文件名读入的,这样图片上的数字、文件名和标签就都对应上了。

最后随机选取4500张图片作为训练样本,500张图片作为测试样本。MATLAB是主程序的21-28行。提取的特征在ann_data中,也就是BP神经网络的输入,标签在ann_label中,也就是BP神经网络的输入输出。这样,我们就将BP神经网络的输入、输出准备好了。就可以开始创建BP神经网络了。

(2)BP神经网络的创建

BP神经网络具有输入层、隐含层(隐藏层)和输出层的三层结构。其中,隐含层可以有一个或两个及以上,这里采用具有一个隐含层的基本BP网络模型,隐含层神经元个数选取25个,激励函数选取默认的Sigmoid函数,学习速率设为0.1,网络训练函数选取默认的Trainlm,网络目标误差设为0.001。随机抽取4500张图片提取的特征矩阵作为训练样本的输入,计算隐含层和输出层输出、误差,更新网络权值。当误差达到设定目标时,网络的学习过程就结束。在main.m中调用network_train子函数,其MATLAB程序如下。

function net = network_train(train_data,train_label )
% BP网络训练
% 初始化网络结构
layer=30;%隐含层个数
net=newff(train_data,train_label,layer);%创建网络
net.trainParam.epochs=10;%迭代次数
net.trainParam.lr=0.2;%学习率
net.trainParam.goal=0.001;%误差参数
net.trainFcn='trainrp';%训练方法
% 网络训练
net=train(net,train_data,train_label);
end

这样我们得到了训练好哒神经网络net。

(3)神经网络的测试

训练好神经网络之后,用随机抽取的500张手写数字图片对网络进行测试,输入特征向量,计算隐含层和输出层输出,得到最后测试的数据。同时计算每个数字的正确率和全体的正确率。在主程序中调用network_test子函数,其MATLAB程序如下。

function out = network_test(test_data,net)
% 输入:测试数据的特征和真值。输出:测试数据的label以及误差图
% BP网络预测
an=sim(net,test_data);
for i=1:length(test_data)
    out(i)=find(an(:,i)==max(an(:,i)));
end
end

测试数据的标签存在了predict_label中,可以在工作区双击predict_label,打开查看。如下所示。
来着我的MATLAB截图
正确率在命令行窗口可以看到。
来着我的MATLAB截图
另外,在网络训练的性能等可以点击下图中的按钮进行查看。这部分在上一篇介绍了,这里就不赘述了。
来着我的MATLAB截图

手写数字的数据集,data,我存放在百度网盘里了。
data的提取链接

已标记关键词 清除标记
相关推荐
<ul style="color:rgba(0,0,0,.560784);font-size:14px;background-color:#FFFFFF;"> <li> <span>Tensorflow2.0介绍:</span> </li> </ul> <p style="color:rgba(0,0,0,.560784);font-size:14px;background-color:#FFFFFF;"> tensorflow是GOOGLE在2015年底发布的一款深度学习框架,也是目前全世界用得最多,发展最好的深度学习框架。2019年3月8日,GOOGLE发布最新tensorflow2版本。新版本的tensorflow有很多新特征,更快更容易使用更人性化。但是老版的tensorflow程序在新版本中几乎都无法继续使用,所以我们有必要学习新版tensorflow2的新用法。 </p> <ul style="color:rgba(0,0,0,.560784);font-size:14px;background-color:#FFFFFF;"> <li> <span>课程介绍:</span> </li> </ul> <p style="color:rgba(0,0,0,.560784);font-size:14px;background-color:#FFFFFF;"> 我们的这门课程适合小白学习,也适合有基础的同学学习。课程会从0开始学习,从python环境安装,python入门,numpy,pandas,matplotlib使用,深度学习基础,一直讲到tensorflow基础,进阶,项目实战。不管你是0基础小白,想进入AI行业,还是有一定基础,想学习最新的tensorflow2的使用,都适合我们这门课程。 </p> <ul style="color:rgba(0,0,0,.560784);font-size:14px;background-color:#FFFFFF;"> <li> <span>讲师介绍:</span> </li> </ul> <p style="color:rgba(0,0,0,.560784);font-size:14px;background-color:#FFFFFF;"> 覃秉丰,物理系毕业转AI行业,想转行同学可以找我聊聊。机器学习、深度学习神经网络领域多年研究开发授课经验,精通算法原理与编程实践;曾完成过多项图像识别、目标识别、语音识别等企业项目,一线实战经验丰富;长期为多家包括世界五百强在内的大型企业总部做人工智能技术内训服务(中国移动、中国银行,华夏银行,中国太平洋,国家电网、中海油等)。上课特点:公式尽量一个一个符号推,代码尽量一行一行讲,希望所有人都能学有所得。 </p>
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页