精华内容
下载资源
问答
  • BP神经网络实现手写数字识别,使用matlab实现。内有测试数据及实验结果,非常适合入门者使用。绝对超值、值5分。0.99MB的文件下载该文档,你不会吃亏。
  • 可以直接运行的代码,关于bp神经网络进行手写数字识别的,内附0-9手写字体图片,每个数字500张图片。
  • 基于BP神经网络对几种字体0-9的数字识别(MATLAB)
  • 利用BP实现手写字母识别,非常好使!!!!!!
  • matlab+BP神经网络 手写数字识别训练程序(含训练数据)。 包含5000张手写数字图片(20x20像素),以及matlab训练程序。
  • matlab基于bp算法实现的手写数字识别

    热门讨论 2010-03-25 19:48:13
    先打开gui,和别人相比,我做了图形用户界面很容易看到的
  • MNIST手写Matlab程序,包含BP和CNN程序。不依赖任何库,包含MNIST数据,BP网络可达到98.3%的识别率,CNN可达到99%的识别率。CNN比较耗时,关于CNN的程序介绍:...
  • BP神经网络手写数字识别matlab

    千次阅读 2020-11-03 11:33:51
    BP神经网络手写数字识别matlab实现 BP神经网络原理 BP神经网络是一种按误差逆传播算法训练的多层前馈网络。标准的前馈神经网络一般包括三层神经,即输入层,隐含层,输出层,每层神经包含的神经元个数不一。它的...

    BP神经网络手写数字识别的matlab实现

    BP神经网络原理

    BP神经网络是一种按误差逆传播算法训练的多层前馈网络。标准的前馈神经网络一般包括三层神经,即输入层,隐含层,输出层,每层神经包含的神经元个数不一。它的学习规则是使用最速下降法,通过反向传播来不断调整网络的权值和阈值,使网络的误差平方和最小。网络上有许多BP神经网络的原理,比较通俗易懂,读者可以自行搜索。这里推荐一篇BP神经网络权值迭代过程的博文和手写BP神经网络权值迭代公式的推导博文
    链接1: BP神经网络权值迭代的直观过程.
    链接2: BP神经网络权值迭代公式.

    数据集选择

    本次实验采用mmist数据集对搭建的网络进行训练和测试,下载网站如下:
    链接3: MNIST数据集.
    该数字集包含60000张手写数字的照片的训练集和包含10000张手写数字照片的测试集。每张图片为28*28像素,带有标签,满足训练网络所需要求。

    实验代码

    由于代码之中注释比较全面,所以直接上代码。

    读取image数据

    function y=loadmnistdata()
        fp = fopen('文件保存路径', 'r');%打开文件句柄,路径之中不可以有汉字,否则打不开
        assert(fp ~= -1, ['Could not open ',文件保存路径', '']);
        magic = fread(fp, 1, 'int32', 0, 'ieee-be');
        assert(magic == 2051, ['Bad magic number in ','文件保存路径', '']);
        numImages = fread(fp, 1, 'int32', 0, 'ieee-be');%读取图片数
        numRows = fread(fp, 1, 'int32', 0, 'ieee-be');%读取图片行数
        numCols = fread(fp, 1, 'int32', 0, 'ieee-be');%读取图片列数
        images = fread(fp, inf, 'unsigned char');%读取数据
        images = reshape(images, numCols, numRows, numImages);%转化成28X28X6000
        images = permute(images,[2 1 3]);%旋转
        images = images/255;%让图片更加清晰
        y=images;
        fclose(fp);%关闭文件
    end
    

    读取label数据

    function lables = loadmnistlabels()
    	fp = fopen('文件保存路径', 'r');
    	assert(fp ~= -1, ['Could not open ', '文件保存路径', '']);
    	magic = fread(fp, 1, 'int32', 0, 'ieee-be');
    	assert(magic == 2049, ['Bad magic number in ', '文件保存路径', '']);
    	numLabels = fread(fp, 1, 'int32', 0, 'ieee-be');
    	lables = fread(fp, inf, 'unsigned char');%
    	assert(size(lables,1) == numLabels, 'Mismatch in label count');
    	fclose(fp);
    end
    

    特征提取

    虽然数据集中,每一张相片只有28x28像素,但是若是将每个像素的数值作为神经网络的输入,会导致神经元的数量过大,神经元特别是输入到输入层神经元的连接变得非常复杂,导致网络训练的速度变慢,推广能力变差。而且图片中并不是每一个像素都包含了识别该图片所必备的信息。因此要对照片进行特征提取,减少不必要信息输入,简化网络结构,增加训练速度和网络的推广性。特征提取的思路如下:在以4x4个像素为一个单位,原来的28x28像素图片分成49个4x4的单位,将里面的16个像素的数值相加,用这个数表示这个单位的特征。这样就把原本28x28=784个像素的照片变成了7x7=49的特征矩阵。

    function y=takefeatures(images)
    	a=size(images);
    	b=a(3);
    	images=mat2cell(images,4*ones(1,7),4*ones(1,7),ones(1,b));%转为元胞数组,4X4X7x60000
    	images=cellfun(@(x) sum(x(:)),images);%4X4元胞求和,转换成 矩阵
    	images=reshape(images,[49,1,b]);%再转换成49X1X60000
    	y=0.1*images;%相当于归一化
    end
    
    

    BP神经网络代码

    function [y1,y2,y3,y4]=bpnet_handwritednum(images,lables,innum,hdnum,otnum,learn_rate,traic)
    	
    	in_w=double(rand(49,innum));%隐含层1权重
    	hd_w=double(rand(innum,hdnum));%隐含层2权重
    	ot_w=double(rand(hdnum,otnum));%输出层权重
    	in_incell(1,49)=(0);%保存隐含层1各个节点的输入值
    	in_outcell(1,innum)=(0);%保存隐含层1各个节点的输出值
    	hd_incell(1,hdnum)=(0);%保存隐含层2各个节点的输入值
    	hd_outcell(1,hdnum)=(0);%保存隐含层2各个节点的输出值
    	ot_incell(1,otnum)=(0);%保存输出层各个节点的输入值
    	ot_outcell(1,otnum)=(0);%保存输出层各个节点的输出值
    	ot_error(1,otnum)=(0);%保存输出各节点的偏差
    	hd_error(1,hdnum)=(0);%保存反向传后递隐含层各节点的误差
    	in_error(1,innum)=(0);%保存反向传播后隐含层1各节点的误差
    	bi=size(images);
    	count=0;
    	canout=0;
    	derror(traic)=0;%
    	tic
    	while(1)
    	
    	  count=count+1;
    	    derror(count)=canout/bi(3);%误差计算,实际上没有用到
    	     if count>=traic
    	       break;
    	     end
    	    canout=0;
    	for i=1:1:bi(3)
    	     in_incell=images(:,1,i)'*in_w;
    	     if min(in_incell)<=-500
    	         in_incell=mapminmax(in_incell,-400,20);
    	     end
    	    % in_incell=mapminmax(in_incell,-2,2);   原本用来归一化,但是导致训练过程变长,所以不用
    	%隐含层1各个节点的输出
    	    in_outcell=1./(1+exp(-in_incell));
    	%隐含层2各个节点的输入
    	     hd_incell=in_outcell*hd_w;
    	    % hd_incell=mapminmax(hd_incell,0,1);   原本用来归一化,但是训练过程变长,所以不用
    	%隐含层2各个节点的输出
    	    hd_outcell=1./(1+exp(-hd_incell));
    	%输出层各个节点的输入
    	    ot_incell=hd_outcell*ot_w;
    	   % ot_incell=mapminmax(ot_incell,0,1);    原本用来归一化,但是训练过程变长,所以不用
    	%输出层的输出
    	    ot_outcell=1./(1+exp(-ot_incell));
    	    % ot_outcell=mapminmax( ot_outcell,0,1);
    	 
    	switch lables(i)%判断图片对应的输出
    	    case 0
    	        ideal_out=[1,0,0,0,0,0,0,0,0,0];
    	    case 1
    	        ideal_out=[0,1,0,0,0,0,0,0,0,0];
    	    case 2
    	        ideal_out=[0,0,1,0,0,0,0,0,0,0];
    	    case 3
    	        ideal_out=[0,0,0,1,0,0,0,0,0,0];
    	    case 4
    	        ideal_out=[0,0,0,0,1,0,0,0,0,0];
    	    case 5
    	        ideal_out=[0,0,0,0,0,1,0,0,0,0];
    	    case 6
    	        ideal_out=[0,0,0,0,0,0,1,0,0,0];
    	    case 7
    	        ideal_out=[0,0,0,0,0,0,0,1,0,0];
    	    case 8
    	        ideal_out=[0,0,0,0,0,0,0,0,1,0];
    	    case 9
    	        ideal_out=[0,0,0,0,0,0,0,0,0,1];
    	end
    	%计算实际输出和理想输出之间的偏差
    	   ot_error=ideal_out-ot_outcell;    
    	       %ot_error=0.5*(ot_error.*ot_error);  
    	       %原本是按照推导用欧氏几何距离作为误差计算,但是后来发现直接用差值效果更好
    	   canout=canout+ot_error*ot_error';
    	%反向传播隐含层各个节点的误差
    	  hd_error=ot_error*ot_w';
    	       % hd_error= (exp(-ot_incell)./(exp(-ot_incell) + 1).^2).*ot_error*ot_w';
    	        %原本是按照推导用应该用上述公式计算误差,但是后来发现直接用权值乘效果跟更好
    	%反向传播输入层各个节点的误差
    	in_error=hd_error*hd_w';
    	% %输入层权值更新
    	      %in_w= in_w+learn_rate*images(:,1,i).*(exp(-images(:,1,i)')./(exp(-images(:,1,i)') + 1).^2)'.*in_error';
    	        in_w= in_w+learn_rate*images(:,1,i)*(exp(-in_incell)./(exp(-in_incell) + 1).^2).*in_error;
    	%隐含层2权值更新      
    	        hd_w= hd_w+learn_rate*in_outcell'*(exp(-hd_incell)./(exp(-hd_incell) + 1).^2).*hd_error;
    	%隐含层1权值更新
    	        ot_w=ot_w+learn_rate*hd_outcell'*(exp(-ot_incell)./(exp(-ot_incell) + 1).^2).*ot_error;
    	
    	end
    	end
    	toc
    	y1=in_w;
    	y2=hd_w;
    	y3=ot_w;
    	y4=derror;
    end
    

    测试正确率代码

    function y=bpnet_test(data,lables,in_w,hd_w,ot_w)
        isright=0;
        error(10)=0;
        yes(10)=0;
        a=1;
        b=size(lables);
        en=b(1);
        for i=1:1:en
        %隐含层1各个节点的输入
             in_incell=data(:,1,i)'*in_w;
        %隐含层1各个节点的输出
            in_outcell=1./(1+exp(-in_incell));
        %隐含层2各个节点的输入
             hd_incell=in_outcell*hd_w;
        %隐含层2各个节点的输出
            hd_outcell=1./(1+exp(-hd_incell));
        %输出层各个节点的输入
            ot_incell=hd_outcell*ot_w;
        %输出层的输出
            ot_outcell=1./(1+exp(-ot_incell));
              switch lables(i)%判断图片对应的输出
            case 0
                ideal_out=[1,0,0,0,0,0,0,0,0,0];
            case 1
                ideal_out=[0,1,0,0,0,0,0,0,0,0];
            case 2
                ideal_out=[0,0,1,0,0,0,0,0,0,0];
            case 3
                ideal_out=[0,0,0,1,0,0,0,0,0,0];
            case 4
                ideal_out=[0,0,0,0,1,0,0,0,0,0];
            case 5
                ideal_out=[0,0,0,0,0,1,0,0,0,0];
            case 6
                ideal_out=[0,0,0,0,0,0,1,0,0,0];
            case 7
                ideal_out=[0,0,0,0,0,0,0,1,0,0];
            case 8
                ideal_out=[0,0,0,0,0,0,0,0,1,0];
            case 9
                ideal_out=[0,0,0,0,0,0,0,0,0,1];
            end
            a=lables(i)+1;
            if find(ideal_out==max(ideal_out))==find(ot_outcell==max(ot_outcell))
                isright=isright+1;
                yes(a)=yes(a)+1;
            else
                error(a)=error(a)+1;
            end
        end
           error./yes
            y=isright/en;
    end
    

    实验测试:
    在这里插入图片描述

    在这里插入图片描述

    结论:可以看到,用训练集,训练400次以后,用测试集测试,得到的正确率为0.9404.正确率较高,符合预期。各个数据的错误率如图所示。可以看到5和8的错误率最高,但是正确率都在百分之九十左右。结果较为满意。

    有兴趣的同学可以利用自己手写的数字进行测试。实际上本实验之中训练出来的 网络泛化性较差,用不在数据集之中的手写数字进行测试得出的正确率没有这么高,有待改进。

    代码较多,阅读可能有点困难,见谅。若有错误,欢迎指正交流。

    展开全文
  • 希望对大家有帮助!
  • 该课题为基于MATLAB bp神经网络的手写汉字识别系统。可以利用鼠标手写中文汉字进行训练,测试,可以识别任何字体,只需要到GUI界面面板更换即可。在GUI界面就可以随写随训练中文,不需要到后台手动更换文字训练,...
  • BP神经网络实现手写数字识别matlab实现
  • MATLAB--基于BP神经网络的手写数字识别

    千次阅读 多人点赞 2020-03-06 21:12:13
    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的提取链接

    展开全文
  • 代码主要实现了对手写数字识别,可通过代码得到识别的错误率,
  • BP(Back Propagation)神经网络是1986年由Rumelhart和McCelland为首的科研小组提出,参见他们发表在Nature上的论文 Learning representations by back-propagating errors 。 BP神经网络是一种按误差逆传播算法训练...

    一、简介

    1 概述\ BP(Back Propagation)神经网络是1986年由Rumelhart和McCelland为首的科研小组提出,参见他们发表在Nature上的论文 Learning representations by back-propagating errors 。

    BP神经网络是一种按误差逆传播算法训练的多层前馈网络,是目前应用最广泛的神经网络模型之一。BP网络能学习和存贮大量的 输入-输出模式映射关系,而无需事前揭示描述这种映射关系的数学方程。它的学习规则是使用最速下降法,通过反向传播来不断 调整网络的权值和阈值,使网络的误差平方和最小。

    2 BP算法的基本思想\ 上一次我们说到,多层感知器在如何获取隐层的权值的问题上遇到了瓶颈。既然我们无法直接得到隐层的权值,能否先通过输出层得到输出结果和期望输出的误差来间接调整隐层的权值呢?BP算法就是采用这样的思想设计出来的算法,它的基本思想是,学习过程由信号的正向传播与误差的反向传播两个过程组成。\ 正向传播时,输入样本从输入层传入,经各隐层逐层处理后,传向输出层。若输出层的实际输出与期望的输出(教师信号)不符,则转入误差的反向传播阶段。\ 反向传播时,将输出以某种形式通过隐层向输入层逐层反传,并将误差分摊给各层的所有单元,从而获得各层单元的误差信号,此误差信号即作为修正各单元权值的依据。\ 这两个过程的具体流程会在后文介绍。

    BP算法的信号流向图如下图所示\ 在这里插入图片描述\ 3 BP网络特性分析——BP三要素\ 我们分析一个ANN时,通常都是从它的三要素入手,即\ 1)网络拓扑结构;\ 2)传递函数;\ 3)学习算法。\ 在这里插入图片描述

    每一个要素的特性加起来就决定了这个ANN的功能特性。所以,我们也从这三要素入手对BP网络的研究。\ 3.1 BP网络的拓扑结构\ 上一次已经说了,BP网络实际上就是多层感知器,因此它的拓扑结构和多层感知器的拓扑结构相同。由于单隐层(三层)感知器已经能够解决简单的非线性问题,因此应用最为普遍。三层感知器的拓扑结构如下图所示。\ 一个最简单的三层BP:\ 在这里插入图片描述\ 3.2 BP网络的传递函数\ BP网络采用的传递函数是非线性变换函数——Sigmoid函数(又称S函数)。其特点是函数本身及其导数都是连续的,因而在处理上十分方便。为什么要选择这个函数,等下在介绍BP网络的学习算法的时候会进行进一步的介绍。\ 单极性S型函数曲线如下图所示。\ 在这里插入图片描述\ 双极性S型函数曲线如下图所示。\ 在这里插入图片描述\ 3.3 BP网络的学习算法\ BP网络的学习算法就是BP算法,又叫 δ 算法(在ANN的学习过程中我们会发现不少具有多个名称的术语), 以三层感知器为例,当网络输出与期望输出不等时,存在输出误差 E ,定义如下\ 在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述\ 下面我们会介绍BP网络的学习训练的具体过程。

    4 BP网络的训练分解\ 训练一个BP神经网络,实际上就是调整网络的权重和偏置这两个参数,BP神经网络的训练过程分两部分:

    前向传输,逐层波浪式的传递输出值;\ 逆向反馈,反向逐层调整权重和偏置;\ 我们先来看前向传输。\ 前向传输(Feed-Forward前向反馈)\ 在训练网络之前,我们需要随机初始化权重和偏置,对每一个权重取[ − 1 , 1 ] [-1,1][−1,1]的一个随机实数,每一个偏置取[ 0 , 1 ] [0,1][0,1]的一个随机实数,之后就开始进行前向传输。

    神经网络的训练是由多趟迭代完成的,每一趟迭代都使用训练集的所有记录,而每一次训练网络只使用一条记录,抽象的描述如下:

    while 终止条件未满足: for record:dataset: trainModel(record)

    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述\ 在这里插入图片描述\ 4.1 逆向反馈(Backpropagation)\ 在这里插入图片描述\ 在这里插入图片描述\ 4.2 训练终止条件\ 每一轮训练都使用数据集的所有记录,但什么时候停止,停止条件有下面两种:\ 设置最大迭代次数,比如使用数据集迭代100次后停止训练\ 计算训练集在网络上的预测准确率,达到一定门限值后停止训练

    5 BP网络运行的具体流程\ 5.1 网络结构\ 输入层有n nn个神经元,隐含层有p pp个神经元,输出层有q qq个神经元。\ 5.2 变量定义\ 在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述\ 第九步:判断模型合理性\ 判断网络误差是否满足要求。\ 当误差达到预设精度或者学习次数大于设计的最大次数,则结束算法。\ 否则,选取下一个学习样本以及对应的输出期望,返回第三部,进入下一轮学习。

    6 BP网络的设计\ 在进行BP网络的设计是,一般应从网络的层数、每层中的神经元个数和激活函数、初始值以及学习速率等几个方面来进行考虑,下面是一些选取的原则。\ 6.1 网络的层数\ 理论已经证明,具有偏差和至少一个S型隐层加上一个线性输出层的网络,能够逼近任何有理函数,增加层数可以进一步降低误差,提高精度,但同时也是网络 复杂化。另外不能用仅具有非线性激活函数的单层网络来解决问题,因为能用单层网络解决的问题,用自适应线性网络也一定能解决,而且自适应线性网络的 运算速度更快,而对于只能用非线性函数解决的问题,单层精度又不够高,也只有增加层数才能达到期望的结果。\ 6.2 隐层神经元的个数\ 网络训练精度的提高,可以通过采用一个隐含层,而增加其神经元个数的方法来获得,这在结构实现上要比增加网络层数简单得多。一般而言,我们用精度和 训练网络的时间来恒量一个神经网络设计的好坏:\ (1)神经元数太少时,网络不能很好的学习,训练迭代的次数也比较多,训练精度也不高。\ (2)神经元数太多时,网络的功能越强大,精确度也更高,训练迭代的次数也大,可能会出现过拟合(over fitting)现象。\ 由此,我们得到神经网络隐层神经元个数的选取原则是:在能够解决问题的前提下,再加上一两个神经元,以加快误差下降速度即可。

    6.3 初始权值的选取\ 一般初始权值是取值在(−1,1)之间的随机数。另外威得罗等人在分析了两层网络是如何对一个函数进行训练后,提出选择初始权值量级为s√r的策略, 其中r为输入个数,s为第一层神经元个数。

    6.4 学习速率\ 学习速率一般选取为0.01−0.8,大的学习速率可能导致系统的不稳定,但小的学习速率导致收敛太慢,需要较长的训练时间。对于较复杂的网络, 在误差曲面的不同位置可能需要不同的学习速率,为了减少寻找学习速率的训练次数及时间,比较合适的方法是采用变化的自适应学习速率,使网络在 不同的阶段设置不同大小的学习速率。

    6.5 期望误差的选取\ 在设计网络的过程中,期望误差值也应当通过对比训练后确定一个合适的值,这个合适的值是相对于所需要的隐层节点数来确定的。一般情况下,可以同时对两个不同 的期望误差值的网络进行训练,最后通过综合因素来确定其中一个网络。

    7 BP网络的局限性\ BP网络具有以下的几个问题:

    (1)需要较长的训练时间:这主要是由于学习速率太小所造成的,可采用变化的或自适应的学习速率来加以改进。\ (2)完全不能训练:这主要表现在网络的麻痹上,通常为了避免这种情况的产生,一是选取较小的初始权值,而是采用较小的学习速率。\ (3)局部最小值:这里采用的梯度下降法可能收敛到局部最小值,采用多层网络或较多的神经元,有可能得到更好的结果。

    8 BP网络的改进\ P算法改进的主要目标是加快训练速度,避免陷入局部极小值等,常见的改进方法有带动量因子算法、自适应学习速率、变化的学习速率以及作用函数后缩法等。 动量因子法的基本思想是在反向传播的基础上,在每一个权值的变化上加上一项正比于前次权值变化的值,并根据反向传播法来产生新的权值变化。而自适应学习 速率的方法则是针对一些特定的问题的。改变学习速率的方法的原则是,若连续几次迭代中,若目标函数对某个权倒数的符号相同,则这个权的学习速率增加, 反之若符号相反则减小它的学习速率。而作用函数后缩法则是将作用函数进行平移,即加上一个常数。

    二、源代码

    ``` function varargout = numberreconginize(varargin) % NUMBERRECONGINIZE MATLAB code for numberreconginize.fig % NUMBERRECONGINIZE, by itself, creates a new NUMBERRECONGINIZE or raises the existing % singleton*. % % H = NUMBERRECONGINIZE returns the handle to a new NUMBERRECONGINIZE or the handle to % the existing singleton*. % % NUMBERRECONGINIZE('CALLBACK',hObject,eventData,handles,...) calls the local % function named CALLBACK in NUMBERRECONGINIZE.M with the given input arguments. % % NUMBERRECONGINIZE('Property','Value',...) creates a new NUMBERRECONGINIZE or raises the % existing singleton*. Starting from the left, property value pairs are % applied to the GUI before numberreconginizeOpeningFcn gets called. An % unrecognized property name or invalid value makes property application % stop. All inputs are passed to numberreconginize_OpeningFcn via varargin. % % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one % instance to run (singleton)". % % See also: GUIDE, GUIDATA, GUIHANDLES

    % Edit the above text to modify the response to help number_reconginize

    % Last Modified by GUIDE v2.5 06-Apr-2020 18:32:38

    % Begin initialization code - DO NOT EDIT guiSingleton = 1; guiState = struct('guiName', mfilename, ... 'guiSingleton', guiSingleton, ... 'guiOpeningFcn', @numberreconginizeOpeningFcn, ... 'guiOutputFcn', @numberreconginizeOutputFcn, ... 'guiLayoutFcn', [] , ... 'guiCallback', []); if nargin && ischar(varargin{1}) guiState.gui_Callback = str2func(varargin{1}); end

    if nargout [varargout{1:nargout}] = guimainfcn(guiState, varargin{:}); else guimainfcn(guiState, varargin{:}); end % End initialization code - DO NOT EDIT

    % --- Executes just before numberreconginize is made visible. function numberreconginizeOpeningFcn(hObject, eventdata, handles, varargin) % This function has no output args, see OutputFcn. % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % varargin command line arguments to numberreconginize (see VARARGIN)

    % Choose default command line output for number_reconginize handles.output = hObject;

    % Update handles structure guidata(hObject, handles);

    % UIWAIT makes number_reconginize wait for user response (see UIRESUME) % uiwait(handles.figure1);

    % --- Outputs from this function are returned to the command line. function varargout = numberreconginizeOutputFcn(hObject, eventdata, handles) % varargout cell array for returning output args (see VARARGOUT); % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA)

    % Get default command line output from handles structure varargout{1} = handles.output;

    % --- Executes on button press in openimage. function openimageCallback(hObject, eventdata, handles) % hObject handle to openimage (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) [filename,pathname]=uigetfile({'.png';'.bmp';'.tif';'.jpg';'.'},'载入图像'); if isequal(filename,0)|isequal(pathname,0) errordlg('没有选中文件','出错'); return; else file=[pathname,filename]; global S %设置一个全局变量S,保存初始图像路径,以便之后的还原操作 S=file; x=imread(file); set(handles.axes1,'HandleVisibility','ON'); axes(handles.axes1); function edit1_Callback(hObject, eventdata, handles) % hObject handle to edit1 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA)

    % Hints: get(hObject,'String') returns contents of edit1 as text % str2double(get(hObject,'String')) returns contents of edit1 as a double

    % --- Executes during object creation, after setting all properties. function edit1_CreateFcn(hObject, eventdata, handles) % hObject handle to edit1 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called ```

    三、运行结果

    在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述

    在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述\ 在这里插入图片描述

    四、备注

    版本:2014a

    展开全文
  • BP神经网络实现手写数字识别matlab实现
  • BP神经网络实现手写数字识别matlab实现matlab
  • BP神经网络识别手写数字项目代码,matlab版本,附带图片识别包,直接使用。原理及代码分析:https://blog.csdn.net/huang_miao_xin/article/details/51364152 因为原程序和博主发的解析有点问题,花了点时间处理了,...
  • 基于BP神经网络的手写数字识别实验报告和matlab仿真源码。
  • 手写数字识别】基于BP神经网络手写数字识别matlab源码含GUI.zip
  • 手写数字识别】基于BP神经网络手写数字识别matlab源码含GUI.md
  • BP神经网络识别手写数字项目解析及matlab实现

    万次阅读 多人点赞 2018-08-08 10:15:20
    BP神经网络指传统的人工神经网络,相比于卷积神经网络(CNN)来说要简单些。 人工神经网络具有复杂模式和进行联想、推理记忆的功能, 它是解决某些传统方法所无法解决的问题的有力工具。目前, 它日益受到重视, 同时其他...

    BP神经网络指传统的人工神经网络,相比于卷积神经网络(CNN)来说要简单些。
    人工神经网络具有复杂模式和进行联想、推理记忆的功能, 它是解决某些传统方法所无法解决的问题的有力工具。目前, 它日益受到重视, 同时其他学科的发展, 为其提供了更大的机会。1986 年, Romelhart 和Mcclelland提出了误差反向传播算法(Error Back Propagation Algorithm) ,简称BP 算法,由于多层前馈网络的训练经常采用误差反向传播算法, 人们也把多层前馈网络称为BP 网络。

    为了便于阅读,下面说一下全文的逻辑顺序:
    1,通俗说下神经网络的结构和工作原理,简单好理解,推荐观看
    2,逆向传播算法的数学推导,如果觉得太复杂可以暂时跳过
    3,matlab代码和图像库
     

    (1) 大白话讲解传统神经网络

    首先,我们看一下神经网络的基本单元——单个的神经元:

    图中圆形表示一个神经元,我们知道,一个神经元接收相邻的神经元传来的刺激,神经元对这些刺激以不同的权重进行积累,到一定的时候产生自己的刺激将其传递给一些与它相邻的神经元。这样工作的无数个神经元便构成了人脑对外界的感知。而人脑对世界的学习的机制就是通过调节这些相邻连接的神经元刺激的权重。
    在图中,周围神经元传过来的刺激表示为Y,权重表示为W,圆形表示的神经元得到的刺激是所有刺激按照权重累加起来,即

    同时这个神经元作为网络的一份子,也像其他神经元一样需要向外传播刺激信号,但是不是直接把s传播,而是传播一个f(s)出去,为什么呢?其实无关大局,我们后面分析。其中f(s)学名称为“激活函数”,常用的函数如下:

    好了,理解到这里如果没什么问题的话,恭喜你你已经入门了,现在我们把这一个个的基本单元连接起来,就构成我们最终的神经网络了。传统的神经网络结构如下图所示:

    是不是觉得很乱?不着急我们一点一点看,由整体到细微来解剖它。首先整体上,它的结构分为三部分,输入层,隐藏层和输出层,一般输入层和输出层各一个,隐藏层若干个,图中画出了一个。细微处,连接结构上,后一层的每个神经元都由前一层的所有神经元连接进来。
    手写数字识别实验使用的是三层的神经网络结构,即只有一个隐藏层,下面以此说明。
    下面说明一下各层的表示和各层的关系:
    输入层:X=(x1,x2,x3…xn)
    隐藏层:Y=(y1,y2,y3…ym)
    输出层:O=(o1,o2,o3…or)

    两个权重:
    输入层到隐藏层的权重:V=(V1,V2,V3…Vm),Vj是一个列向量,表示输入层所有神经元通过Vj加权,得到隐藏层的第j个神经元
    隐藏层到输出层的权重:W=(W1,W2,W3…Wr),Wk是一个列向量,表示隐藏层的所有神经元通过Wk加权,得到输出层的第k个神经元

    根据我们上面说到的单个神经元的刺激传入和刺激传出,相信到这里很多人应该已经得出下面的各层之间的关系了:


    到这里,神经网络的工作过程就清楚一些了。实例说明一下,假设输入是一张图像, 16x16大小,转换为一个二维的灰度值矩阵,再把每一行拼接在上一行的末尾,拼接成一个1x256的行向量,作为输入层的输入,即X,接下来按照公式2就可以计算出隐藏层,然后根据公式1又可以计算出输出层,输出层的输出就得到了。在这个手写数字识别的项目中,我使用的图片输入正是16x16,所以输入层有256个神经元,隐藏层的神经元我取了64个,最后的输出层神经元我取的是10个,为什么是10个呢?因为数字0到9一共10个,期望上是,比如输入一张写着数字1的图像,在输出端得到的输出是{1 0 0 0 0 0 0 0 0 0},输入的图像为2时,输出{ 0 1 0 0 0 0 0 0 0 0},以此类推,实际上输出的未必就是刚好1和刚好0,经过调参和训练,基本是输出0.9多和正负的0.0多,不过也足够了,仅仅用判断最大值所在位置的方式就可以识别到图像上的数字。

    至此,我们已经了解了整个网络的结构和正向工作的具体流程。可以说我们已经对神经网络理解了有50%了。为什么才50%呢?仔细想想相信你会发现,我们还不知道两个在网络中很重要的量,就是权重矩阵W和V。

    如何求得W和V呢,这里要用到一种算法,就是误差反向传播算法(Error Back Propagation Algorithm) ,简称BP 算法。说的很晦涩,我们来翻译成人话。先来看看算法的工作过程,首先随机地初始化W和V的值,然后代入一些图片进行计算,得到一个输出,当然由于W和V参数不会刚好很完美,输出自然不会是像上文说的,刚好就是{1 0 0 0 0 0 0 0 0 0}这一类,所以存在误差,根据这个误差就可以反过来修正W和V的值,修正后的W和V可以使输出更加的靠近于理想的输出,这就是所谓的“误差反向传播”的意思,修正一次之后,再代入其他一些图片,输出离理想输出又靠近了一点,我们又继续计算误差,然后修正W和V的值,就这样经过很多次的迭代计算,最终多次修正得到了比较完美的W和V矩阵,它可以使得输出非常靠近于理想的输出,至此我们的工作完成度才是100%了。这种在输出端计算误差,根据误差来作调节的思想,学自动化的或者接触过飞思卡尔一类的智能车比赛的同学体会应该是比较深的,跟PID自控算法有很大相似性。

    下面是数学推导,关于实际输出和理想输出之间的误差如何具体来调节W和V的值,调节多少的问题。上面说过了,暂时不理解的话可以先跳过推导,看最后的结论就好,自己最后跟着代码实践一遍,有了更深的体会,慢慢会理解的。
     

    (2)逆向传播算法的数学推导

    输出层的理想输出:d=(d1,d2,d3…dr),例如{1 0 0 0 0 0 0 0 0 0}和{0 1 0 0 0 0 0 0 0 0}等
    假设实际输出和理想输出之间的差距是E,明显W是一个关于输入X,权重W和V,输出O的函数。要修正W,则需要知道具体的修正增量ΔW,离散情况下,表征微分增量,可以得到:


    这样,改变η的大小即可改变每一次调节的幅度,η大的话调节更快,小则调节慢,但是过大容易导致振荡,这一点也跟PID中的比例系数P是一样的。一般η的大小需要经过多次尝试来找到合适值。

    好了,到这里神经网络就讲解完毕,下面是一个较次要的内容,我们上面说了,通过不断迭代来调整权重W和V,那么如何衡量迭代是否可以停止了呢。一个自然的想法是判断每次的输出和理想输出是否足够接近,所以我们可以用算向量距离的方法,跟均方差是一个 道理,如下:

    这样,主要s足够小,迭代就可以结束了。


    (3)实践

    下面是我试验用的MATLAB代码。

    训练部分:recognize_handwriting_numbers_by_simple_NN_train.m

    V=double(rand(256,64));
    W=double(rand(64,10));
    delta_V=double(rand(256,64));
    delta_W=double(rand(64,10));
     
    yita=0.2;%缩放系数,有的文章称学习率
    yita1=0.05;%我自己加的参数,缩放激活函数的自变量防止输入过大进入函数的饱和区,可以去掉体会一下变化
    train_number=9;%训练样本中,有多少个数字,一共9个,没有0
    train_num=30;%训练样本中,每种数字多少张图,一共100张
    x=double(zeros(1,256));%输入层
    y=double(zeros(1,64));%中间层,也是隐藏层
    output=double(zeros(1,10));%输出层
    tar_output=double(zeros(1,10));%目标输出,即理想输出
    delta=double(zeros(1,10));%一个中间变量,可以不管
     
    %记录总的均方差便于画图
    s_record=1:1000;
    tic %计时
    for train_control_num=1:1000   %训练次数控制,在调参的最后发现1000次其实有多了,大概400次完全够了
        s=0;
    %读图,输入网络
    for number=1:train_number
    ReadDir=['E:\Matlab\recognize_handwiting_numbers\train_lib\'];%读取样本的路径
    for num=1:train_num  %控制多少张
    photo_name=[num2str(number),num2str(num,'%05d'),'.png'];%图片名
    photo_index=[ReadDir,photo_name];%路径加图片名得到总的图片索引
    photo_matrix=imread(photo_index);%使用imread得到图像矩阵
    photo_matrix=uint8(photo_matrix<=230);%二值化,黑色是1
    tmp=photo_matrix';
    tmp=tmp(:);%以上两步完成了图像二维矩阵转变为列向量,256维,作为输入
    %计算输入层输入
    x=double(tmp');%转化为行向量因为输入层X是行向量,并且化为浮点数
    %得到隐层输入
    y0=x*V;
    %激活
    y=1./(1+exp(-y0*yita1));
    %得到输出层输入
    output0=y*W;
    output=1./(1+exp(-output0*yita1));
    %计算预期输出
    tar_output=double(zeros(1,10));
    tar_output(number)=1.0;
    %计算误差
    %按照公式计算W和V的调整,为了避免使用for循环比较耗费时间,下面采用了直接矩阵乘法,更高效
    delta=(tar_output-output).*output.*(1-output);
    delta_W=yita*repmat(y',1,10).*repmat(delta,64,1);
    tmp=sum((W.*repmat(delta,64,1))');
    tmp=tmp.*y.*(1-y);
    delta_V=yita*repmat(x',1,64).*repmat(tmp,256,1);
    %计算均方差
    s=s+sum((tar_output-output).*(tar_output-output))/10;
    %更新权值
    W=W+delta_W;
    V=V+delta_V;
    end
    end
    s=s/train_number/train_num  %不加分号,随时输出误差观看收敛情况
    train_control_num           %不加分号,随时输出迭代次数观看运行状态
    s_record(train_control_num)=s;%记录
    end
    toc %计时结束
    plot(1:1000,s_record);
    

     

    测试部分:recognize_handwriting_numbers_by_simple_NN_test.m

     

    correct_num=0;%记录正确的数量
    incorrect_num=0;%记录错误数量
    test_number=9;%测试集中,一共多少数字,9个,没有0
    test_num=100;%测试集中,每个数字多少个,最大100个
    % load W;%%之前训练得到的W保存了,可以直接加载进来
    % load V;
    % load yita1;
     
    %记录时间
    tic %计时开始
    for number=1:test_number
    ReadDir=['E:\Matlab\recognize_handwiting_numbers\test_lib\'];
    for num=1:test_num  %控制多少张
    photo_name=[num2str(number),num2str(num,'%05d'),'.png'];
    photo_index=[ReadDir,photo_name];
    photo_matrix=imread(photo_index);
    %大小改变
    photo_matrix=imresize(photo_matrix,[16 16]);
    %二值化
    photo_matrix=uint8(photo_matrix<=230);%黑色是1
    %行向量
    tmp=photo_matrix';
    tmp=tmp(:);
    %计算输入层输入
    x=double(tmp');
    %得到隐层输入
    y0=x*V;
    %激活
    y=1./(1+exp(-y0*yita1));
    %得到输出层输入
    o0=y*W;
    o=1./(1+exp(-o0*yita1));
    %最大的输出即是识别到的数字
    [o,index]=sort(o);
    if index(10)==number
        correct_num=correct_num+1
    else
        incorrect_num=incorrect_num+1;
        %显示不成功的数字,显示会比较花时间
    %     figure(incorrect_num)
    %     imshow((1-photo_matrix)*255);
    %     title(num2str(number));
    end
    end
    end
    correct_rate=correct_num/test_number/test_num
    toc %计时结束
    

     

    使用的库来自于http://www.ee.surrey.ac.uk/CVSSP/demos/chars74k/#download
    使用其中的EnglishFnt.tgz库,从其中的数字选出前100张作为训练,再另外取100张作为测试。图片集有需要也可以邮件我发送。

     

    运行结果:

    最后调参得到比较好的结果,使用η=0.2,η1=0.05,在我电脑上,i5-3210M,4G内存,迭代1000次所需要的时间是468s,最终得到下面的曲线,横坐标是训练的迭代次数,纵坐标是均方差,可以看到,其实在350次迭代的时候已经取得了很小的均方差,考虑时间和性能的折中的话,迭代350次已经可以了。

    最后训练结束,使用η=0.2,η1=0.05,用测试集测试,可以得到89.11%的准确率,继续调节参数,曾经可以得到90.56%的准确率,不过也难再上去,估计瓶颈了。

    如果你跟着本文的步骤一步一步下来,最后还自己动手打一遍代码,应该会很好的理解了传统类型的神经网络,对接下来理解卷积神经网络应该会有些帮助。
     

    个人对神经网络的的一些理解:

           以识别图片手写数字为例,图片中黑色像素点和白色像素点之间的空间编排关系构成了我们看到的数字,如果我们能找到一个很厉害的方程组,方程的输入参数是一张图片,返回一个数字表示识别结果,那肯定是很理想的,但是可惜,很难找到的方程来映射图片像素点的空间排布和识别结果这样的一种关系。而神经网络刚好就完成了这样的映射功能,所有的关于像素点空间排布信息的解析都隐藏于矩阵W和V之中,所以W和V实际上代表了这样一种映射关系。而神经网络聪明的地方在于,当这样的映射关系未知时,我们设计了一套机理让它自己来寻找,这就是学习和训练的过程,而最后得到的W和V就是学习的结果,这个过程很像婴儿开始认东西的过程,一开始婴儿的认知体系是空白的,像刚随机初始化的W和V,我们给它看一本书,像给了网络一个输入,告诉他这个是“书”,像告诉网络,理想输出应该是“书”,他会开始尝试来理解,建立书这个物品到“书”这个字的映射关系,一开始他会犯错,看到相似的比如一张纸也会认为是书,但是在看到更多的书之后,并且我们告诉他这个是“书”之后,他又会不断修正这样一种映射关系,最后建立完整的对于书这样一种物品到“书”这个字的映射过程,初步的认知体系建立。现在可以说说上面的“激活函数”是干嘛用的了,可以想象,自然界的各种各样的映射关系显然是比较复杂的,关靠线性关系是无力描述的,而神经网络中用的是加权相加的运算,如果没有经过激活函数处理,后层的所有输入都可以由多层之前的信号经过线性运算来得到,一个现象模型显然表现力是远远不够的,所以我们在神经网络模型中加入了非线性的因素,就是激活函数。

     

    //

    转载:https://blog.csdn.net/huang_miao_xin/article/details/51364152

    展开全文
  • 手写数字识别】基于BP神经网络手写数字识别matlab源码含GUI2.zip
  • 摘要在信息化飞速发展的时代,光学字符识别是一个重要的信息录入与信息转化的手段,其中手写数字识别有着广泛地应用,如:邮政编码、统计报表、银行票据等等,因其广泛地应用范围,能带来巨大的经济与社会效益。...
  • 本ZIP文件包含了经典的手写数字的bmp数据,共{0,1,2,……,9}10个类,每个类包含500个数据;然后对图片进行二值化处理,采用patch来对每张image提出特征,最后设计神经网络对特征进行训练,并用得到的net来测试...
  • BP神经网络实现手写数字识别matlab实现,基于bp神经网络的手写数字识别,matlab源码.zip.zip
  • MATLAB神经网络BP手写数字识别.zip
  • 利用MATLAB实现的手写数字识别

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,038
精华内容 415
关键字:

bp手写数字识别matlab

matlab 订阅