原文链接
卷积神经网络是深度学习的基本工具,尤其适用于图像识别。
这个示例展示给我们:

  • 加载和浏览图像数据
  • 定义网络架构
  • 指定训练选项
  • 训练网络
  • 预测新数据的标签并计算分类准确度

    加载和浏览图像数据

    加载数字样本数据作为图像数据存储。imageDatastore根据文件夹名称自动标记图像,并将数据存储为 imageDataStore图像。通过图像数据存储可以存储大图像数据,包括无法放入内存的数,并在卷积神经网络的训练过程中高校分批读取图像。

    1. digitDatasetPath = fullfile(matlabroot, 'toolbox', 'nnet', 'nndemos', 'nndatasets', 'DigitDataset');
    2. imds = imageDatastore(digitDatasetPath, 'IncludeSubfolders', true, 'LabelSource', 'foldernames');

    显示数据存储中的部分图像

    1. figure;
    2. perm = randperm(10000, 20); %随机选取20个数
    3. for i = 1 : 20
    4. subplot(4, 5, i);
    5. imshow(imds.Files{perm(i)}); %选取20张图片展示
    6. end

    计算每个类别中的图像数量。labelCount是一个表,其中列出了标签,以及每个标签对应的图像数量。数据存储包含数组0-9的总共10000张图像,每个数字对应1000张图像。可以在网络的最后一个连接层中指定类数作为 OutputSize参数。

    1. labelCount = countEachLabel(imds);

    必须在网络的输入层中指定图像的大小,检查digitData中第一个图像的大小,每个图像的大小为♠ 创建简单的神经网络用于分类 - 图1像素。

    1. img = readimage(imds, 1);
    2. size(img)

    指定训练集和验证集

    将数据划分为训练数据集和验证数据集,以使训练集中的每个类别包含750个图象,并且验证集中包含对应每个标签的其余图像。splitEachLabel将数据存储digitData拆分为两个新的数据存储trainDigitDatavalDigitData

    1. numTrainFiles = 750;
    2. [imdsTrain, imdsValidation] = splitEachLabel(imds, numTrainFiles, 'randomize');

    定义网络架构

    定义卷积神经网络架构

    1. layers = [imageInputLayer([28, 28, 1])
    2. convolution2dLayer(3, 8, 'Padding', 'same')
    3. batchNormalizationLayer
    4. reluLayer
    5. maxPooling2dLayer(2, 'Stride', 2)
    6. convolution2dLayer(3, 16, 'Padding', 'same')
    7. batchNormalizationLayer
    8. reluLayer
    9. maxPooling2dLayer(2, 'Stride', 2)
    10. convolution2dLayer(3, 32, 'Padding', 'same')
    11. batchNormalizationLayer
    12. reluLayer
    13. fullyConnectedLayer(10)
    14. softmaxLayer
    15. classificationLayer
    16. ];

    图像输入层

    imageInputLayer用于指定图像大小,在本例中为♠ 创建简单的神经网络用于分类 - 图2。这些数字对应高度宽度和通道大小。数字数据由灰度图像组成,因此颜色通道大小为1。对于彩色图像,通道大小为3,对应于RGB值。并不需要打乱数据,因为 trainNetwork默认会在训练开始时打乱数据。trainNetwork还可以在训练过程中的每轮训练开始时自动打乱数据。

    卷积层

    在卷积层中,第一个参数是filterSize,它是训练函数在沿图像扫描时使用的过滤器的高度和宽度。在此示例中,数字3代表过滤器大小为♠ 创建简单的神经网络用于分类 - 图3。我们可以为过滤器的高度和宽度指定不同的大小。第二个参数是过滤器的数量 numFilters,它是连接到同一区域的神经元数量。此参数决定了特征图的数量。使用 ‘Padding’名称-值对组对输入特征图进行填充。对于默认幅度为1的卷积层,’same’填充确保空间输出大小和输入大小相同。也可以使用 convolution2dLayer名称-值对组参数定义该层的步幅和学习率。

    批量归一化

    批量归一化层对网络中的激活值和梯度传播进行归一化,使网络训练成为更简单的优化问题。在卷积层和非线性部分(例如ReLU层)之间使用批量归一化层,使网络称为更简单的优化问题。在卷积层和非线性部分(例如ReLU层)之间使用批量归一化层,来加速网络训练并降低对网络初始化的敏感度。使用 batchNormalizationLayer创建批量归一化层。

    ReLU层

    批量归一化后接一个非线性激活函数。最常见的激活函数是修正线性单元(ReLU),使用reluLayer创建ReLU层。

    最大池化层

    卷积层(带激活函数)有时会后跟下采样操作,以减小特征图的空间大小并删除冗余空间信息,通过下采样可以增加更深卷积层中的过滤器数量,而不会增加每层所需的计算量。下采样的一种方法是使用最大池化,可以使用maxPooling2dLayer创建。最大池化层返回第一个参数 poolSize指定的矩形输入区域的最大值。在此示例中,该矩形区域的大小是♠ 创建简单的神经网络用于分类 - 图4。’Stride’名称-值对组参数指定训练函数在沿输入扫描时所采用的步长。

    全连接层

    卷积层和下采样层后跟一个或多个全连接层。顾名思义,全连接层中的神经元将连接到前一层中的所有神经元,该层将先前层在图像学习的所有特征组合在一起,以识别较大的模式,最后一个全部连接层中的 OutputSize参数等于目标数据中的类数。在此示例中,输出大小为10,对应于10个类。使用fullyConnectedLayer创建全连接层。

    softmax层

    softmax激活函数对全连接层的输出进行归一化,softmax层的输出由总和为1的多个正数组成,这些数字随后可以被分类层用作分类概率。使用 softmaxLayer函数在最后一个全连接层创建一个softmax层

    分类层

    最终层是分类层。该层使用softmax激活函数针对每个输入返回的概率,将输入分配到其中一个互斥类并计算损失。创建分类层使用classificationLayer

    指定训练选项

    定义网络结构体后,指定训练选项。使用具有动量的随机梯度下降(SGDM)训练网络,初始学习率为0.01。将最大训练轮数设置为4。一轮训练是对整个训练数据集的一个完整训练周期。通过指定验证数据和验证频率,监控训练过程中的网络准确度,每轮训练都会打乱数据。基于训练数据训练网络,并在训练过程中按固定时间间隔计算基于验证数据的准确度。验证数据不用于更新网络权重。打开训练进度图,关闭命令行窗口输出。

    1. options = trainingOptions('sgdm',...
    2. 'InitialLearnRate', 0.01,...
    3. 'MaxEpochs', 4,...
    4. 'Shuffle', 'every-epoch',...
    5. 'ValidationData', imdsValidation,...
    6. 'ValidationFrequency', 30,...
    7. 'Verbose', false, ...
    8. 'Plots', 'training-progress');

    使用训练数据训练网络

    使用layers定义的架构,训练数据和训练选项训练网络。默认情况下,如果有GPU可用,trainNetwork就会使用GPU(需要Parallel Computing Toolbox和具有3.0或更高计算能力的支持CUDA的GPU)。否则,将使用CPU。您还可以使用 trainingOptionsExecutionEnvironment名称-值对组参数指定执行环境。
    训练进度图显示了小批量损失和准确度以及验证损失和准确度。有关训练进度图的详细信息,请参阅监控深度学习训练进度。损失是交叉熵损失。准确度是网络分类正确的图像的百分比。

    1. net = trainNetwork(imdsTrain, layers, options);

    对验证图像进行分类并计算准确度

    使用经过训练的网络预测验证数据的标签,并计算最终验证准确度。准确度是网络预测正确的标签的比例。在本例中,超过99%的预测标签与验证集的真是标签相匹配。 ```matlab YPred = classify(net, imdsValidation); YValidation = imdsValidation.Labels;

accuracy = sum(YPred == YValidation)/numel(YValidation); ```