MATLAB深度学习入门之旅

目录
1. 简介
2. 使用预训练网络:使用已创建和训练后的网络进行分类
2.1 课程示例-识别一些图像中的对象
2.1.1任务1:读取图像
2.1.2任务2:显示图像
2.2 进行预测
2.2.1任务1:定义网络
2.2.2任务2:进行分类
2.3 CNN结构
2.3.1任务1:提取网络的层
2.3.2任务2:提取某一层
2.3.3任务3:提取某一层的某个属性
2.3.4任务4:图像维度
2.3.5任务5:提取输出层的类属性
2.4 调查预测
2.4.1任务1:预测分数
2.4.2任务2:创建预测分类的条形图
2.4.3任务3:挑出主要分数
2.4.4任务4:显示挑选预测分数后的条形图
2.4.4任务5:为x轴增加类别标签
3 管理数据集:使用已创建和训练后的网络执行分类
3.1 图像数据集
3.1.1任务1:使用imageDatastore创建数据存储(DataStore)
3.1.2任务2:获取文件名
3.1.3任务3:从数据存储(DataStore)中导入某幅图像
3.1.4任务4:预测数据存储(DataStore)中的所有图像
3.2 准备输入图像
3.2.1任务1:查看图像大小
3.2.2任务2:查看网络输入层的输入图像大小
3.2.3任务3:将输入图像调整至要求大小并显示
3.3 在数据存储(DataStore)中处理图像
3.3.1创建增强图像数据存储(DataStore)
3.3.2使用增强的图像数据存储(DataStore)进行颜色预处理
3.4 使用子文件夹创建一个数据存储(DataStore)
3.4.1任务1:创建数据存储(Data Store)
3.4.2任务2:分类
4 迁移学习:修改预训练网络对图像分类
4.1 什么是迁移学习?
4.2 迁移学习所需的组件
4.3 准备训练数据
4.3.1标记图像
4.3.2分割数据以用于训练和测试
4.4 修改网络层
4.4.1任务1:使用fullyConnectedLayer函数创建一个新的全连接层
4.4.2任务2:对层的数组通过索引进行修改
4.4.3任务3:将输出层与前面的层(第23层)进行匹配
4.5 设置训练选项
4.5.1任务1:使用trainingOptions设置训练算法的一些选项(一定要查看帮助手册)
4.5.2任务2:设置初始学习率
4.6 训练网络
4.6.1mini-batch
4.6.2使用GPUs
4.6.3迁移学习示例(脚本)
4.7 评估性能
4.7.1评估训练和测试性能
4.7.2调查测试性能
1. 简介 该课程为MATLAB官网免费课程(英文),此笔记只对该课程进行一定的翻译和记录,方便日后复习,如有错误,还请大佬批评指正。官网链接为https://ww2.mathworks.cn/learn/tutorials/deep-learning-onramp.html(深度学习入门之旅)。
2. 使用预训练网络:使用已创建和训练后的网络进行分类 2.1 课程示例-识别一些图像中的对象 本节将学习如何使用预先制作的深度神经网络来分类下面12幅图像的内容。理想的分类应该是“海滩”、“猫”、“纸杯蛋糕”、“湖泊”、“鱼”等等。
MATLAB深度学习入门之旅
文章图片

2.1.1任务1:读取图像
I = imread('filename.png'); % 以分号结束将不会打印出结果
2.1.2任务2:显示图像
imshow(I)
2.2 进行预测 2.2.1任务1:定义网络
net = alexnet% 这里的网络模型使用Alexnet
2.2.2任务2:进行分类
[pred, score] = classify(net,img)% 将网络和输入图像传入分类函数,将得到输入图像的类别preds以及它在每一类中的预测分数score
2.3 CNN结构 MATLAB将CNN表示为一个层的数组,数组的第一个元素为输入层,最后一个元素为输出层。
MATLAB深度学习入门之旅
文章图片

2.3.1任务1:提取网络的层
ly = net.Layers% 由下图可以看出Alexnet是一个具有25层的数组
MATLAB深度学习入门之旅
文章图片

2.3.2任务2:提取某一层
inlayer = ly(1)% 输入层
layer2 = ly(2)% 第二层
outlayer = ly(end)% 分类输出层
MATLAB深度学习入门之旅
文章图片
MATLAB深度学习入门之旅
文章图片
MATLAB深度学习入门之旅
文章图片

2.3.3任务3:提取某一层的某个属性
insz = inlayer.InputSize% 输入层的输入图像大小
2.3.4任务4:图像维度
输入图像是彩色图像,尺寸为:227×227×3。灰度图像的尺寸为227×227。
2.3.5任务5:提取输出层的类属性
categorynames = outlayer.Classes% 得到一个列向量,表示Alexnet的1000个类的名字
2.4 调查预测 2.4.1任务1:预测分数
上面的分类函数classify只是将输入图像预测为某一类,并不知道输入图像是该类的概率。该任务不仅会得到预测分类,还会得出预测分数。
[pred,scrs] = classify(net,img)% 得到的分数是一个行向量,表示1000个类的预测分数
MATLAB深度学习入门之旅
文章图片

2.4.2任务2:创建预测分类的条形图
bar(scrs)
MATLAB深度学习入门之旅
文章图片

2.4.3任务3:挑出主要分数
由上图可知,1000个分类中大部分的值为0,仅有少数预测分数不等于0,本任务旨在将主要分数挑选出来,可以创建一个逻辑数组,返回scrs中大于0.01的值
highscores = scrs > 0.01% 将scrs数组中大于0.01的元素赋为1,其他为0
2.4.4任务4:显示挑选预测分数后的条形图
bar(scores(highscores))% scores(highscores)返回大于0.01的类别的预测分数
MATLAB深度学习入门之旅
文章图片

2.4.5任务5:为x轴增加类别标签
xticklabels(categorynames(highscores))% categorynames(highscores) 返回大于0.01的类别的名字
MATLAB深度学习入门之旅
文章图片

3 管理数据集:使用已创建和训练后的网络执行分类 3.1 图像数据集 3.1.1任务1:使用imageDatastore创建数据存储(DataStore)
ls *.jpg% list列出工作空间里与.jpg相关的文件,工作空间中文件夹里的无法列出
net = alexnet;
imds = imageDatastore('*.jpg')% 使用通配符*指定多个文件。
MATLAB深度学习入门之旅
文章图片
MATLAB深度学习入门之旅
文章图片

3.1.2任务2:获取文件名
fname = imds.Files% 使用数据存储(DataStore)的Files属性获取包含路径的文件名
3.1.3任务3:从数据存储(DataStore)中导入某幅图像
使用函数:read, readimage, readall可以手动地从数据存储(DataStore)中导入图像
for i = 1:3
img = read(imds)% 按顺序依次读取图像,每次仅返回一张图像
end
img = readimage(imds, 7)% 读取并返回数据存储(DataStore)中的某张(第7张)图像
img = readall(imds)% 一次性读取数据存储(DataStore)中的所有图像,返回的并不是图像数据
3.1.4任务4:预测数据存储(DataStore)中的所有图像
preds = classify(net, imds)
3.2 准备输入图像 由于不同的网络对输入图像的要求不同,所以需要对输入图像进行预处理后再输入网络。
3.2.1任务1:查看图像大小
img = imread('filename.jpg');
imshow(img)
sz = size(img)% 返回图像的高度、宽度、通道数
3.2.2任务2:查看网络输入层的输入图像大小
net = alexnet
ly = net.Layers
insz = ly(1).InputSize
3.2.3任务3:将输入图像调整至要求大小并显示
img = imresize(img, [r, c]); % r为行(高度),c为列(宽度)
imshow(img)
3.3 在数据存储(DataStore)中处理图像 上面是对单个图像进行预处理,但平常的数据集中的图像数量相当之大。因此,直接对整个图像数据集进行处理就显得很有必要了。
3.3.1创建增强图像数据存储(DataStore)
3.3.3.1任务1:创建数据存储(DataStore)
ls *.jpg
net = alexnet
imds = imageDatastore('*.jpg')
3.3.3.2任务2:创建增强的图像数据存储(DataStore)
auds = augmentedImageDatastore([r c],imds)% 将数据存储(DataStore)中所有图像的大小统一调整到[r c]大小,特别强调r与c没有逗号
3.3.3.3任务3:对预处理后的图像数据存储(DataStore)进行分类
preds = classify(net, auds)
3.3.2使用增强的图像数据存储(DataStore)进行颜色预处理
3.3.2.1任务1:蒙太奇(montage)
ls *.jpg
net = alexnet
montage(imds)% 使用蒙太奇手法显示数据存储(DataStore)中的所有图像
MATLAB深度学习入门之旅
文章图片

3.3.2.2任务2:创建增强图像数据存储(DataStore)
这里做的增强除了调整大小之外,还有灰色图像转换为彩色图像
auds = augmentedImageDatastore([227 227], imds, 'ColorPreprocessing', 'gray2rgb')
3.3.2.3任务3:对预处理后的图像数据存储(DataStore)进行分类
preds = classify(net, auds)
3.4 使用子文件夹创建一个数据存储(DataStore) 将每一类的图像放在一个子文件夹下,图像已经按照这种格式放置,而非按照这种方式去创建。
MATLAB深度学习入门之旅
文章图片

3.4.1任务1:创建数据存储(Data Store)
net = alexnet;
ds = imageDatastore('folder', 'IncludeSubfolders', true)% folder为图像数据集的路径,使用“IncludeSubfolders”选项在给定文件夹的子文件夹中查找图像。
3.4.2任务2:分类
preds = classify(net, ds)
4 迁移学习:修改预训练网络对图像分类 4.1 什么是迁移学习? 如果从网络架构和随机权重开始,自己构建和训练网络。但要达到合理的结果需要付出很多努力:(1)网络架构的知识和经验,(2)大量的训练数据,(3)大量的计算机时间。
迁移学习是解决许多问题的有效方法。训练需要一些数据和计算机时间,但比从零开始的培训要少得多,其结果是形成了适合您的特定问题的网络。
4.2 迁移学习所需的组件 三大件:
修改后的网络Network layers
知道标签的训练数据Training data
训练算法Algorithm options
MATLAB深度学习入门之旅
文章图片

4.3 准备训练数据 将训练数据按照类别数分为一定的子文件夹进行存放,每个子文件夹的名字为相应类别的标签。如下图,花的数据集,包含12个类,所以有12个子文件夹,每个子文件夹的名字为每类花的名字。
MATLAB深度学习入门之旅
文章图片

4.3.1标记图像
4.3.1.1任务1:创建带标签的数据集
load pathToImages% 加载数据集文件pathToImages.mat
flwrds = imageDatastore(pathToImages,'IncludeSubfolders', true);
flowernames = flwrds.Labels
训练所需的标签可以存储在图像数据存储库的标签属性中。默认情况下,标签属性为空。
MATLAB深度学习入门之旅
文章图片

通过指定“LabelSource”选项,可以让数据存储自动确定文件夹名称中的标签。如果指定了 'foldernames',将根据文件夹名称分配标签并存储在 Labels 属性中。您以后可以通过直接访问 Labels 属性来修改标签。
flwrds = imageDatastore(pathToImages, 'IncludeSubfolders',true, 'LabelSource', 'foldernames')
MATLAB深度学习入门之旅
文章图片

4.3.1.2任务2:提取新的标签
flowernames = flwrds.Labels
4.3.2分割数据以用于训练和测试 4.3.2.1任务1:使用splitEachLabel函数分割数据集
[ds1,ds2] = splitEachLabel(imds,p)% imds是创建的数据存储,p是零一之间的一个比例,返回的ds1是imds的p倍,剩下的imds分配给ds2,即ds2是imds的(1-p)倍
4.3.2.2任务2:随机分割分割
[ds1,ds2] = splitEachLabel(imds,p,'randomized')
4.3.2.3任务3:处理不平衡的训练数据
由于某些数据集在类别上是不平衡的,也即是说,可能有些类的数据多一些,有些类的数据少一些,它们的数目并不是相等的。因此,使用按比例分配的方式主要在数据多的类上进行学习,在数据少的类少学习很少。为了避免这种情况,可以对数据进行分割,使每个类的训练图像具有相等的数量。
[ds1,ds2] = splitEachLabel(imds, n, 'randomized')% 确保ds1中的每一类都有n个数据,剩下的数据分给ds2, 'randomized'可选
4.4 修改网络层 不同的数据集往往类别数也不同,因此,需要对网络中的某些层进行修改,比如输出层的神经元个数应该修改为数据集的类别数。
4.4.1任务1:使用fullyConnectedLayer函数创建一个新的全连接层
anet = alexnet;
layers = anet.Layers
fc = fullyConnectedLayer(n)% n是新建全连接层的神经元个数
4.4.2任务2:对层的数组通过索引进行修改
layers(23) = fc% 将Alexnet的第23层修改为上述新建的全连接层
4.4.3任务3:将输出层与前面的层(第23层)进行匹配
layers(end) = classificationLayer% 使用classificationLayer函数新建一个分类层,并赋给最后一层(输出层),该函数将自动确定输出层的神经元个数
4.5 设置训练选项 4.5.1任务1:使用trainingOptions设置训练算法的一些选项(一定要查看帮助手册)
opts = trainingOptions(solverName)% 返回一个由solverName指定的优化器的选项,solverName默认为'sgdm'
还可以设置

options = trainingOptions('sgdm', ...

'LearnRateSchedule','piecewise', ...% 学习率减少方案

'LearnRateDropFactor',0.2, ...

'LearnRateDropPeriod',5, ...% 每5个epoch减少0.2倍的学习率

'MaxEpochs',20, ...% 最多迭代的epoch数

'MiniBatchSize',64, ...% 每个epoch迭代的batchsize

'Plots','training-progress')
MATLAB深度学习入门之旅
文章图片

'Plots'设置为'training-progress'时有下图
MATLAB深度学习入门之旅
文章图片

4.5.2任务2:设置初始学习率
学习率控制算法改变网络权重的幅度。迁移学习的目标是对现有的网络进行微调,因此通常希望更改权重,而不是像从头开始训练时那样大刀阔斧。
opts = trainingOptions('sgdm','Name', value)% 指定训练选项的名称'Name'和值value(相当于字典的键值对)
opts = trainingOptions('sgdm', 'InitialLearnRate', 0.001)
4.6 训练网络 4.6.1mini-batch
MATLAB深度学习入门之旅
文章图片

mini-batch是指在每一次迭代过程中,用到的部分训练集。每次迭代都会使用不同的mini-batch。当整个数据集都被使用过一次后,这样的一个周期称为epoch。训练多少个周期可以通过设置'MaxEpochs'来实现。
值得注意的是,损失和准确率是针对当前的mini-batch而言的,而非整个训练集的平均
默认在划分mini-batch之前,通常会对数据集进行洗牌,你可以通过shuffle选项来设置。
4.6.2使用GPUs
GPU可以显著提高深度学习的计算性能。如果你的计算机不支持GPU的话,MATLAB将会在CPU上执行训练过程,不过这会花费大量的时间。
4.6.3迁移学习示例(脚本)
  • 获取训练图像
flower_ds = imageDatastore('Flowers','IncludeSubfolders',true,'LabelSource','foldernames');
[trainImgs,testImgs] = splitEachLabel(flower_ds,0.6);
numClasses = numel(categories(flower_ds.Labels)); % 这句话是前面没有的,目的是取类别数。numel表示取数组的元素数目,categories返回一个字符向量元胞数组,其中包含分类数组的类别。
  • 创建一个修改后的Alexnet
net = alexnet;
layers = net.Layers;
layers(end-2) = fullyConnectedLayer(numClasses);
layers(end) = classificationLayer;
  • 设置训练算法选项
options = trainingOptions('sgdm','InitialLearnRate', 0.001);
  • 执行训练
[flowernet,info] = trainNetwork(trainImgs, layers, options); % flowernet是训练后的网络(具有新的参数),info是训练信息(包含训练损失、准确率等信息)
  • 使用训练网络去分类测试图像
testpreds = classify(flowernet,testImgs);
4.7 评估性能 4.7.1评估训练和测试性能
4.7.1.1任务1:画出训练损失(位于info的TrainingLoss中)
load pathToImages
load trainedFlowerNetwork flowernet info
plot(info.TrainingLoss)
4.7.1.2任务2:分类图像
dsflowers =imageDatastore(pathToImages,'IncludeSubfolders',true,'LabelSource', 'foldernames');
[trainImgs,testImgs] = splitEachLabel(dsflowers,0.98);
flwrPreds = classify(flowernet,testImgs)
4.7.2调查测试性能
4.7.2.1任务1:提取测试数据集的标签
load pathToImages.mat
pathToImages
flwrds = imageDatastore(pathToImages,'IncludeSubfolders',true,'LabelSource', 'foldernames');
[trainImgs,testImgs] = splitEachLabel(flwrds,0.98);
load trainedFlowerNetwork flwrPreds
flwrActual = testImgs.Labels% trainImgs,testImgs是对数据存储进行划分得到的,所以它们具有数据存储的相关属性
4.7.2.2任务2:计算正确个数
numCorrect = nnz(flwrActual == flwrPreds)% nnz函数返回的是矩阵非零元素的数目,flwrActual == flwrPreds将得到一个0-1矩阵
4.7.2.3任务3:计算正确率
fracCorrect = numCorrect/numel(flwrPreds)% 就是正确个数除以测试数据的个数
上面的计算有些麻烦,先改写为:
mean(flwrActual == flwrPreds)
4.7.2.4任务4:显示预测分类的混淆矩阵
混淆矩阵又称误差矩阵,矩阵中的元素(j,k)表示第j个类被预测为第k个类的数目,主对角线的元素表示正确预测,其余元素表示误分类。
confusionchart(knownclass,predictedclass)% 第一个参数为已知类,即flwrActual;第二个参数为预测类,即flwrPreds
MATLAB深度学习入门之旅
文章图片












【MATLAB深度学习入门之旅】

    推荐阅读