Matlab基于MNIST数据集的图像识别(深度学习入门卷积神经网络附完整学习资料)
Posted 阿汪先生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Matlab基于MNIST数据集的图像识别(深度学习入门卷积神经网络附完整学习资料)相关的知识,希望对你有一定的参考价值。
Matlab——数字0~9的图像识别(Phil Kim著、Matlab)
本文可以为那些想对深度学习和人工智能有初步了解的朋友提供一些基础入门的帮助。
本文所用参考书:
《MATLAB深度学习 机器学习、神经网络与人工智能》
【美】Phil Kim著
敖富江 杜静 周浩 译
清华大学出版社
ISBN:978-7-302-49638-0
水平有限,本文仅作学习交流,笔记分享所用。
工程文件由上述参考书给出,本文对该工程中部分函数作了一些注解,方便大家理解和应用。
所需的知识储备:
阿汪先生做的印象笔记链接:
- MATLAB深度学习-思维导图目录.
- 第1章-1.0-机器学习-绪论.
- 第1章-1.1-什么是机器学习.
- 第1章-1.2-机器学习面临的挑战.
- 第1章-1.3-机器学习的类型.
- 第2章-2.0-神经网络-绪论.
- 第2章-2.1、2.3-神经网络的节点、层.
- 第2章-2.4-神经网络的监督学习.
- 第2章-2.5、2.6-delta规则、广义delta规则.
- 第2章-2.7、2.8-SGD、Batch和Mini Batch.
- 第2章-2.9-神经网络的局限性.
- 第3章-3.0-多层神经网络的训练-绪论.
- 第3章-3.1-反向传播算法.
- 第3章-3.2-反向传播示例.
- 第3章-3.3-代价函数与学习规则.
- 第3章-3.4、3.5-交叉熵函数及其示例.
- 第3章-3.6、3.7-代价函数比较及本章小结.
- 第4章-4.0-神经网络与分类问题-绪论.
- 第4章-4.1-二元分类.
- 第4章-4.2-多元分类.
- 第4章-4.3-多元分类的示例及本章小结.
- 第5章-5.0-深度学习-绪论.
- 第5章-5.1-深度神经网络的改进.
- 第5章-5.2-ReLU与Dropout的实例.
- 第6章-6.0-卷积神经网络-绪论 .
- 第6章-6.1-卷积神经网络架构.
- 第6章-6.2-卷积层.
- 第6章-6.3-池化层.
- 第6章-6.4-MNIST示例.
- l第6章-6.5-本章小结.
部分工程文件注解:
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基于MNIST数据集的图像识别(深度学习入门卷积神经网络附完整学习资料)的主要内容,如果未能解决你的问题,请参考以下文章
Matlab基于MNIST数据集的图像识别(深度学习入门卷积神经网络附完整学习资料)
MATLAB可视化实战系列(四十)-基于MATLAB 自带手写数字集的CNN(LeNet5)手写数字识别-图像处理(附源代码)