Matlab深度学习


前言

   最近想在matlab环境下跑一下深度学习模型,找到了以下的一篇博客,但因为该博客所附录的资源失效,而且也可能因为版本问题导致数据集的预处理容易出bug,所以打算改成.mat格式数据上传到我的博客资源,方便下载和练习。原博客地址如下:
https://blog.csdn.net/longlongsvip/article/details/105466512
环境
Matlab: 2020b
GPU:NVIDIA Quadro P620
(注:Matlab2020b好像不支持NVIDIA安培架构显卡即不支持30系列,用3090在matlab2020b上测试过,报错找不到GPU)


一、MNIST手写体数字数据

   MNIST手写体数据包含60000个训练样本(数字0-9),以及测试集数据10000个(数字0-9),这里不再详细叙述数据集背景,上文博客写得很详细。 我已经将数据集转换为.mat文件格式(省去上文博客中的复杂预处理步骤),其数据格式如下:
在这里插入图片描述
由上图可以看出,图片是以一维的形式存储的,其数据维度为1 x 784,即原28 x 28 维度的图片压缩成了一维,所以在使用的时候需要将图片恢复为二维形式(代码下面给出)。

二、用到的深度学习框架-LeNet5

2-0 LeNet5的网络架构

在这里插入图片描述

2-1 框架实现-通过Matlab GUI 拖拽界面

打开matlab APP 的Deep Network Designer
在这里插入图片描述
打开后如下图所示:(可以选择好预训练的网络,也可以新建空白网络)
在这里插入图片描述
点击空白网络,根据LetNet5[1]的网络结构搭建网络(拖拽搭建)
在这里插入图片描述
搭建完成后点击分析,没问题后就可以导出(导出-生成代码)网络了
在这里插入图片描述

2-2 框架实现2-直接写框架代码

很明显,以上步骤是非必要的,老手可以直接写层代码来实现…

layers = [
    imageInputLayer([28 28 1],"Name","imageinput")
    convolution2dLayer([5 5],6,"Name","conv1","Padding","same")
    tanhLayer("Name","tanh1")
    maxPooling2dLayer([2 2],"Name","maxpool1","Stride",[2 2])
    convolution2dLayer([5 5],16,"Name","conv2")
    tanhLayer("Name","tanh2")
    maxPooling2dLayer([2 2],"Name","maxpool","Stride",[2 2])
    fullyConnectedLayer(120,"Name","fc1")
    fullyConnectedLayer(84,"Name","fc2")
    fullyConnectedLayer(10,"Name","fc")
    softmaxLayer("Name","softmax")
    classificationLayer("Name","classoutput")];

三、代码

3-0 机器学习与深度学习对比

   在进行实现深度网络前,可以先用传统机器学习的方法进行对比,有助于更好理解深度学习网络架构的优越性。

3-1 SVM分类手写体数字

   SVM作为机器学习的老大哥,在小样本,小分类数的情况下一直表现优异,但数据量庞大和分类数量比较多的情况下不一定合适。SVM在本例的评价如下:
运行时间:1星 (不管是训练还是测试都非常慢)
准确率: 1星
用到的SVM分类器为libsvm工具箱,其调用代码如下:

load handwriting.mat                               %载入数据集
model=svmtrain(y_train,x_train,'-c 2 -g 0.10');    %训练
[predicted_label]=svmpredict(y_test,x_test,model); %测试

3-2 ANN分类手写体数字

   相对于SVM,ANN人工神经网络更适合于处理数据量庞大的情况,但是相对与本例的LetNet-5而言,ANN忽略了输入图片的空间信息,即输入的数据是一维训练数据。设计的ANN网络结构如下:
在这里插入图片描述
   这里我用了3层隐藏层的ANN网络,其中第一层有100个神经元,第二层60个神经元,第三层40个神经元,第四层10个神经元。ANN在本例的表现评价如下:
运行时间:2星
准确率: 3星(Accuracy:95%)
ANN的实现用matlab自带的ANN工具箱,其调用代码如下:

load handwriting.mat     %载入手写体数字数据集
for i=1:size(y_train)
    if y_train(i)==0
        y_train(i)=10;    %这里把数字0标签换成10,不然出bug
    end
end
for j=1:size(y_test)
    if y_test(j)==0
        y_test(j)=10;     %这里把数字0标签换成10,不然出bug
    end
end
class=y_train;
[input,minI,maxI]=premnmx(x_train');
s = length( class) ;   
output = zeros( s , 2 ) ;%构造输出矩阵
for i = 1 : s 
   output( i , class( i )  ) = 1 ;
end
%% 网络参数
net = newff( minmax(input) , [100 60 40 10] , { 'logsig' 'logsig' 'logsig' 'purelin' } , 'traingdx' ) ;  %创建神经网络
%激活函数有'tansig' 'logsig'以及'purelin'三种
net.trainparam.show = 50 ;                %显示中间结果的周期
net.trainparam.epochs = 7000 ;            %最大迭代次数(学习次数)
net.trainparam.goal = 0.01 ;              %神经网络训练的目标误差
net.trainParam.lr = 0.001 ;               %学习速率(Learning rate)
%% 开始训练
net = train( net, input , output' ) ;     %其中input为训练集的输入信号,对应output为训练集的输出结果
%% GPU训练
% gpudev=gpuDevice;%事先声明gpudev变量为gpu设备类
% gpudev.AvailableMemory;%实时获得当前gpu的可用内存
% input=single(input);%double型的P转为single型
% output=single(output);%double型的T转为single型
% net = train( net, input , output' , 'useGPU','only' ) ;     %GPU
%% 测试
tic
testInput=tramnmx(x_test',minI,maxI);
Y=sim(net,testInput);
[s1 , s2] = size( Y ) ;                   %统计识别正确率
hitNum = 0 ;
predictChar=[];                           %输出结果
for i = 1 : s2
    [m , Index] = max( Y( : ,  i ) ) ;
    predictChar=[predictChar;Index];
    if( Index  == y_test(i)   ) 
        hitNum = hitNum + 1 ; 
    end
end
sprintf('识别率是 %3.3f%%',100 * hitNum / s2 )
toc

3-3 深度学习LetNet5

   通过第二节获得层参数layers后,就可以直接将该参数用于深度学习训练,当然训练前需要进行数据格式的转换,把一维数据转换为二维图片数据。LetNet5在本例的评价如下:
运行时间:3星(GPU训练)
准确率: 4星
代码如下:
Datapre.m(一维数据转换为二维)

load handwriting.mat
% 将一维数据转为二维图像数据
%% 训练集
X=x_train;              
X = permute(X,[2 1]);    %交换数据维度
X = X./255;              %归一化
X=reshape(X,[28,28,1,size(X,2)]);  
X = dlarray(X, 'SSCB');
Y=categorical(y_train);
%% 测试集
X2=x_test;
X2 = permute(X2,[2 1]);    %交换数据维度
X2 = X2./255;              %归一化
X2=reshape(X2,[28,28,1,size(X2,2)]);  
X2 = dlarray(X2, 'SSCB');
Y2=categorical(y_test);
%% 保存数据
save XY.mat X Y X2 Y2

CNNTrain.m(网络训练)

load XY.mat
XTrain=X;      %训练集
YTrain=Y;      %训练集标签
XTest=X2;      %测试集
Ytest=Y2;      %测试集标签
layers = [
    imageInputLayer([28 28 1],"Name","imageinput")
    convolution2dLayer([5 5],6,"Name","conv1","Padding","same")
    tanhLayer("Name","tanh1")
    maxPooling2dLayer([2 2],"Name","maxpool1","Stride",[2 2])
    convolution2dLayer([5 5],16,"Name","conv2")
    tanhLayer("Name","tanh2")
    maxPooling2dLayer([2 2],"Name","maxpool","Stride",[2 2])
    fullyConnectedLayer(120,"Name","fc1")
    fullyConnectedLayer(84,"Name","fc2")
    fullyConnectedLayer(10,"Name","fc")
    softmaxLayer("Name","softmax")
    classificationLayer("Name","classoutput")];

options = trainingOptions('sgdm', ...         %优化器
    'LearnRateSchedule','piecewise', ...      %学习率
    'LearnRateDropFactor',0.2, ...             
    'LearnRateDropPeriod',5, ...
    'MaxEpochs',20, ...                       %最大学习整个数据集的次数
    'MiniBatchSize',128, ...                  %每次学习样本数
    'Plots','training-progress');             %画出整个训练过程
    
%训练网络
trainNet = trainNetwork(XTrain, YTrain,layers,options); 

save Minist_LeNet5 trainNet                      %训练完后保存模型
yTest = classify(trainNet, XTest);               %测试训练后的模型
accuracy = sum(yTest == Ytest)/numel(yTest);     %模型在测试集的准确率
disp(accuracy)                                   %打印测试集准确率

CNNTest.m(通过JPG图片进行测试)

load('Minist_LeNet5');                      %导入训练好的LeNet5网络
test_image = imread('1.jpg');               %导入手写体数字图片
shape = size(test_image);
dimension=numel(shape);
if dimension > 2
    test_image = rgb2gray(test_image);      %灰度化
end
test_image = imresize(test_image, [28,28]); %保证输入为28*28
test_image = imcomplement(test_image);      %反转,使得输入网络时一定要保证图片 背景是黑色,数字部分是白色
test_image=double(test_image);
test_image=test_image';                     %旋转
test_image=test_image./255;                 %归一化
result = classify(trainNet, test_image);    %利用LetNet5分类
disp(result);

测试

测试用的是自己用windows画图工具画的10个数字,如下:
在这里插入图片描述
CNNTest.m运行结果:
在这里插入图片描述

最后

   手写体数字识别.mat数据集已经上传到我的博客资源,到我的博客资源就可以下载了。

   MNIST手写体数字数据集官网
   http://yann.lecun.com/exdb/mnist/

   参考文献
   [1] Lecun Y , Bottou L . Gradient-based learning applied to document recognition[J].    Proceedings of the IEEE, 1998, 86(11):2278-2324.

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐