BP神经网络应用于手写数字识别--matlab程序

数据集和完整的程序下载见更新版:神经网络用于字符识别更新版

二:BP神经网络应用于字符识别

  字符包括汉字,字母,数字和一些符号。汉字有几千个,字母有几十个,数字的类最少只有10个,所以选择简单的手写数字字符来实现。结合三个相关的程序和论文,一个是语音特征的分类(不调用神经网络工具箱相关函数实现),另外两个是关于手写数字识别的。处理的数据集是放在10个文件夹里,文件夹的名称对应存放的手写数字图片的数字,每个数字500,每张图片的像素统一为28*28,如下

 

这5000张随机选取4500张进行训练,剩下的500张用来测试。为了能对BP神经网络有更深入的了解,选择一步步详细实现。

BP神经网络的特点:信号前向传递,信号反向传播。若输出存在误差,根据误差调整权值和阈值,使网络的输出接近预期。

在用BP神经网络进行预测之前要训练网络

训练过程

1.网络初始化:各个参数的确定包括输入,输出,隐含层的节点数,输入和隐含,隐含和输出层之间的权值,隐含,输出层的阈值,学习速度和激励函数。

2.计算隐含层输出

3.计算输出层输出

4.误差计算

5.权值更新

6.阈值更新

7.判断迭代是否结束

模型建立:

BP神经网络构建-BP神经网络训练-BP神经网络分类

1.确定神经网络的输入,输出。

输入是BP神经网络很重要的方面,输入的数据是手写字符经过预处理和特征提取后的数据。预处理有二值化,裁剪掉空白的区域,然后再统一大小为70*50为特征提取做准备。特征提取采用的是粗网格特征提取,把图像分成35个区域,每个区域100像素,统计区域中1像素所占的比例。经过预处理特征提取后,28*28图像转成1*35的特征矢量。提取完5000张图片后,依次把所有的特征存于一个矩阵(5000*35)中,最后在加上第36行,用来存放原图片的真值。于是最后得到是包含特征向量和真值的矩阵(5000*36),特征向量是神经网络的输入,真值是其输出。

2.神经的网络的训练

用matlab的rands函数来实现网络权值的初始化,网络结构为输入层35,隐藏层34,输出层10,学习速率为0.1,隐藏层激励函数为sigmoid函数。随机抽取4500张图片提取特征后输入,按照公式计算隐含层和输出层输出,误差,更新网络权值。

3.神经网络的预测

训练好神经网络之后,用随机抽取的500个数字字符对网络进行预测,输入特征向量,计算隐含层和输出层输出,得到最后预测的数据。同时计算每个数字的正确率和全体的正确率。最后得到的总体正确率为0.8004。

程序:

clc;
clearall;
closeall;
Files= dir('E:/Matlabdip/word_recognition/testdatabase');
LengthFiles= length(Files);
%========读取存在testdatabase下0-10个文件的全部图片========%
%========存放在number中,number{1}是数字0有500张========%
fori = 3:LengthFiles;   
    if strcmp(Files(i).name,'.')||strcmp(Files(i).name,'..')
    else
       number{i-2}=BatchReadImg(strcat('E:/Matlabdip/word_recognition/testdatabase','/',Files(i).name),0);
    end 
end
charvec1=zeros(35,5000);
%========对读取的图片预处理(二值化-裁剪-特征提取)========%
 for i=1:10
     for j=1:500
        I1=number{1,i}{1,j};
             Ibw = im2bw(I1,graythresh(I1));
         bw2 = edu_imgcrop(Ibw);%对图像进行裁剪,使边框完全贴紧字符
 
        charvec = edu_imgresize(bw2);%提取特征统计每个小区域中图像象素所占百分比作为特征数据
        charvec1(:,(i-1)*500+j)=charvec;
     end
 end
index=[zeros(1,500),zeros(1,500)+1,...
   zeros(1,500)+2,zeros(1,500)+3,zeros(1,500)+4,zeros(1,500)+5,zeros(1,500)+6,zeros(1,500)+7,zeros(1,500)+8,zeros(1,500)+9];
charvec1(36,:)=index;
%=========BP神经网络创建,训练和测试========%
%从1到5000间随机排序(在[0,1]之间产生5000个随机数)==将数据顺序打乱
k=rand(1,5000);
[m,n]=sort(k);
 
 
%输入输出数据
input=charvec1(1:35,:);
output1=charvec1(36,:);
 
%把输出从1维变成10维
fori=1:5000
    switch output1(i)
        case 0
            output(:,i)=[1 0 0 0 0 0 0 0 0 0]';
        case 1
            output(:,i)=[0 1 0 0 0 0 0 0 0 0]';
        case 2
            output(:,i)=[0 0 1 0 0 0 0 0 0 0]';
        case 3
            output(:,i)=[0 0 0 1 0 0 0 0 0 0]';
        case 4
            output(:,i)=[0 0 0 0 1 0 0 0 0 0]';
        case 5
            output(:,i)=[0 0 0 0 0 1 0 0 0 0]';
        case 6
            output(:,i)=[0 0 0 0 0 0 1 0 0 0]';
        case 7
            output(:,i)=[0 0 0 0 0 0 0 1 0 0]';
        case 8
            output(:,i)=[0 0 0 0 0 0 0 0 1 0]';
        case 9
            output(:,i)=[0 0 0 0 0 0 0 0 0 1]';
    end
end
 
%随机提取4500个样本为训练样本,500个样本为预测样本
input_train=input(:,n(1:4500));
output_train=output(:,n(1:4500));
input_test=input(:,n(4501:5000));
output_test=output(:,n(4501:5000));
 
% %输入数据归一化
%[inputn,inputps]=mapminmax(input_train);
 
%% 网络结构初始化
innum=35;
midnum=34;
outnum=10;
 
 
%权值初始化
w1=rands(midnum,innum);%输入到隐藏
b1=rands(midnum,1);
w2=rands(midnum,outnum);%隐藏到输出
b2=rands(outnum,1);
 
w2_1=w2;w2_2=w2_1;
w1_1=w1;w1_2=w1_1;
b1_1=b1;b1_2=b1_1;
b2_1=b2;b2_2=b2_1;
 
%学习率
xite=0.1;
alfa=0.01;
 
%% 网络训练
%for ii=1:10
%     E(ii)=0;
    for i=1:1:4500
       %% 网络预测输出
        x=input_train(:,i);
        % 隐含层输出
        for j=1:1:midnum
           I(j)=input_train(:,i)'*w1(j,:)'+b1(j);
            Iout(j)=1/(1+exp(double(-I(j))));
        end
        % 输出层输出
        yn=w2'*Iout'+b2;
       
       %% 权值阀值修正
        %计算误差
        e=output_train(:,i)-yn;    
%         E(ii)=E(ii)+sum(abs(e));
       
        %计算权值变化率
        dw2=e*Iout;
        db2=e';
        %=======由于采用的是sigmoid单元,所以要对每个输出单元以及隐藏单元计算误差项======%
        for j=1:1:midnum
            S=1/(1+exp(double(-I(j))));
            FI(j)=S*(1-S);
        end     
        for k=1:1:innum
            for j=1:1:midnum
               dw1(k,j)=FI(j)*x(k)*(w2(j,:)*e);%
                db1(j)=FI(j)*(w2(j,:)*e);
            end
        end
          
        w1=w1_1+xite*dw1';
        b1=b1_1+xite*db1';
        w2=w2_1+xite*dw2';
        b2=b2_1+xite*db2';
       
        w1_2=w1_1;w1_1=w1;
        w2_2=w2_1;w2_1=w2;
        b1_2=b1_1;b1_1=b1;
        b2_2=b2_1;b2_1=b2;
    end
%end
 
 
%%% 语音特征信号分类
%inputn_test=mapminmax('apply',input_test,inputps);
 
    for i=1:500%1500
        %隐含层输出
        for j=1:1:midnum
           I(j)=input_test(:,i)'*w1(j,:)'+b1(j);
            Iout(j)=1/(1+exp(double(-I(j))));
        end
        %输出层输出
        fore(:,i)=w2'*Iout'+b2;
    end
 
 
 
 
%% 结果分析
%根据网络输出找出数据属于哪类
fori=1:500
   output_fore(i)=find(fore(:,i)==max(fore(:,i)))-1;
end
 
%BP网络预测误差
error=output_fore'-output1(n(4501:5000))';
 
 
 
%画出预测数字和实际数字的分类图
figure(1)
plot(output_fore,'r')
holdon
plot(output1(n(4501:5000))','b')
legend('预测数字','实际数字')
 
%画出误差图
figure(2)
plot(error)
title('BP网络分类误差','fontsize',12)
xlabel('输入数字','fontsize',12)
ylabel('分类误差','fontsize',12)
 
k=zeros(1,10); 
%找出判断错误的分类属于哪一类
fori=1:500
    if error(i)~=0
        [b,c]=max(output_test(:,i));
        switch c-1
            case 1
                k(1)=k(1)+1;
            case 2
                k(2)=k(2)+1;
            case 3
                k(3)=k(3)+1;
            case 4
                k(4)=k(4)+1;
            case 5
                k(5)=k(5)+1;
            case 6
                k(6)=k(6)+1;
            case 7
                k(7)=k(7)+1;
            case 8
                k(8)=k(8)+1;
            case 9
                k(9)=k(9)+1;
            case 0
                k(10)=k(10)+1;
        end
    end
end
 
%找出每类的个体和
kk=zeros(1,10);
fori=1:500
    [b,c]=max(output_test(:,i));
    switch c-1
            case 1
                kk(1)=kk(1)+1;
            case 2
                kk(2)=kk(2)+1;
            case 3
                kk(3)=kk(3)+1;
            case 4
                kk(4)=kk(4)+1;
            case 5
                kk(5)=kk(5)+1;
            case 6
                kk(6)=kk(6)+1;
            case 7
                kk(7)=kk(7)+1;
            case 8
                kk(8)=k(8)+1;
            case 9
                kk(9)=kk(9)+1;
            case 0
                kk(10)=kk(10)+1;
    end
end
 
%正确率
rightridio=(kk-k)./kk
 
right=(sum(kk(:))-sum(k(:)))/sum(kk(:));
 
 
用到到函数:BatchImg
 
 
function [imglist]=BatchReadImg(rootpath,grayflag)
if nargin<2
   disp('Not enough parameters!');
   return;
end
 
filelist=dir(rootpath);
[filenum,temp]=size(filelist);
tempind=0;
imglist=cell(0);
for i=1:filenum
   
   if strcmp(filelist(i).name,'.')|| strcmp(filelist(i).name,'..')||strcmp(filelist(i).name,'Desktop_1.ini')||strcmp(filelist(i).name,'Desktop_2.ini')
       
   else
       tempind=tempind+1;
       imglist{tempind}=imread(strcat(rootpath,'/',filelist(i).name));
   end
end
if grayflag==1
   tempcount=size(imglist);
   for j=1:tempcount(2)
       imglist{j}=rgb2gray(imglist{j});
   end
end
edu_imgcrop:
function bw2 = edu_imgcrop(bw)
 
%找到图像边界
[y2temp x2temp] = size(bw);
x1=1;
y1=1;
x2=x2temp;
y2=y2temp;
 
% 找左边空白
cntB=1;
while (sum(bw(:,cntB))==y2temp)
   x1=x1+1;
   cntB=cntB+1;
end
 
% 左边
cntB=1;
while (sum(bw(cntB,:))==x2temp)
   y1=y1+1;
   cntB=cntB+1;
end
 
% 上边
cntB=x2temp;
while (sum(bw(:,cntB))==y2temp)
   x2=x2-1;
   cntB=cntB-1;
end
 
% 下边
cntB=y2temp;
while (sum(bw(cntB,:))==x2temp)
   y2=y2-1;
   cntB=cntB-1;
end
bw2=imcrop(bw,[x1,y1,(x2-x1),(y2-y1)]);
 
 
edu_imgresize:
function lett = edu_imgresize(bw2)
% ======提取特征,转成5*7的特征矢量,把图像中每10*10的点进行划分相加,进行相加成一个点=====%
%======即统计每个小区域中图像象素所占百分比作为特征数据====%
bw_7050=imresize(bw2,[70,50]);
for cnt=1:7
   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';

完整的数据集和可以运行的Matlab代码下载

 邮箱联系:dawnminghuang@gmail.com

阅读更多

没有更多推荐了,返回首页