深度学习之MNIST数字分类 - Matlab

前言

面向初学者的深度学习教程。

平台

matlab 2021a
MNIST数据集

代码

数据集

%% Instructions
%
% Train: dataset for training a neural network
% Test: dataset for test a trained neural network
% X: input / for Classification: image
% Y: output / for Classification: label
% angle: an image has been rotated by a certain angle

% Dimensionality of the image data: H*W*C*N 
% (H: height;   W: width;    C: channel(RGB:3,gray:1);  N: number)

%% setting up the way to load datasets
flag_use_dataset_matlab = 0;
flag_use_dataset_MNIST = 1;

%% 1. use the dataset from MATLAB
% https://www.mathworks.com/help/deeplearning/ug/data-sets-for-deep-learning.html
if flag_use_dataset_matlab == 1
    [XTrain,YTrain,anglesTrain] = digitTrain4DArrayData;
    [XTest,YTest,anglesTest] = digitTest4DArrayData;
end

%% 2. use the dataset from MNIST
% https://www.mathworks.com/help/deeplearning/ug/data-sets-for-deep-learning.html
% http://yann.lecun.com/exdb/mnist/
if flag_use_dataset_MNIST == 1
    oldpath = addpath(fullfile(matlabroot,'examples','nnet','main'));
    addpath dataset
    filenameImagesTrain = 'train-images-idx3-ubyte.gz';
    filenameLabelsTrain = 'train-labels-idx1-ubyte.gz';
    filenameImagesTest = 't10k-images-idx3-ubyte.gz';
    filenameLabelsTest = 't10k-labels-idx1-ubyte.gz';
    
    XTrain = processImagesMNIST(filenameImagesTrain);
    YTrain = processLabelsMNIST(filenameLabelsTrain);
    XTest = processImagesMNIST(filenameImagesTest);
    YTest = processLabelsMNIST(filenameLabelsTest);
end

训练

%% Load Training Data
disp('Loading training data...')
if 1
    [XTrain,YTrain] = digitTrain4DArrayData;
    classes = categories(YTrain);
    numClasses = numel(classes);
end
% classes_alt = {'0';'1';'2';'3';'4';'5';'6';'7';'8';'9'};

% A = [3,1,2,3]
% B = categorical(A)
% classes_test = categories(B)
image_input_size = [size(XTrain,1),size(XTrain,2),size(XTrain,3)];
image_size_h = size(XTrain,1);
image_size_w = size(XTrain,2);

%% define network
NN_layers = [
    imageInputLayer(image_input_size, 'Name','input','Mean',mean(XTrain,4))
    fullyConnectedLayer(image_size_h*image_size_w,'Name','fc1')
    reluLayer('Name', 'relu1')
%     fullyConnectedLayer(1024,'Name','fc2')
%     reluLayer('Name','relu2')
    fullyConnectedLayer(512,'Name','fc3')
    reluLayer('Name','relu3')
    fullyConnectedLayer(numClasses,'Name','fc')
    softmaxLayer('Name','softmax')];
lgraph = layerGraph(NN_layers);
% Create a dlnetwork object from the layer graph.
dlnet = dlnetwork(lgraph);
% visualize the neural network
analyzeNetwork(dlnet)

%% Define Model Gradients Function
function [gradients,loss,dlYPred] = modelGradients(dlnet,dlX,Y)

    dlYPred = forward(dlnet,dlX);
    
    loss = crossentropy(dlYPred,Y);
    
    gradients = dlgradient(loss,dlnet.Learnables);
    
end

%% Specify Training Options (hyperparameters)

miniBatchSize = 128;
numEpochs = 10;
learnRate = 0.001;

numObservations = numel(YTrain);
numIterationsPerEpoch = floor(numObservations./miniBatchSize);

% training on CPU or GPU(if available);
% 'auto': Use a GPU if one is available. Otherwise, use the CPU.
% 'cpu' : Use the CPU
% 'gpu' : Use the GPU.
% 'multi-gpu' :Use multiple GPUs
% 'parallel :
executionEnvironment = "auto";

print_frequency = 10;

%% Train neural network
% Visualize the training progress in a plot
plots = "training-progress";
if plots == "training-progress"
    figure
    lineLossTrain = animatedline('Color',[0.85 0.325 0.098]);
    ylim([0 inf])
    xlabel("Iteration")
    ylabel("Loss")
    grid on
end
% initialize the average gradients and squared average gradients
exist averageGrad;
if ans == 0
    averageGrad = [];
    averageSqGrad = [];
end

start = tic;
iteration = 0;
start_time = clock;

fprintf("|=======================================================================================|\n")
fprintf("|\t Epoch \t|\t Iteration \t|\t Time Elapsed \t|\t Mini-batch \t|\t Mini-batch \t|\n")
fprintf("|\t  \t \t|\t \t \t \t|\t \t (s) \t \t|\t \tloss \t \t|\t  Accuracy \t \t|\n")
fprintf("|=======================================================================================|\n")
for epoch = 1:numEpochs
    % Shuffle data.
    idx = randperm(numel(YTrain));
    XTrain = XTrain(:,:,:,idx);
    YTrain = YTrain(idx);
    
    for i = 1:numIterationsPerEpoch
        iteration = iteration + 1;
        
        % Read mini-batch of data and convert the labels to dummy
        % variables.
        idx = (i-1)*miniBatchSize+1:i*miniBatchSize;
        X = XTrain(:,:,:,idx);
        
        Y = zeros(numClasses, miniBatchSize, 'single');
        for c = 1:numClasses
            Y(c,YTrain(idx)==classes(c)) = 1;
        end
        
        % Convert mini-batch of data to a dlarray.
        dlX = dlarray(single(X),'SSCB');
        
        % If training on a GPU, then convert data to a gpuArray.
        if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu"
            dlX = gpuArray(dlX);
        end
        
        % Evaluate the model gradients and loss using dlfeval and the
        % modelGradients helper function.
        [grad,loss,dlYPred] = dlfeval(@modelGradients,dlnet,dlX,Y);
        
        % Update the network parameters using the Adam optimizer.
        [dlnet,averageGrad,averageSqGrad] = adamupdate(dlnet,grad,averageGrad,averageSqGrad,iteration,learnRate);
        
        % Display the training progress.
        if plots == "training-progress"
            D = duration(0,0,toc(start),'Format','hh:mm:ss');
            addpoints(lineLossTrain,iteration,double(gather(extractdata(loss))))
            title("Epoch: " + epoch + ", Elapsed: " + string(D) + ", Loss: " + num2str(double(gather(extractdata(loss)))))
            drawnow
        end
        current_time=clock;
        elapsed_time=etime(current_time,start_time);
        
        if mod(i,print_frequency) == 0
            
            [~,idx] = max(extractdata(dlYPred),[],1);
            YPred = classes(idx);
                       
            [~,Y_label] = max(Y,[],1);
            Y_label = classes(Y_label);
            accuracy_test = mean(YPred==categorical(Y_label));
            
            
            i_in_total = i + (epoch-1) *numIterationsPerEpoch;
            %             fprintf("| %10d | %13d | %20.4f |  %20f | \n" , epoch,i_in_total,round(elapsed_time,3),round(gather(extractdata(loss)),5))
            fprintf("| %9d | %13d | %17.4f |  %16f | %17.2f |\n" , epoch,i_in_total,round(elapsed_time,3),round(gather(extractdata(loss)),5),round(accuracy_test,2))
            
        end
    end
end
fprintf("|=======================================================================================|\n")

%% test neural network 
[XTest, YTest] = digitTest4DArrayData;
dlXTest = dlarray(XTest,'SSCB');
if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu"
    dlXTest = gpuArray(dlXTest);
end

dlYPred = predict(dlnet,dlXTest);
[~,idx] = max(extractdata(dlYPred),[],1);
YPred = classes(idx);

accuracy_test = mean(YPred==YTest)

figure_show_test_result = figure;
    figure_show_test_result.Name = ("test result");

for index_temp = 1:10
    figure_show_test_result();
    subplot(2,5,index_temp);imagesc(XTest(:,:,:,1 +(index_temp-1)*500 ));title(YPred(1 +(index_temp-1)*500 ))
    axis image;set(gca,'XColor', 'none','YColor','none');
end 

测试

结语

你可能感兴趣的:(深度学习,MATLAB,matlab,深度学习,分类算法)