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

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

  1. BP神经网络识别手写数字项目解析及代码

    这两天在学习人工神经网络,用传统神经网络结构做了一个识别手写数字的小项目作为练手.点滴收获与思考,想跟大家分享一下,欢迎指教,共同进步. 平常说的BP神经网络指传统的人工神经网络,相比于卷积神经网络( ...

  2. MATLAB实现基于BP神经网络的手写数字识别+GUI界面+mnist数据集测试

    文章目录 MATLAB实现基于BP神经网络的手写数字识别+GUI界面+mnist数据集测试 一.题目要求 二.完整的目录结构说明 三.Mnist数据集及数据格式转换 四.BP神经网络相关知识 4.1 ...

  3. 基于BP神经网络的手写数字识别

    基于BP神经网络的手写数字识别 摘要 本文实现了基于MATLAB关于神经网络的手写数字识别算法的设计过程,采用神经网络中反向传播神经网络(即BP神经网络)对手写数字的识别,由MATLAB对图片进行读入 ...

  4. 小生不才:tensorflow实战01-基于bp神经网络的手写数字识别

    前言 利用搭建网络八股,使用简单的bp神经网络完成手写数字的识别. 搭建过程 导入相应的包 获取数据集,划分数据集和测试集并进行简单处理(归一化等) 对数据进行乱序处理 定义网络结构 选择网络优化器以 ...

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

    MATLAB–基于BP神经网络的手写数字识别 在干活的过程中整理下来的,希望对大家有帮助. 手写数字识别技术作为图像处理和模式识别中的研究热点,在大规模数据统计(如行业年检.人口普查等).票据识别.财 ...

  6. Python学习记录 搭建BP神经网络实现手写数字识别

    搭建BP神经网络实现手写数字识别 通过之前的文章我们知道了,构建一个简单的神经网络需要以下步骤 准备数据 初始化假设 输入神经网络进行计算 输出运行结果 这次,我们来通过sklearn的手写数字数据集 ...

  7. BP神经网络实现手写数字识别Python实现,带GUI手写画板

    BP神经网络实现手写数字识别 BP神经网络模型 用tkinter编写用于手写输入的画板 程序运行的效果截图 在B站看了一个机器学习基础的视频( 链接)后,发现到资料里面有一个用BP神经网络对手写数字进 ...

  8. Python神经网络识别手写数字-MNIST数据集

    Python神经网络识别手写数字-MNIST数据集 一.手写数字集-MNIST 二.数据预处理 输入数据处理 输出数据处理 三.神经网络的结构选择 四.训练网络 测试网络 测试正确率的函数 五.完整的 ...

  9. 四、用简单神经网络识别手写数字(内含代码详解及订正)

    本博客主要内容为图书<神经网络与深度学习>和National Taiwan University (NTU)林轩田老师的<Machine Learning>的学习笔记,因此在全 ...

最新文章

  1. skyline粒子效果xml获取
  2. 【中级软考】结构化开发方法是啥,主要包含哪些内容?
  3. 十进制与二进制八进制十六进制的相互转换
  4. SAP UI5 Connection manager
  5. html动态计算高度,透明半透明背景
  6. linux 常识笔记 20160621
  7. POJ 2996, Help Me with the Game
  8. oracle 密码解锁
  9. 维谛技术(Vertiv)隆重举行“笃行——数据中心基础设施智能化管理研讨会”...
  10. AI 隐身术,让你在视频中消失的“黑魔法”,想拥有吗?
  11. 使用 GPG 为极狐GitLab git commit 签名
  12. VMware克隆Linux虚拟机
  13. e^(πi)=-1的最佳解释笔记
  14. SCAU 8615 快乐
  15. hadoop订单项目实战
  16. android 虹软人脸存储,用虹软Android SDK做人脸识别
  17. Unity3D:2D/3D 项目
  18. Excel工作表的移动
  19. PDF小技巧 如何在PDF上添加水印
  20. 浏览器提示无法安全地连接到此页面TLS安全设置未设置为默认怎么办?

热门文章

  1. python怎么写方程条件,条件方程曲线拟合
  2. python数据分析开发环境_在MAC上搭建python数据分析开发环境
  3. 2019头条抖音Java 3面真题,含面试题答案!
  4. 开源开放 | 欢迎选修浙江大学《知识图谱》开放共享慕课
  5. 推荐 10 个饱受好评且功能独特的开源人工智能项目
  6. 10 操作系统第二章 进程管理 死锁、死锁的处理策略 银行家算法
  7. centos 6.5 防火墙开放指定端口
  8. NET(C#):await返回Task的async方法
  9. 如何让css与js分离
  10. NOIP2016天天爱跑步 题解报告【lca+树上统计(桶)】