BP神经网络识别手写数字项目解析及matlab实现

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)==numbercorrect_num=correct_num+1
elseincorrect_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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/492271.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能家居市场年增速近30%!苹果看齐亚马逊、谷歌,欲开辟三足鼎立

来源&#xff1a;物联网智库整理摘要&#xff1a;作为世界领先的科技巨头&#xff0c;亚马逊、谷歌和苹果相爱相杀许多年。在智能家居领域&#xff0c;三家的“战争”也会随着市场的成熟而更加激烈。尽管苹果目前稍显落后&#xff0c;但未来市场广阔谁主沉浮仍未可知。近日&…

简单实现UITableView索引功能(中英文首字母索引)(一) ByH罗

UITableView索引功能是常见的,主要是获取中英文的首字母并排序&#xff0c;系统自带获取首字母 //系统获取首字母 - (NSString *) pinyinFirstLetter:(NSString*)sourceString {NSMutableString *source [sourceString mutableCopy];CFStringTransform((__bridge CFMutableStr…

matlab——图像细化

所谓细化&#xff0c;就是从原来的图像中去掉一些点&#xff0c;但仍要保持原来的形状。 1、代码如下&#xff1a; close all;clear all;clc; %关闭所有图形窗口&#xff0c;清除工作空间所有变量&#xff0c;清空命令行 I1imread(circles.png); subplot(1,3,1),imshow(I1);…

中国60家最强汽车初创在此!芯片厂高调入局,智能网联强势霸榜

来源&#xff1a;智东西摘要&#xff1a;中国汽车科技最全地图&#xff01;2018年&#xff0c;知名市场研究机构毕马威再次设立了中国汽车科技领先企业50强和新锐企业10强榜单评选&#xff0c;并在近日公布了结果。备选企业包括在智能网联、汽车后市场服务、汽车制造技术、出行…

Python中矩阵库Numpy基本操作

NumPy是一个关于矩阵运算的库&#xff0c;熟悉Matlab的都应该清楚&#xff0c;这个库就是让python能够进行矩阵话的操作&#xff0c;而不用去写循环操作。 下面对numpy中的操作进行总结。 numpy包含两种基本的数据类型&#xff1a;数组和矩阵。 数组(Arrays) >>> …

作业6--团队项目之需求

队员&#xff1a;欧泽波 201306114428 杨洁华 201306114429 赵泽嘉 201306114430 林扬滨 201306114424 学生&#xff08;杨洁华&#xff09;&#xff1a;软件的界面太单调了&#xff0c;不好看&#xff0c;要是有卡通人物就好了&#xff0c;有些题老师也没教&#xff0c;不知道…

专设AI周会 高管悉数到场 微软CEO有多重视人工智能?

来源&#xff1a;CNBC 翻译 | 网易智能 (天门山)据CNBC报道&#xff0c;一般在每周的周四&#xff0c;微软首席执行官萨蒂亚纳德拉(Satya Nadella)和微软高管团队都要在一起开会&#xff0c;讨论该公司越来越多的人工智能&#xff08;AI&#xff09;项目。微软首席技术官凯文斯…

vb的VSFlexGrid控件

多行选中 VSFlexGrid的SelectionMode flexSelectionListBox&#xff0c;现在可以配合Ctrl进行多行选择 循环取值 用vsflexgrid.SelectedRows 可以得到你选择的行的总数量然后用循环可以得到具体的行中具体列的内容Dim Temp As StringDim i As IntegerFor i 0 To VSFlexGrid.…

汽车电子:下一个苹果产业链

来源&#xff1a;安信证券摘要&#xff1a;本文将从“7个层级深度解析”这次产业发展红利带来巨大且丰富的投资机遇。汽车电子产业&#xff0c;预计将是继家电、PC和手机之后又一次全产业链级别的大发展机遇&#xff0c;不同的是&#xff1a;1. 其构成产品附加值更高(高稳定/高…

模块化开发之sea.js实现原理总结

seajs官网说&#xff1a;seajs是一个模块加载器&#xff0c;所以学习它并不难。 在我的理解就是&#xff1a;本来我们是需要手动创建 script标签 引入 js文件的&#xff0c;但用seajs后&#xff0c;它就自动帮我们完成这些工作。 这里只说实现原理&#xff0c;具体使用请看seaj…

mysql获取各种日期

select curdate(); --获取当前日期 select last_day(curdate()); --获取当月最后一天。 select DATE_ADD(curdate(),interval -day(curdate())1 day); --获取本月第一天 select date_add(curdate()-day(curdate())1,interval 1 month); -- 获取下个月的第一天 select DATEDIFF(…

【干货】百度联合清华大学发布国内首个基于AI实践的《产业智能化白皮书》(附报告全文)...

来源&#xff1a;百度AI在4月9日举行的“百度大学 Alpha 学院首期学员毕业典礼”上&#xff0c;百度联合清华大学发布国内首个基于 AI 实践的行业重磅报告&#xff0c;《产业智能化白皮书——人工智能产业化发展地形初现端倪》。这是国内首次从产业演进的视角探讨 AI 与产业融合…

endl与'\n'的区别

endl\n刷新缓冲区&#xff0c;但是以下两段代码&#xff1a; #include<iostream> #include<iomanip> #include<cstdlib> …

全球语种谱系图,看看机器翻译需要跨越的大山

来源&#xff1a;语言春秋编辑 | 北外新闻中心 杨丹蕊摘要&#xff1a;当前机器翻译技术可以分成两类&#xff0c;一种是 Rich Resource NMT&#xff0c;也就是双语语料丰富的语言对&#xff08;比如中文 - 英文&#xff09;&#xff1b;另一种叫 Low Resource NMT&#xff0c…

Big Data Security Part One: Introducing PacketPig

Series Introduction Packetloop CTO Michael Baker (cloudjunky) made a big splash when he presented ‘Finding Needles in Haystacks (the Size of Countries)‘ at Blackhat Europe earlier this year. The paper outlines a toolkit based onApache Pig, Packetpig pack…

美国科学家成功恢复老年人工作记忆,望奠定认知干预疗法基础

来源&#xff1a;科技日报伴随着人体衰老&#xff0c;大脑对信息加工和贮存的能力也必然会下降&#xff0c;但如果这种能力可以被逆转呢&#xff1f;据英国《Nature Neuroscience》杂志8日在线发表的一项研究&#xff0c;美国科学家通过同步脑区节律——按特定节律刺激颞叶和额…

SQL Server--通过存储过程生成表数据的脚本

CREATE PROCEDURE dbo.UspOutputData   tablename sysname AS declare column varchar(1000) declare columndata varchar(1000) declare sql varchar(4000) declare xtype tinyint declare name sysname declare objectId int declare objectname sysname declare ident int…

广告机市场和产品

广告机行业分析 前言 关于广告机&#xff0c;不同的人有不同的认识&#xff0c;此部分主要说明文中所指广告机的范围。 在讨论前&#xff0c;先区分几个概念。 1、 广告机与数字标牌 数字标牌是数字标示牌的简称&#xff0c;指代显示任意信息的显示终端&#xff1b;广告机是指…

《工业大数据白皮书》2019版正式发布

来源&#xff1a;悟空智能科技近日&#xff0c;由中国电子技术标准化研究院、全国信息技术标准化技术委员会大数据标准工作组主编&#xff0c;工业大数据产业应用联盟联合主编&#xff0c;联想集团等多家联盟成员企业参编的《工业大数据白皮书&#xff08;2019版&#xff09;》…

产品金字塔

制造业产品大概可以分为三个层次&#xff0c;第一层为实物&#xff0c;第二层为服务&#xff0c;第三层为体验。其中产品为基础&#xff0c;服务为改善&#xff0c;共同给客户美好的体验。三者组成一个产品金字塔。第一层&#xff0c;实物。比如手机&#xff0c;满足通话、上网…