天天看點

Matlab深度學習-手寫體數字識别Matlab深度學習前言一、MNIST手寫體數字資料二、用到的深度學習架構-LeNet5三、代碼最後

Matlab深度學習

文章目錄

  • Matlab深度學習
  • 前言
  • 一、MNIST手寫體數字資料
  • 二、用到的深度學習架構-LeNet5
    • 2-0 LeNet5的網絡架構
    • 2-1 架構實作-通過Matlab GUI 拖拽界面
    • 2-2 架構實作2-直接寫架構代碼
  • 三、代碼
    • 3-0 機器學習與深度學習對比
    • 3-1 SVM分類手寫體數字
    • 3-2 ANN分類手寫體數字
    • 3-3 深度學習LetNet5
    • 測試
  • 最後

前言

   最近想在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檔案格式(省去上文部落格中的複雜預處理步驟),其資料格式如下:

Matlab深度學習-手寫體數字識别Matlab深度學習前言一、MNIST手寫體數字資料二、用到的深度學習架構-LeNet5三、代碼最後

由上圖可以看出,圖檔是以一維的形式存儲的,其資料次元為1 x 784,即原28 x 28 次元的圖檔壓縮成了一維,是以在使用的時候需要将圖檔恢複為二維形式(代碼下面給出)。

二、用到的深度學習架構-LeNet5

2-0 LeNet5的網絡架構

Matlab深度學習-手寫體數字識别Matlab深度學習前言一、MNIST手寫體數字資料二、用到的深度學習架構-LeNet5三、代碼最後

2-1 架構實作-通過Matlab GUI 拖拽界面

打開matlab APP 的Deep Network Designer

Matlab深度學習-手寫體數字識别Matlab深度學習前言一、MNIST手寫體數字資料二、用到的深度學習架構-LeNet5三、代碼最後

打開後如下圖所示:(可以選擇好預訓練的網絡,也可以建立空白網絡)

Matlab深度學習-手寫體數字識别Matlab深度學習前言一、MNIST手寫體數字資料二、用到的深度學習架構-LeNet5三、代碼最後

點選空白網絡,根據LetNet5[1]的網絡結構搭建網絡(拖拽搭建)

Matlab深度學習-手寫體數字識别Matlab深度學習前言一、MNIST手寫體數字資料二、用到的深度學習架構-LeNet5三、代碼最後

搭建完成後點選分析,沒問題後就可以導出(導出-生成代碼)網絡了

Matlab深度學習-手寫體數字識别Matlab深度學習前言一、MNIST手寫體數字資料二、用到的深度學習架構-LeNet5三、代碼最後

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網絡結構如下:

Matlab深度學習-手寫體數字識别Matlab深度學習前言一、MNIST手寫體數字資料二、用到的深度學習架構-LeNet5三、代碼最後

   這裡我用了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個數字,如下:

Matlab深度學習-手寫體數字識别Matlab深度學習前言一、MNIST手寫體數字資料二、用到的深度學習架構-LeNet5三、代碼最後

CNNTest.m運作結果:

Matlab深度學習-手寫體數字識别Matlab深度學習前言一、MNIST手寫體數字資料二、用到的深度學習架構-LeNet5三、代碼最後

最後

   手寫體數字識别.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.

繼續閱讀