matlab基于mnist数据集的图像识别(深度学习入门卷积神经网络附完整学习资料)(代码片段)

阿汪先生 阿汪先生     2023-03-01     787

关键词:


Matlab——数字0~9的图像识别(Phil Kim著、Matlab)


本文可以为那些想对深度学习和人工智能有初步了解的朋友提供一些基础入门的帮助。


本文所用参考书:

《MATLAB深度学习 机器学习、神经网络与人工智能》
【美】Phil Kim著
敖富江 杜静 周浩 译
清华大学出版社
ISBN:978-7-302-49638-0


水平有限,本文仅作学习交流,笔记分享所用。

工程文件由上述参考书给出,本文对该工程中部分函数作了一些注解,方便大家理解和应用。


所需的知识储备:



阿汪先生做的印象笔记链接:


部分工程文件注解:

1、神经网络训练函数-MnistConv

function [W1, W5, Wo] = MnistConv(W1, W5, Wo, X, D)
%MnistConv函数接收神经网络的权重和训练数据,并返回经过训练后的权重。
%W1-卷积滤波器矩阵
%W5:池化-隐含层权重矩阵
%Wo:隐含-输出层权重矩阵
%X:训练数据的输入
%D:标准输出

alpha = 0.01;       %delta规则,参数学习率α,
                        %笔记:第2章-2.5、2.6-delta规则、广义delta规则
beta  = 0.95;       %β:小于1的正常数,动量,反向传播,提高学习效率,
                        %笔记:第3章-3.2-反向传播示例

momentum1 = zeros(size(W1));           %动量矩阵,生成全零矩阵
momentum5 = zeros(size(W5));           %公式,见笔记,第3章-3.2-反向传播示例
momentumo = zeros(size(Wo));

N = length(D);      %标准输出D数组的长度

bsize = 100;        %批次数,8000个训练数据,100批次
                    %权重的调整,次数为80次,完成80次调整为一个历元。
blist = 1:bsize:(N-bsize+1);
                    %保存置入minibatch的首个训练数据点的所在位置。       
        
% 一次历元epoch循环
%
for batch = 1:length(blist)
  dW1 = zeros(size(W1));
  dW5 = zeros(size(W5));
  dWo = zeros(size(Wo));
  
  % Mini-batch循环
  %
  begin = blist(batch);
  for k = begin:begin+bsize-1
    %
    x  = X(:, :, k);         % 输入 28x28 的原始图像
    y1 = Conv(x, W1);        % 卷积层(卷积滤波器)处理后,输出20个20x20的图像
    y2 = ReLU(y1);           %进入池化层前进行ReLU,避免梯度消失问题
    y3 = Pool(y2);           % 平均池化,输出20个10x10的图像
    y4 = reshape(y3, [], 1); %y3矩阵重排列,转换成1列多行的矩阵
    v5 = W5*y4;              % 
    y5 = ReLU(v5);           %
    v  = Wo*y5;              % 
    y  = Softmax(v);         %代入激活函数Softmax, 10个输出节点,输出10x1矩阵

    % 独热编码过程
    d = zeros(10, 1);
    d(sub2ind(size(d), D(k), 1)) = 1;
                            %sub2ind()生成线性索引编号
                            %matlab中矩阵的存储是按列优先的
    % 反向传播过程
    e      = d - y;                   % 输出层 
    delta  = e;

    e5     = Wo' * delta;             % 隐藏层(ReLU)
    delta5 = (y5 > 0) .* e5;

    e4     = W5' * delta5;            % 池化层(Pool)
    
    e3     = reshape(e4, size(y3));   %重新排列矩阵e4,排列成y3的相同行列数

    e2 = zeros(size(y2));           
    W3 = ones(size(y2)) / (2*2);
    for c = 1:20
      e2(:, :, c) = kron(e3(:, :, c), ones([2 2])) .* W3(:, :, c);
            %kron即为Kronecker积,所谓Kronecker积是一种矩阵运算          
            %C=kron (A,B)    
            %A为m×n矩阵,B为p×q矩阵,则C为mp×nq矩阵。
    end
    
    delta2 = (y2 > 0) .* e2;          % ReLU层
  
    delta1_x = zeros(size(W1));       % 卷积层
    for c = 1:20
      delta1_x(:, :, c) = conv2(x(:, :), rot90(delta2(:, :, c), 2), 'valid');
    end
    
    dW1 = dW1 + delta1_x; 
    dW5 = dW5 + delta5*y4';    
    dWo = dWo + delta *y5';
  end 
  
  % 更新权重数值
  %
  dW1 = dW1 / bsize;         %minibatch更新次数,
  dW5 = dW5 / bsize;         %见笔记,第2章-2.7、2.8-SGD、Batch和Mini Batch
  dWo = dWo / bsize;
  
  momentum1 = alpha*dW1 + beta*momentum1;   %采用动量来调整权重
  W1        = W1 + momentum1;               %见笔记,第3章-3.2-反向传播示例
  
  momentum5 = alpha*dW5 + beta*momentum5;
  W5        = W5 + momentum5;
   
  momentumo = alpha*dWo + beta*momentumo;
  Wo        = Wo + momentumo;  
end

end



2、测试文件-TestMnistConv-计算卷积神经网络输出结果的正确率

clear all

Images = loadMNISTImages('E:\\code_matlab\\matlab_kim\\ch.6\\MNIST\\t10k-images.idx3-ubyte');
Images = reshape(Images, 28, 28, []);
Labels = loadMNISTLabels('E:\\code_matlab\\matlab_kim\\ch.6\\MNIST\\t10k-labels.idx1-ubyte');
Labels(Labels == 0) = 10;    % 0 --> 10

rng(1);

% 训练数据进行学习
%
W1 = 1e-2*randn([9 9 20]);
W5 = (2*rand(100, 2000) - 1) * sqrt(6) / sqrt(360 + 2000);
Wo = (2*rand( 10,  100) - 1) * sqrt(6) / sqrt( 10 +  100);

X = Images(:, :, 1:8000);
D = Labels(1:8000);

for epoch = 1:3
  epoch();
  [W1, W5, Wo] = MnistConv(W1, W5, Wo, X, D);
end

save('MnistConv.mat');


% 测试部分
%
X = Images(:, :, 8001:10000);       %训练数据部分
D = Labels(8001:10000);             %验证数据部分

acc = 0;
N   = length(D);
for k = 1:N
  x = X(:, :, k);                   % 输入 28x28 的原始图像

  y1 = Conv(x, W1);                 % 卷积层(卷积滤波器)处理后,输出20个20x20的图像
  y2 = ReLU(y1);                    %
  y3 = Pool(y2);                    %y3矩阵重排列,转换成1列多行的矩阵
  y4 = reshape(y3, [], 1);          %                   
  v5 = W5*y4;                       % 
  y5 = ReLU(v5);                    %
  v  = Wo*y5;                       %代入激活函数Softmax,          10x1
  y  = Softmax(v);                  %

  %比较网络的输出和标注输出,并计数匹配的结果
  [~, i] = max(y);                  %将10x1的向量输出转换回一个数字
  if i == D(k)                      %将其和给定的标准输出进行比较
    acc = acc + 1;
  end
end

acc = acc / N;                      %计算卷积神经网络输出结果的正确率
fprintf('Accuracy is %f\\n', acc);




3、屏幕显示输出-display_network-将矩阵显示在屏幕上

function [h, array] = display_network(A, opt_normalize, opt_graycolor, cols, opt_colmajor)

%此功能可将矩阵A中的过滤器可视化,将矩阵显示在屏幕上。
%A的每一列都是一个过滤器。 
%我们将每列重塑为正方形图像,并在可视化面板的每个单元上进行可视化。
%opt_normalize:是否需要标准化过滤器,以使所有过滤器具有相似的对比度。 默认值为true。
%opt_graycolor:是否使用灰色作为热图。 默认为true。
%列:显示屏中有几列。 默认值为A中列数的平方根。
%opt_colmajor:您可以将约定切换为A的行专业。
%在这种情况下,A的每一行都是一个过滤器。 默认值为false。

warning off all %不显示警告信息

if ~exist('opt_normalize', 'var') || isempty(opt_normalize)
    opt_normalize= true;
end

if ~exist('opt_graycolor', 'var') || isempty(opt_graycolor)
    opt_graycolor= true;
end

if ~exist('opt_colmajor', 'var') || isempty(opt_colmajor)
    opt_colmajor = false;
end

% rescale
%重新缩放
A = A - mean(A(:));

if opt_graycolor, colormap(gray); end

% compute rows, cols
%计算行,列
[L, M]=size(A);
sz=sqrt(L);
buf=1;
if ~exist('cols', 'var')
    if floor(sqrt(M))^2 ~= M
        n=ceil(sqrt(M));
        while mod(M, n)~=0 && n<1.2*sqrt(M), n=n+1; end
        m=ceil(M/n);
    else
        n=sqrt(M);
        m=n;
    end
else
    n = cols;
    m = ceil(M/n);
end

array=-ones(buf+m*(sz+buf),buf+n*(sz+buf));

if ~opt_graycolor
    array = 0.1.* array;
end


if ~opt_colmajor
    k=1;
    for i=1:m
        for j=1:n
            if k>M 
                continue; 
            end
            clim=max(abs(A(:,k)));
            if opt_normalize
                array(buf+(i-1)*(sz+buf)+(1:sz),buf+(j-1)*(sz+buf)+(1:sz))=reshape(A(:,k),sz,sz)/clim;
            else
                array(buf+(i-1)*(sz+buf)+(1:sz),buf+(j-1)*(sz+buf)+(1:sz))=reshape(A(:,k),sz,sz)/max(abs(A(:)));
            end
            k=k+1;
        end
    end
else
    k=1;
    for j=1:n
        for i=1:m
            if k>M 
                continue; 
            end
            clim=max(abs(A(:,k)));
            if opt_normalize
                array(buf+(i-1)*(sz+buf)+(1:sz),buf+(j-1)*(sz+buf)+(1:sz))=reshape(A(:,k),sz,sz)/clim;
            else
                array(buf+(i-1)*(sz+buf)+(1:sz),buf+(j-1)*(sz+buf)+(1:sz))=reshape(A(:,k),sz,sz);
            end
            k=k+1;
        end
    end
end

if opt_graycolor
    h=imagesc(array,'EraseMode','none',[-1 1]);
else
    h=imagesc(array,'EraseMode','none',[-1 1]);
end
axis image off

drawnow;

warning on all


4、卷积滤波器矩阵-Conv(x, W)

function y = Conv(x, W)
%Conv函数接收输入图像和卷积滤波器矩阵,并返回特征映射图。
%
[wrow, wcol, numFilters] = size(W);
[xrow, xcol, ~         ] = size(x);
    %将矩阵W的行数返回到输出变量wrow,将矩阵W的列数返回到输出变量wcol。
    %将矩阵x的行数返回到输出变量xrow,将矩阵x的列数返回到输出变量xcol。
yrow = xrow - wrow + 1;
ycol = xcol - wcol + 1;

y = zeros(yrow, ycol, numFilters);      %生成全零矩阵y
for k = 1:numFilters
  filter = W(:, :, k);                  %第k层W矩阵
  filter = rot90(squeeze(filter), 2);
             %squeeze,除去size为1的维度,获得一个二维的矩阵
             %将矩阵(图片)旋转2个90度
  y(:, :, k) = conv2(x, filter, 'valid');
              %用matlab内置的二维卷积函数--conv函数执行卷积计算
              %x(:, :, k):第k层x矩阵
              %valid 返回在卷积过程中,未使用边缘补0部分进行计算的卷积结果部分
              %image 的结果是一个2*2矩阵
end

end



5、平均池化层- Pool(x)- 2x2子矩阵进行平均池化

function y = Pool(x)
% 2x2子矩阵进行平均池化    
% 
[xrow, xcol, numFilters] = size(x);
%xrow:行
%xcol:列
%numFilters:滤波器个数

y = zeros(xrow/2, xcol/2, numFilters); %生成全零矩阵y
for k = 1:numFilters
  filter = ones(2) / (2*2);  %卷积滤波器,2*2的矩阵(元素为0.25)  
                             %池化层的滤波器filter值是预定义的。
  image  = conv2(x(:, :, k), filter, 'valid');
           %x(:, :, k):第k层x矩阵
           %conv2函数:二维卷积函数
           %valid 返回在卷积过程中,未使用边缘补0部分进行计算的卷积结果部分
           %image 的结果是一个2*2矩阵
  y(:, :, k) = image(1:2:end, 1:2:end);
           %每层(k层)2*2矩阵分别赋值
end

end
 

6、绘图函数-PlotFeatures


warning off all %不显示警告信息
clear all
load('MnistConv.mat')
k  = 32;
x  = X(:, :, k);
y1 = Conv(x, W1);                 % 卷积层Convolution,20张20x20的图像
y2 = ReLU(y1);                    %
y3 = Pool(y2);                    % 池化层Pool,输出20张10x10的图像
y4 = reshape(y3, [], 1);          %  转换成一维数据,2000个像素点  
v5 = W5*y4;                       % ReLU转化,
y5 = ReLU(v5);                    %去除非正值,明显化特征(去除图中黑色区域,灰度化) 
v  = Wo*y5;                       % 代入激活函数Softmax函数,
y  = Softmax(v);                  %
  

figure;                          
display_network(x(:));             %显示输入图像
title('Input Image')               %显示输入图像

convFilters = zeros(9*9, 20);     %初始化全零矩阵
for i = 1:20
  filter            = W1(:, :, i);
  convFilters(:, i) = filter(:);
end
figure                            
display_network(convFilters);      %显示经神经网络训练确定的卷积滤波器
title('Convolution Filters')     

fList = zeros(20*20, 20);           %初始化全零矩阵
for i = 1:20
  feature     = y1(:, :, i);
  fList(:, i) = feature(:);
end
figure                            %创建新窗口
display_network(fList);           %显示卷积滤波器处理的结果(特征图像)
title('Features [Convolution]')   

fList = zeros(20*20, 20);         %初始化全零矩阵
for i = 1:20
  feature     = y2(:, :, i);
  fList(:, i) = feature(:);
end
figure                              %创建新窗口
display_network(fList);             %显示特征图像经ReLU处理后的图像
title('Features [Convolution + ReLU]')

fList = zeros(10*10, 20);           %初始化全零矩阵
for i = 1:20
  feature     = y3(:, :, i);
  fList(:, i) = feature(:);
end
figure                                %创建新窗口
display_network(fList);               %显示卷积神经网络的最终输出图像
title('Features [Convolution + ReLU + MeanPool]')
                    %生成的图像被转换成一个一维向量,并存储在分类神经网络中。



7、线性整流函数-ReLU(x)-解决梯度消失问题

function y = ReLU(x)
  y = max(0, x);
end
%ReLU函数,线性整流函数,传递误差,解决梯度消失的问题。
%笔记位置,第5章-5.1-深度神经网络的改进

8、产生伪随机数-rng(x)

function rng(x)
  %rand和randn都是用来产生伪随机数的,发生器为'seed';
  randn('seed', x)
  rand('seed', x)
  %matlab推荐使用 %rng(0);代替使用randn('seed',0); 
        %更换的理由见笔记:matlab:rand('seed',sd)-伪随机数
end

9、深度神经网络所用冲激函数-Softmax(x)

function y = Softmax(x)
  ex = exp(x);
  y  = ex / sum(ex);
end
%激活函数softmax不仅考虑输入输入的加权和,还考虑其他输入节点的输入。
%详细公式见笔记-第4章-4.2-多元分类

10、实验现象

图像含义见绘图函数-PlotFeatures.

在此仅列出-深度神经网络训练函数MnistConv的训练结果:






11、一些说明:

1、导入导出图像路径的函数,本文并未列出。

2、完整工程文件,详见参考书,本文仅供学习参考。

3、参考书源代码下载地址:Apress网站.

//水平有限,能者见笑,大家见谅。

matlab可视化实战系列(四十)-基于matlab自带手写数字集的cnn(lenet5)手写数字识别-图像处理(附源代码)(代码片段)

一、前言利用MATLAB实践MNIST手写数字识别,下载手写数据集的准备工作有些麻烦。以下是我为大家准备的几个精品专栏,喜欢的小伙伴可自行订阅,你的支持就是我不断更新的动力哟!MATLAB-30天带你从入门到精通MATLAB深入理解高... 查看详情

《动手学深度学习》图像分类数据集(fashion-mnist)(代码片段)

图像分类数据集(Fashion-MNIST)图像分类数据集(Fashion-MNIST)获取数据集读取小批量小结参考文献数据集下载图像分类数据集(Fashion-MNIST)在介绍softmax回归的实现前我们先引入一个多类图像分类数据集。... 查看详情

[基于pytorch的mnist识别02]用户数据集的读取(代码片段)

写在前面pytorch包含了很多包括mnist在内的开源数据集,但是如果要建立自己的神经网络的话肯定需要训练自己的数据集,那么如何利用pytorch加载用户自己的数据集呢?今天就来解决这个问题。今天的工作需要加载用... 查看详情

百度paddlepaddle入门-8(代码片段)

...打印"HelloWorld!"一样。在飞桨的入门教程中,我们选取了基于MNIST数据集的手写数字识别模型作为启蒙教材,以便更好的帮助用户快速掌握飞桨平台的使用。MNIST是深度学习领域标准、易用的成熟数据集,包含60000条训练样本和100... 查看详情

步态识别基于深度学习的步态识别系统的matlab仿真,包括alexnet,改进cnn,googlenet(代码片段)

1.软件版本matlab2021a2.本算法理论知识    图显示了步态识别研究策略的流程图。在整个研究过程中,我们将从实际场景中记录多人的行走视频。利用颜色模型从行走视频中提取人体目标,得到人体目标行走的二值图... 查看详情

keras入门实战:手写数字识别

...数字识别是机器学习和深度学习领域的“helloworld”,MNIST数据集是手写数字的数据集合,训练集规模为60000,测试集为100 查看详情

深度学习笔记:基于keras库的mnist手写数字识别(代码片段)

...断8在测试集上评估模型9Summary1前言        本文介绍基于Keras库创建一个最简单的神经网络模型进行MNIST手写数字识别的试验。麻雀虽小五脏俱全,模型虽然简单但是这个试验基本上覆盖了一个深度学习任务的完整流程中... 查看详情

深度学习基于tensorflow的服装图像分类训练(数据集:fashion-mnist)(代码片段)

​活动地址:CSDN21天学习挑战赛目录前言了解Fashion-MNIST数据集下载数据集使用tensorflow下载(推荐)数据集分类数据集格式采用CPU训练还是GPU训练区别使用CPU训练使用GPU训练预处理最值归一化(normalization)升... 查看详情

基于tensorflow2.x实现bp神经网络,实践mnist手写数字识别(代码片段)

一、MNIST数据集MNIST是一个非常有名的手写数字识别数据集,在很多资料中都会被用作深度学习的入门样例。在Tensorflow2.x中该数据集已被封装在了tf.keras.datasets工具包下,如果没有指定数据集的位置,并先前也没有使... 查看详情

基于tensorflow2.x实现bp神经网络,实践mnist手写数字识别(代码片段)

一、MNIST数据集MNIST是一个非常有名的手写数字识别数据集,在很多资料中都会被用作深度学习的入门样例。在Tensorflow2.x中该数据集已被封装在了tf.keras.datasets工具包下,如果没有指定数据集的位置,并先前也没有使... 查看详情

实现手写体mnist数据集的识别任务(代码片段)

    实现手写体mnist数据集的识别任务,共分为三个模块文件,分别是描述网络结构的前向传播过程文件(mnist_forward.py)、描述网络参数优化方法的反向传播过程文件(mnist_backward.py)、验证模型准确率的 测试... 查看详情

实战google深度学习框架-c5-mnist数字识别问题

5.1MNIST数据处理 MNIST是NIST数据集的一个子集,包含60000张图片作为训练数据,10000张作为测试数据,其中每张图片代表0~9中的一个数字,图片大小为28*28(可以用一个28*28矩阵表示) 为了清楚表示,用下图14*14矩阵表示了,其实... 查看详情

matlab从入门到精通:matlab识别自带手写数字集的cnn(lenet5)

...语言实战应用精讲50篇 R语言函数解析及案例实战应用MATLAB-30天带你从入门到精通 MATLAB入门知识,函数原理解析及案例解析python快速学习实战应用系列课程 Python函数解析及实战应用案例MATLAB深入理解高级教程(附源码... 查看详情

深度学习基于tensorflow的小型物体识别训练(数据集:cifar-10)(代码片段)

​活动地址:CSDN21天学习挑战赛目录前言了解CIFAR-10数据集CIFAR-10数据集与MNIST数据集的区别下载数据集官方下载地址(较慢)使用tensorflow下载(推荐)使用迅雷(推荐)采用CPU训练还是GPU训练区别使用... 查看详情

深度学习基于华为mindspore的手写体图像识别实验(代码片段)

1实验介绍1.1简介Mnist手写体图像识别实验是深度学习入门经典实验。Mnist数据集包含60,000个用于训练的示例和10,000个用于测试的示例。这些数字已经过尺寸标准化并位于图像中心,图像是固定大小(28x28像素),其值为0到255... 查看详情

深度学习---从入门到放弃优化器(代码片段)

...任务的中进行说明。在这里我们使用的是手写数字的MNIST数据集,上图为MNIST数据集的部分展示。1.1网络构建思路1.网络种类:MLP通常来说在对于图片的分类上࿰ 查看详情

图像识别基于卷积神经网络cnn实现车牌识别matlab源码(代码片段)

 过去几年,深度学习(Deeplearning)在解决诸如视觉识别(visualrecognition)、语音识别(speechrecognition)和自然语言处理(naturallanguageprocessing)等很多问题方面都表现出非常好的性能。在不同类型的深度神经网络当中,卷积... 查看详情

毕业设计水果图像识别系统-深度学习opencvpython(代码片段)

...简介3识别原理3.1传统图像识别原理3.2深度学习水果识别4数据集5部分关键代码5.1处理训练集的数据结构5.2模型网络结构5.3训练模型6识别效果1前言🔥Hi,大家好,这里是丹成学长的毕设系列文章!🔥对毕设有... 查看详情