5/1-1 神经网络识别手写数字及MATLAB程序

5/1-1 神经网络识别手写数字及MATLAB程序

注: 本文参考教材为http://neuralnetworksanddeeplearning.com/

1.介绍

1.1 感知器

一个感知器由输入变量、权重、阈值,输出变量(可视为无激活函数)几个部分组成

在这里插入图片描述
输 出 = { 0 , if  ∑ i = 1 n x i w i < 阈 值   1 , if  ∑ i = 1 i = n x i w i > 阈 值 输出= \begin{cases} 0 , & \text {if $\sum_{i=1}^{n}x_iw_i<阈值$ } \\ 1, & \text{if $\sum_{i=1}^{i=n}x_iw_i>阈值$} \end{cases} ={0,1,if i=1nxiwi<阈值 if i=1i=nxiwi>阈值
偏 置 b = − 阈 值 , w = ( w 1 , w 2 , . . . , w n ) , x = ( x 1 , . . . , x 2 ) 偏置b=-阈值,w=(w_1,w_2,...,w_n),x=(x_1,...,x_2) b=,w=(w1,w2,...,wn),x=(x1,...,x2)上式可写为
输 出 = { 0 , if  w ⋅ x + b < 0   1 , if  w ⋅ x + b > 0 输出= \begin{cases} 0 , & \text {if $w\cdot x+b<0$ } \\ 1, & \text{if $w\cdot x+b>0$} \end{cases} ={0,1,if wx+b<if wx+b>0

1.2 Sigmoid函数

remark1: 由上一小节可看出感知器的输入是0和1,并且运算过程是线性(加法,乘法)

Sigmoid函数是一个在生物学中常见的S型函数,也称为S型生长曲线。在信息科学中,由于其单增以及反函数单增等性质,Sigmoid函数常被用作神经网络的阈值函数,将变量映射到0,1之间 。----参考百度百科激活函数

Sigmoid函数的公式为:
σ ( x ) = 1 1 + e − z \sigma(x)=\frac{1}{1+e^{-z}} σ(x)=1+ez1
其中 z = w ⋅ x + b , x i ∈ [ 0 , 1 ] z=w\cdot x+b,x_i\in[0,1] z=wx+b,xi[0,1]
图像:

在这里插入图片描述
如果不用激活函数,每一层输出都是上层输入的线性函数,无论神经网络有多少层,输出都是输入的线性组合,这种情况就是最原始的感知机(Perceptron)。
如果使用的话,激活函数给神经元引入了非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以应用到众多的非线性模型中。

2.神经网络

人工神经网络(Artificial Neural Network,即ANN ),是20世纪80 年代以来人工智能领域兴起的研究热点。它从信息处理角度对人脑神经元网络进行抽象, 建立某种简单模型,按不同的连接方式组成不同的网络。在工程与学术界也常直接简称为神经网络或类神经网络。神经网络是一种运算模型,由大量的节点(或称神经元)之间相互联接构成。每个节点代表一种特定的输出函数,称为激励函数(activation function)。每两个节点间的连接都代表一个对于通过该连接信号的加权值,称之为权重,这相当于人工神经网络的记忆。网络的输出则依网络的连接方式,权重值和激励函数的不同而不同。而网络自身通常都是对自然界某种算法或者函数的逼近,也可能是对一种逻辑策略的表达。
最近十多年来,人工神经网络的研究工作不断深入,已经取得了很大的进展,其在模式识别、智能机器人、自动控制、预测估计、生物、医学、经济等领域已成功地解决了许多现代计算机难以解决的实际问题,表现出了良好的智能特性。----摘自百度百科神经网络

假设有如下网络,这个网络中最左边的称为输入层,其中的神经元称为输入神经元,最右边的即输出层,包含有输出神经元。在本例中,输出层只有⼀个神经元。中间层,既然这层中的神经元既不是输入也不是输出,则被称为隐藏层。

在这里插入图片描述

3.梯度下降法

  1. 损失函数
    L ( w , b ) = 1 2 n ∑ i = 1 n ( f ( x i ) − y ) 2 (1) L(w,b)=\frac{1}{2n}\sum^{n}_{i=1}(f(x_i)-y)^2 \tag1 L(w,b)=2n1i=1n(f(xi)y)2(1)
    其中 w , b w,b w,b分别为上文中提到的权重和偏置。右端分母部分也可写作 1 n \frac{1}{n} n1,最终的目的是使损失函数为零,分母部分不影响结果,本文为了方便后面展开,遂用 ( 1 ) (1) (1)式系数。
    ( 1 ) (1) (1)式子是没有隐含层时的损失函数,假设一个神经网络输入 x = ( x 1 , . . . , x n ) ∈ R n x=(x_1,...,x_n)\in \Bbb{R}^n x=(x1,...,xn)Rn,共 p p p层神经元,假设每层分别有 l j , j = 1 , . . . k l_j,j=1,...k lj,j=1,...k个神经元,输出 f ( x ) = ( f 1 , . . . , f m ) ∈ R m f(x)=(f_1,...,f_m)\in \Bbb{R}^m f(x)=(f1,...,fm)Rm,假设神经元每层之间的连接为全连接( i . e . i.e. i.e.上一层的每个输出都是下一层每个神经元的输入,如下图),且每层激活函数均为同一函数
    在这里插入图片描述
    则此网络的损失函数为:
    L ( w , b ) = 1 2 n ∑ l = 1 n ∑ k = 1 d ( a k L − y k ) 2 L(w,b)=\frac{1}{2n}\sum^{n}_{l=1}\sum_{k=1}^{d}(a_k^L-y_k)^2 L(w,b)=2n1l=1nk=1d(akLyk)2
    其中:
    a k L 表 示 最 后 一 层 第 k 个 神 经 元 的 输 出 a_k^L表示最后一层第k个神经元的输出 akLk
  2. Taylor展开
    L ( w + h , b + k ) = L ( w , b ) + ( h ∂ ∂ w + k ∂ ∂ b ) L ( w , b ) + R n (2) L(w+h,b+k)=L(w,b)+(h\frac{\partial}{\partial w}+k\frac{\partial}{\partial b})L(w,b)+R_n\tag2 L(w+h,b+k)=L(w,b)+(hw+kb)L(w,b)+Rn(2)
  3. 梯度下降法
    舍弃(2)式余项,可改写为
    Δ L = ∂ L ∂ w ⋅ Δ w + ∂ L ∂ b ⋅ Δ b (3) \Delta L=\frac{\partial L}{\partial w}\cdot\Delta w+\frac{\partial L}{\partial b}\cdot\Delta b\tag3 ΔL=wLΔw+bLΔb(3)
    我们最终的目标是使 L L L尽可能地小(接近 0 0 0)于是当 Δ L \Delta L ΔL小于 0 0 0时说明 L L L在逐渐减小,直到 Δ L = 0 \Delta L=0 ΔL=0,记 Δ v = ( Δ w , Δ b ) , ∇ L = ( ∂ L ∂ w , ∂ L ∂ b ) T \Delta v=(\Delta w,\Delta b),\nabla L=(\frac{\partial L}{\partial w},\frac{\partial L}{\partial b})^T Δv=(Δw,Δb),L=(wL,bL)T,则 ( 3 ) (3) (3)式可表示成
    Δ L = Δ v ⋅ ∇ L (4) \Delta L=\Delta v\cdot\nabla L\tag4 ΔL=ΔvL(4)
    Δ v = − η ∇ L \Delta v=-\eta \nabla L Δv=ηL这⾥的 η \eta η是个很⼩的正数(称为学习速率). ( 3 ) (3) (3)式告诉我们 Δ L = − η ∇ L ⋅ ∇ L = − η ∥ ∇ L ∥ 2 < 0 \Delta L=-\eta \nabla L \cdot\nabla L=-\eta\|\nabla L\|^2<0 ΔL=ηLL=ηL2<0,于是我们可按照 ( 4 ) (4) (4)式的方法去改变 v v v使得 Δ L \Delta L ΔL一直在减小。于是 v v v的变化为
    v → v ′ = v − η ∇ L (5) v\rightarrow v'=v-\eta \nabla L\tag5 vv=vηL(5)
    这样就能找到 L L L的全局最小值。

4.随机梯度下降法

若训练所需样本过大,我们可将样本打乱,选择小样本(m)代替大样本,由统计学知识,小样本的均值和总样本均值是相等的。当选择的小样本循环完总个样本后成为一个循环周期(epoch)。这样可以使训练加速。

5.BP(backpropagation)神经网络

对于(5)式而言,最难的在于求解 C C C w , b w,b w,b的梯度,现在引入变量 δ \delta δ求解 C C C的梯度。

δ = ∂ C ∂ z (6) \delta=\frac{\partial C}{\partial z}\tag6 δ=zC(6)
则最后一层的 δ L \delta^L δL
δ L = ∂ C ∂ z L = ∂ C ∂ a L ∂ a L ∂ z L = ∂ C ∂ a L σ ′ ( z L ) \delta^L=\frac{\partial C}{\partial z^L}=\frac{\partial C}{\partial a^L}\frac{\partial a^L}{\partial z^L}=\frac{\partial C}{\partial a^L}\sigma'(z^L) δL=zLC=aLCzLaL=aLCσ(zL)
应用链式法则可得以下三个公式:
δ l = ( ( w l + 1 ) T δ l + 1 ) ⨀ σ ′ ( z l ) \delta^l=((w^{l+1})^T\delta^{l+1})\bigodot\sigma'(z^l) δl=((wl+1)Tδl+1)σ(zl) ∂ C ∂ b l = δ l \frac{\partial C}{\partial b^l}=\delta^l blC=δl ∂ C ∂ w l = a l − 1 δ l \frac{\partial C}{\partial w^l}=a^{l-1}\delta^l wlC=al1δl
运用此四式子便可更新权重和偏置。

6.程序

6.1 主代码

clc,clear
%% %%%%规定一行为一个神经元,一列为一个层
mat= load('data_base.mat');
Ptrain=mat.X_train;                                               %训练集输入
T=mat.Y_train;                                                      %训练集输出
Ptest=mat.X_test;                                                 %测试集输入
T1=mat.Y_test;                                                     %测试集输出(十进制)
%% 将输出转为向量形式(输出神经元个数为10)
Ttrain=zeros(10,length(T));                      %训练集输出(向量形式)
Ttest=zeros(10,length(T1));                      %测试集输出
i=1;
while i<=length(T)
    s=T(i)+1;
    Ttrain(s,i)=1;
    if  i<length(T1)
        t=T1(i)+1;
        Ttest(t,i)=1;
    end
    i=i+1;
end
%% 初始化权重和偏置
net=[784,15,10];                                           %定义神经元的层数与个数
b_hid=randn(net(2),1) ;                                 %(将输入也看做一层神经元)只有中间层和输出层神经元有偏置
b_out=randn(net(3),1);                                  %初始化两层权重为(0,1)的随机数
w_hid=randn(net(2),net(1));                           
%此程序中w_hid为15*784的矩阵,
%第一行为第一层第一个神经元到所有隐藏层的权重,
%第一列为第一层所有神经元到隐藏层第一个神经元的权重,以此类推。
w_out=randn(net(3),net(2));                                   %初始化权重                               

%% 训练
epochs=8000; %最大迭代次数
c=0;
% v=randperm(1000,1000);
% Ptrain=Ptrain(:,v);
% Ttrain=Ttrain(:,v);
while c<epochs
    %调用sgd函数更新权重和偏置
    [delta2,delta3,w_hid,w_out,b_hid,b_out]=sgd(8,Ptrain,Ttrain,w_hid,w_out,b_hid,b_out);
    [s,t]=size(Ttrain);
    z2=w_hid*Ptrain+b_hid;
    a2=sigmod(z2);
    z3=w_out*a2+b_out;
    a3=sigmod(z3);
    tt=zeros(size(a3));
    sum=0;
   for i=1:t
       for j=1:s
           if a3(j,i)>0.6
               tt(j,i)=1;
           end
       end
   end
   for k=1:t
       if norm(tt(:,k)-Ttrain(:,k))==0
           sum=sum+1;
       end
   end 
       correct=sum/t;
  
         c=c+1; 
    if correct>0.95
         fprintf('周期%1.0f的正确率是%1.4f\n',c,correct) 
        break
    end
%     c=c+1;
     fprintf('周期%1.0f的正确率是%1.4f\n',c,correct) 
end
    
%% 测试
    [n,m]=size(Ttest);
    z2=w_hid*Ptest+b_hid;
    a2=sigmod(z2);
    z3=w_out*a2+b_out;
    a3=sigmod(z3);
    tt=zeros(size(a3));
    sum=0;
   for i=1:m
       for j=1:n
           if a3(j,i)>0.8
               tt(j,i)=1;
           end
       end
   end
   for k=1:m
       if norm(tt(:,k)-Ttest(:,k))==0
           sum=sum+1;
       end
   end 
       correct=sum/m;
    fprintf('测试集的正确率是%1.4f\n',correct) 

6.2 求解梯度

%% 定义函数求partialb,partialw
function [delta2,delta3,pb_hid,pb_out,pw_hid,pw_out]=bpnn(P,T,z2,z3,w_out)
%(单样本输入)P为输入,T为输出,net为神经网络每层的神经元个数,z2,z3为权重与偏置的线性组合,w为权重,delta为反向传播“误差”
a3=sigmod(z3);
delta3=(a3-T).*dsigmod(z3);
delta2=(w_out'*delta3).*dsigmod(z2);
%求权重和偏置的偏导
pb_hid=delta2;
pb_out=delta3;
pw_hid=delta2*P';
pw_out=delta3*sigmod(z2)';
end

注:为防止某些朋友(大学生)只顾参考而不动手编程,故隐去部分简单代码(求梯度的代码(6.2)已给出,只需将求好的梯度带入(5)式即可,数据集来自文章顶端链接)

7.消失的梯度

请注意看文章顶端的sigmod函数,他的偏导最大值为 1 / 4 1/4 1/4.如图

在这里插入图片描述
请注意:
若以三层单元神经网络为例:

w2
w3
b2
b3

∂ C ∂ b 2 = ∂ C ∂ a 3 ∂ a 3 ∂ z 3 ∂ z 3 ∂ a 2 ∂ a 2 ∂ b 2 = ∂ C ∂ a 3 σ ′ ( z 3 ) w 3 σ ′ ( z 2 ) \frac{\partial C}{\partial b^2}=\frac{\partial C}{\partial a_3}\frac{\partial a_3}{\partial z_3}\frac{\partial z_3}{\partial a_2}\frac{\partial a_2}{\partial b_2}=\frac{\partial C}{\partial a_3}\sigma'(z_3)w3\sigma'(z_2) b2C=a3Cz3a3a2z3b2a2=a3Cσ(z3)w3σ(z2) ∂ C ∂ b 3 = ∂ C ∂ a 3 σ ′ ( z 3 ) = δ 3 \frac{\partial C}{\partial b^3}=\frac{\partial C}{\partial a^3}\sigma'(z_3)=\delta^3 b3C=a3Cσ(z3)=δ3
由于 σ ′ ≤ 1 4 \sigma'\leq\frac{1}{4} σ41 w < 1 w<1 w<1由第五部分式子可知, δ 2 < 1 / 4 δ 3 \delta^2<1/4\delta^3 δ2<1/4δ3
若神精网络含有多层,则前边层的梯度趋于0,导致梯度消失,学习速度下降。

神经网络由于参数过多,受激活函数、初值选取、网络结构等的影响含有很多不确定性,如今存在的文献中也给了各式各样的神经网络,目前仍是一个研究热点。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值