基于深度学习的手写数字识别Matlab实现

深度学习 同时被 3 个专栏收录
1 篇文章 0 订阅
3 篇文章 0 订阅

基于深度学习的手写数字识别Matlab实现

1.网络设计

1.1 CNN(特征提取网络+分类网络)
随着深度学习的迅猛发展,其应用也越来越广泛,特别是在视觉识别、语音识别和自然语言处理等很多领域都表现出色。卷积神经网络(Convolutional Neural Network,CNN)作为深度学习中应用最广泛的网络模型之一,也得到了越来越多的关注和研究。事实上,CNN作为一项经典的机器学习算法,早在20世纪80年代就已被提出并展开一定的研究。但是,在当时硬件运算能力有限、缺乏有效训练数据等因素的影响下,人们难以训练不产生过拟合情形下的高性能深度卷积神经网络模型。所以,当时CNN的一个经典应用场景就是用于识别银行支票上的手写数字,并且已实际应用。伴随着计算机硬件和大数据技术的不断进步,人们也尝试开发不同的方法来解决深度CNN训练中所遇到的困难,特别是Kizhesky 等专家提出了一种经典的CNN架构,论证了深度结构在特征提取问题上的潜力,并在图像识别任务上取得了重大突破,热起了深度结构研究的浪潮。而卷积神经网络作为一种已经存在的、有一定应用案例的深度结构,也重新回到人们的视野中,得以进一步研究和应用。
而本次实验就是基于CNN实现的。
1.1.1基本架构
卷积神经网络基本架构包括特征抽取器和分类器。特征抽取器通常由若干个卷积层和池化层叠加构成,卷积和池化过程不断将特征图缩小,同时会导致特征图数量的增多。特征抽取器后面一般连接分类器,通常由一个多层感知机构成。特别地,在最后一个特征抽取器后面,将所有的特征图展开并排列成一个向量得到特征向量,并作为后层分类器的输入。
1.1.2卷积层
卷积运算的基本操作是将卷积核与图像的对应区域进行卷积得到一个值,通过在图像上不断移动卷积核和来计算卷积值,进而完成对整幅图像的卷积运算。在卷积神经网络中,卷积层不仅涉及一般的图像卷积,还涉及深度和步长的概念。深度对应于同一个区域的神经元个数,即有几个卷积核对同一块区域进行卷积运算;步长对应于卷积核移动多少个像素,即前后距离的远近程度。
本次实验卷积层采用的是20个99的滤波器进行滤波,激活函数为ReLU函数。
1.1.2.1局部感知
人对外界的认知一般可以归纳为从局部到全局的过程,而图像的像素空间联系也是局部间的相关性强,远距离的相关性弱。因此,卷积神经网络的每个神经元实际上只需关注图像局部的感知,对图像全局的感知可通过更高层综合局部信息来获得,这也说明了卷积神经网络部分连通的思想。类似于生物学中的视觉系统结构,视觉皮层的神经元用于局部接收信息,即这些神经元只响应某些特定区域的刺激,呈现出部分连通的特点。
1.1.2.2参数共享
局部感知过程假设每个神经元都对应100个参数,共106个神经元,则参数共有100×106个,依然是一个很大的数字。如果这106个神经元的100个参数相等,那么参数个数就减少为100,即每个神经元用同样的卷积核执行卷积操作,这将大大降低运算量。因不论隐层的神经元个数有多少,两层间的连接只要100个参数,这也说明了参数共享的意义。
1.1.2.3多核卷积
如果10×10维数的卷积核都相同,那么只能提取图像的一种特征,局限性很明显。可以考虑通过增加卷积核来提高特征类别,例如选择16个不同的卷积核用于学习16种特征。其中,应用卷积核到图像执行卷积操作,可得到图像的不同特征,统称为特征图(Feature Map),所以16个不同的卷积核就有16个特征图,可以视作图像的不同通道。此时,卷积层包含10×10×16=1600个参数。
1.1.3池化层
从理论上来看,经卷积层得到特征集合,可直接用于训练分类器(例如经典的Softmax分类器),但这往往会带来巨大计算量的问题。通过计算图像局部区域上的某特定特征的平均值或最大值等来计算概要统计特征。这些概要统计特征相对于经卷积层计算得到的特征图,不仅达到了降维目的,同时还会提高调练效率,这种特征聚合的操作叫作池化(Pooling),本次实验采用的是2
2的平均池化。
1.1.4 特征提取网络
使用reshape函数将特征提取网络的矩阵转换为2000*1的列向量,然后是两个隐层节点,这两个隐层节点含分别都含有95个神经元,中间采用的都是ReLU激活函数。最后是10个输出节点,实现单热编码输出,使用的是Softmax激活函数。

2. 训练方法

Delata规则+BP算法+交叉熵代价函数+SGD(随机梯度下降算法)+动量算法
2.1程序实现
使用到的 MNIST包自行下载后,需要用到的函数
accuracy

function y = accuracy(W1,W2,W3,W4,X_Test,D_Test,epoch)
N=length(D_Test);
d_comp=zeros(1,N);
for  k=1:N
     X=X_Test(:,:,k);
     V1=Conv(X,W1);%自定义函数(不旋转,直接滤波)
     Y1=ReLU(V1);
     Y2=Pool(Y1);%自定义函数,2×2平均池化操作
     y1=reshape(Y2,[],1);
     v2=W2*y1;
     y2=ReLU(v2);
     v3=W3*y2;
     y3=ReLU(v3);
     v=W4*y3;
     y=Softmax(v);
    [~,i]=max(y);%找到y向量中的最大元素,i为其位置索引
    d_comp(k)=i;%保存CNN的计算值(识别出的数字)
end
[~,d_true]=max(D_Test);%将单热编码变回相应数字,存入d true(1xN维向量)
acc=sum(d_comp==d_true);%统计正确识别的总数
fprintf('第%d轮:',epoch);
fprintf('Accuracy is %f\n',acc/N);%输出正确率
end

Conv

    function y = Conv(x, W)
    %     对一幅图片的卷积
    %
    %     [wrow, wcol, numFilters] = size(W);
    %     [xrow, xcol, ~] = size(x);
    %     y = zeros(xrow - wrow + 1, xcol - wcol + 1, numFilters);
    %     for k = 1:numFilters
    %         y(:, :, k) = conv2(x, rot90(W(:, :, k),2), 'valid');
    %     end

    [xrow, xcol, xcha] = size(x);
    [wrow, wcol, wpage, numFilters] = size(W);
    if xcha>1&&(xcha==wpage)
        y = zeros(xrow - wrow + 1, xcol - wcol + 1, numFilters);
        W = W(:,:,end:-1:1,:);
        for i = 1:numFilters
            for j = 1:wpage
                W(:,:,j,i) = rot90(W(:,:,j,i),2);
            end
            y(:, :, i) = convn(x, W(:,:,:,i), 'valid');
        end
    else
        y = zeros(xrow - wrow + 1, xcol - wcol + 1, wpage);
        for k = 1:wpage
            y(:, :, k) = conv2(x, rot90(W(:, :, k),2), 'valid');
        end
    end
    
end

Dropout

function ym = Dropout(y, ratio)
  [m, n] = size(y);  
  ym     = zeros(m, n);
  num     = round(m*n*(1-ratio));
  idx     = randperm(m*n, num);
  ym(idx) = m*n / num;
end

Pool

function y = Pool(x)
%     
% 2x2 mean pooling
%
%
y=(x(1:2:end,1:2:end,:)+x(2:2:end,1:2:end,:)+x(1:2:end,2:2:end,:)+x(2:2:end,2:2:end,:))/4;
end

ReLU

function y = ReLU(x)
  y = max(0, x);
end

Softmax
function y = Softmax(x)
  ex = exp(x);
  y  = ex / sum(ex);
end

test

clc;clear all; close all;
tic;
load MNISTData
%初始化权值
alpha=0.01;
beta =0.01;
epoch=20;
W1=randn(9,9,20);
W2=(2*rand(95,2000)-1)/20 ;  
W3=(2*rand(45,95)-1)/10;  
W4=(2*rand(10,45)-1)/5;
mmt1 = zeros(size(W1));
mmt2 = zeros(size(W2));
mmt3 = zeros(size(W3)); 
mmt4 = zeros(size(W4));
for G=1:epoch
  [xrow, xcol, xcha] = size(X_Train);
for    I= 1:xcha
    %%卷积池化层
       V1= Conv(X_Train(:,:,I),W1);
       Y1=ReLU(V1);
       Y2=Pool(Y1);
    %%分类层
       y1=reshape(Y2,[],1);
       v2=W2*y1;
       y2=ReLU(v2);
       y2 = y2 .* Dropout(y2, 0.01);
       v3=W3*y2;
       y3=ReLU(v3);
       y3 = y3 .* Dropout(y3, 0.01);
       v=W4*y3;    
       y=Softmax(v);
       e=D_Train(:,I)-y;
    %%误差前向传播
       delta=e;%交叉熵+softmax
       e3=W4'*delta;
       delta3=(v3>0).*e3;
       e2=W3'*delta3;
       delta2=(v2>0).*e2;
       e1=W2'*delta2;
       E2=reshape(e1,size(Y2));
       E1=zeros(size(Y1));E2_4=E2/4;
       E1(1:2:end,1:2:end,:)=E2_4;
       E1(1:2:end,2:2:end,:)=E2_4;
       E1(2:2:end,1:2:end,:)=E2_4;
       E1(2:2:end,2:2:end,:)=E2_4;
       delta1=(V1>0).*E1;
     %%更新权值
       [a,b,c]=size(W1);
       for t=1:c
           dW1(:,:,t)=alpha* conv2(X_Train(:,:,I),rot90(delta1(:,:,t),2),'valid');
           mmt1(:,:,t)= dW1 (:,:,t)+ beta*mmt1(:,:,t);
           W1(:,:,t)=W1(:,:,t)+mmt1(:,:,t);
 %         W1(:,:,t)=W1(:,:,t)+dW1(:,:,t);
       end
          dW4=alpha*delta*y3';
          mmt4 = dW4 + beta*mmt4;
          W4   = W4 + mmt4;
 %        W4   = W4 +dW4;
          dW3=alpha*delta3*y2';
          mmt3 = dW3 + beta*mmt3;
          W3   = W3 + mmt3;
 %        W3   = W3 +dW3;
          dW2=alpha*delta2*y1';
          mmt2 = dW2 + beta*mmt2;
          W2   = W2 + mmt2;
 %        W2   = W2 +dW2;
end

toc
%%统计正确率的代码:
 acc=accuracy(W1,W2,W3,W4,X_Test,D_Test,G);
end

2.2代码解释
2.2.1加载数据

clc; clear all; close all;
tic;
load MNISTData

2.2.2根据网络结构初始化学习速率,权值,循环次数等

alpha=0.01;
beta =0.01;
epoch=2
W1=randn(9,9,20);
W2=(2*rand(95,2000)-1)/20;  
W3=(2*rand(45,95)-1)/10;  
W4=(2*rand(10,45)-1)/5;
  mmt2 = zeros(size(W2));
  mmt3 = zeros(size(W3)); 
  mmt4 = zeros(size(W4));
for G=1:epoch

2.2.3训练CNN网络

[xrow, xcol, xcha] = size(X_Train);
for    I= 1:xcha
    %%卷积池化层
       V1= Conv(X_Train(:,:,I),W1);
       Y1=ReLU(V1);
       Y2=Pool(Y1);
    %%分类层 + dropout
        y1=reshape(Y2,[],1);
       v2=W2*y1;
       y2=ReLU(v2);
       y2 = y2 .* Dropout(y2, 0.01);
       v3=W3*y2;
       y3=ReLU(v3);
       y3 = y3 .* Dropout(y3, 0.01);
       v=W4*y3;    
       y=Softmax(v);
       e=D_Train(:,I)-y;

BP算法+Delta规则+交叉熵代价函数
%误差前向传播(交叉熵+softmax)

 delta=e;
   e3=W4'*delta;
   delta3=(v3>0).*e3;
   e2=W3'*delta3;
   delta2=(v2>0).*e2;
   e1=W2'*delta2;
   E2=reshape(e1,size(Y2));
   E1=zeros(size(Y1));E2_4=E2/4;
   E1(1:2:end,1:2:end,:)=E2_4;
   E1(1:2:end,2:2:end,:)=E2_4;
   E1(2:2:end,1:2:end,:)=E2_4;
   E1(2:2:end,2:2:end,:)=E2_4;
   delta1=(V1>0).*E1;

2.2.5 动量算法+SGD更新权值

            [a,b,c]=size(W1);
       for t=1:c
           dW1(:,:,t)=alpha* conv2(X_Train(:,:,I),rot90(delta1(:,:,t),2),'valid');
           mmt1(:,:,t)= dW1 (:,:,t)+ beta*mmt1(:,:,t);
           W1(:,:,t)=W1(:,:,t)+mmt1(:,:,t);
 %         W1(:,:,t)=W1(:,:,t)+dW1(:,:,t);
       end
          dW4=alpha*delta*y3';
          mmt4 = dW4 + beta*mmt4;
          W4   = W4 + mmt4;
 %        W4   = W4 +dW4;
          dW3=alpha*delta3*y2';
          mmt3 = dW3 + beta*mmt3;
          W3   = W3 + mmt3;
 %        W3   = W3 +dW3;
          dW2=alpha*delta2*y1';
          mmt2 = dW2 + beta*mmt2;
          W2   = W2 + mmt2;
 %        W2   = W2 +dW2;
end

toc

2.2.6 评估训练效果
%%统计正确率的代码:

acc=accuracy(W1,W2,W3,W4,X_Test,D_Test);
end

3.实验结果

在这里插入图片描述
在这里插入图片描述
上图分别为四轮次和单轮的最佳运行效果,成功达到了要求。

4.实验结果分析

通过对网络结构,算法,权值的不断调整,获得了目前最好的结果(98%+正确率)。通过对训练后的权值和初始化的权值对比,不断调整其参数,尽量让初始化权值大小和训练后的结果差不多大,这样的训练效果最好。在SGD,小批量,批量中,根据运行的时间和精度不断比较,最终还是选择SGD算法最优。而动量算法对准确率提升不大,但是提升了稳定性,也提高了更新速度。在特征提取网络中,从一个隐层变成两个隐层,对实验结果精确率也有所帮助。而学习速率和动量算法的步进速率的选取,只能通过一次次实验寻找合适的值。一轮训练效果不够理想,所以进行了多轮训练。对于dropout,多轮次训练中可以有效解决过拟合问题。我也尝试了20001000100*10的分类层,虽然不符合设计要求,可是我发现节点更多,训练效果会更好一些。最高跑过10轮,可以达到98.9%的准确率。

5.结论

*卷积神经网络在图像、视频、语音和文本处理中取得了较多突破。在这一次的设计中,通过对代码的查找,修改,理解,自己从底层了解了卷积神经网络的一些概念,算法,优化方法。而且我认为只有如此才能理解其他编程软件的框架的由来,每一步在做什么。当然,也通过这次设计熟悉掌握了卷积神经网络在matlab上的代码操作。简单实现这次目标检测后,我也深刻认识到他还需要我更进一步的研究。
首先,由于CNN层数变得越来越深,人们对大规模的有效数据和高性能的计算能力也提出了越来越多的要求。同时,传统的人工搜集标签数据要求投入大量的人力和物力,这也导致了成本的提升,所以,无监督式的CNN学习方式越来越重要。
其次,为了提高CNN训练速度,一般采用某些异步的SGD算法,通过CPU和GPU集群可以得到一定的效果,但同时对硬件配置提出了一定的要求。因此,开发高效可扩展的训练算法依然有重要的实际价值。此外,深度模型在训练过程中往往需要在较长时间内占据较多的内存空间,对运行环境也带来了较大的压力。因此,在保证准确度的情况下,如何降低复杂性并快速训练得到模型,也是重要的研究方向。
再次,CNN应用于不同的任务要面临的关键问题是如何选择合适的训练参数,例如学习率、卷积核大小、卷积和池化层数等,这要求较多的技术积累和经验总结。这些训练参数存在内部相关性,也为参数调整带来较高的成本。因此,在CNN架构的选择上,依然值得我们去深入研究。

<p style="font-size:16px;"> 本课程适合具有一定深度学习基础,希望发展为深度学习之计算机视觉方向的算法工程师和研发人员的同学们。<br /> <br /> 基于深度学习的计算机视觉是目前人工智能最活跃的领域,应用非常广泛,如人脸识别和无人驾驶中的机器视觉等。该领域的发展日新月异,网络模型和算法层出不穷。如何快速入门并达到可以从事研发的高度对新手和中级水平的学生而言面临不少的挑战。精心准备的本课程希望帮助大家尽快掌握基于深度学习的计算机视觉的基本原理、核心算法和当前的领先技术,从而有望成为深度学习之计算机视觉方向的算法工程师和研发人员。<br /> <br /> 本课程系统全面地讲述基于深度学习的计算机视觉技术的原理并进行项目实践。课程涵盖计算机视觉的七大任务,包括图像分类、目标检测、图像分割(语义分割、实例分割、全景分割)、人脸识别、图像描述、图像检索、图像生成(利用生成对抗网络)。本课程注重原理和实践相结合,逐篇深入解读经典和前沿论文70余篇,图文并茂破译算法难点, 使用思维导图梳理技术要点。项目实践使用Keras框架(后端为Tensorflow),学员可快速上手。<br /> <br /> 通过本课程的学习,学员可把握基于深度学习的计算机视觉的技术发展脉络,掌握相关技术原理和算法,有助于开展该领域的研究与开发实战工作。另外,深度学习之计算机视觉方向的知识结构及学习建议请参见本人CSDN博客。<br /> <br /> 本课程提供课程资料的课件PPT(pdf格式)和项目实践代码,方便学员学习和复习。<br /> <br /> 本课程分为上下两部分,其中上部包含课程的前五章(课程介绍、深度学习基础、图像分类、目标检测、图像分割),下部包含课程的后四章(人脸识别、图像描述、图像检索、图像生成)。 </p> <div> <br /> </div> <p> <br /> </p> <p> <br /> </p> <p style="font-size:16px;"> <br /> </p> <p style="font-size:16px;"> <img src="https://img-bss.csdn.net/201902211157137641.jpg" alt="" /><img src="https://img-bss.csdn.net/201902211157578041.gif" alt="" /><img src="https://img-bss.csdn.net/201902211158173579.gif" alt="" /><img src="https://img-bss.csdn.net/201902211158498135.gif" alt="" /><img src="https://img-bss.csdn.net/201902211159093293.gif" alt="" /><img src="https://img-bss.csdn.net/201902211159209625.gif" alt="" /> </p> <p style="font-size:16px;"> <br /> </p>
©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值