• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

matlab版深度学习入门之旅----体验过后的个人记录

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

目录

1. 简介

2. 使用预训练网络:使用已创建和训练后的网络进行分类

2.1 课程示例-识别一些图像中的对象

 

2.1.1  读取图像

2.1.2  显示图像 

2.1.3 存储图像

2.2 进行预测

2.2.1  引用网络

2.2.2  进行分类

2.3 CNN结构

2.3.1  提取网络的层

2.3.2 提取某一层

2.3.3  提取某一层的某个属性

2.3.4  图像维度

2.3.5  提取输出层的类属性

2.4 调查预测

2.4.1  预测分数

2.4.2  创建预测分类的条形图

2.4.3  挑出主要分数

2.4.4  显示挑选预测分数后的条形图

bar(scores(highscores))  % scores(highscores)返回大于0.01的类别的预测分数

2.4.5  为x轴增加类别标签

3 管理数据集:使用已创建和训练后的网络执行分类

3.1 图像数据集

3.1.1  使用imageDatastore创建数据存储(DataStore)

3.1.2  获取文件名

3.1.3  从数据存储(DataStore)中导入某幅图像

3.1.4  预测数据存储(DataStore)中的所有图像

3.2 准备输入图像

3.2.1  查看图像大小

3.2.2  查看网络输入层的输入图像大小

3.2.3  将输入图像调整至要求大小并显示

3.3 在数据存储(DataStore)中处理图像

3.3.1  创建增强图像数据存储(DataStore)

3.3.2  使用增强的图像数据存储(DataStore)进行颜色预处理

3.4 使用子文件夹创建一个数据存储(DataStore)

3.4.1  创建数据存储(Data Store)

3.4.2  分类预测

4 迁移学习:修改预训练网络对图像分类

4.1 什么是迁移学习?

4.2 迁移学习所需的组件

4.3 准备训练数据

4.3.1  标记图像

4.3.2  分割数据以用于训练和测试

4.4 修改网络层

4.4.1  使用fullyConnectedLayer函数创建一个新的全连接层

4.4.2  对层的数组通过索引进行修改

4.4.3  将输出层与前面的层(第23层)进行匹配

4.5 设置训练选项

4.5.1  使用trainingOptions设置训练算法的一些选项(一定要查看帮助手册)

4.5.2  设置初始学习率

4.6 训练网络

4.6.1  mini-batch

4.6.2  使用GPUs

4.6.3  迁移学习示例(脚本)

4.7 评估性能

4.7.1  评估训练和测试性能

4.7.2  调查测试性能

4.8 迁移学习摘要



1. 简介

该课程为MATLAB官网免费课程,此笔记只对该课程进行一定的翻译和记录,方便日后复习。官网链接为https://ww2.mathworks.cn/learn/tutorials/deep-learning-onramp.html(深度学习入门之旅)。
 

2. 使用预训练网络:使用已创建和训练后的网络进行分类


2.1 课程示例-识别一些图像中的对象

 

在本节课程中,您将学习如何使用预先构建的深度神经网络对下面 12 个图像的内容进行分类。理想的分类应为 'beach'、'cat'、'cupcakes'、'lake'、'fish' 等。

在此交互练习中,您会将部分图像文件导入到 MATLAB 中并查看它们。

2.1.1  导入图像

将文件 file01.jpg 中的图像导入 MATLAB 工作区中。将其存储在名为 img1 的变量中。
I = imread('filename.png')

2.1.2  显示导入的图像。


imshow(I)

2.1.3 存储图像

前两项任务将导入并显示 file01.jpg 中的图像。在脚本中添加命令,以导入并显示 file02.jpg 和 file03.jpg 文件中的图像。将图像分别存储在名为 img2 和 img3 的变量中。

img2 = imread('file02.jpg');

imshow(img2)

img3 = imread('file03.jpg');

imshow(img3)

2.2 执行预测


2.2.1  创建预定义的深度网络“AlexNet”的副本

使用 alexnet 函数加载一个预训练网络。将结果保存为一个名为 deepnet 的变量。
deepnet = alexnet  % 这里的网络模型使用Alexnet;可以通过matlab官方下载Alexnet安装包,安装后可用(APP----安装APP)

2.2.2  分类预测

用 classify 函数和预训练的 AlexNet 网络来预测变量 img1 中存储的图像的主题类别。将网络的预测存储在名为 pred1 的变量中。     pred1 = classify(deepnet,img1)
也可用 [pred, score] = classify(net,img)  % 将网络和输入图像传入分类函数,将得到输入图像的类别preds以及它在每一类中的预测分数score

2.2.3 img2和3的分类预测

在脚本中添加命令,对变量 img2 和 img3 中存储的图像的内容进行预测。将预测的类分别存储在名为 pred2 和 pred3 的变量中。

pred2 = classify(deepnet,img2)

pred3 = classify(deepnet,img3)

2.2.4 获取预训练网络

2.3 CNN架构 查看网络层

MATLAB将CNN表示为一个层的数组,数组的第一个元素为输入层,最后一个元素为输出层。

2.3.1  查看网络的层

将 deepnet 的 Layers 属性提取到名为 ly 的变量中。

ly = deepnet.Layers  % 由下图可以看出Alexnet是一个具有25层的数组

2.3.2 索引查看单个层

将网络的第一层(输入层)提取到名为 inlayer 的变量中。

inlayer = ly(1)

2.3.3  提取某一层的某种属性

提取网络第一层的 InputSize 属性(存储在变量 inlayer 中)。将结果存储在名为 insz 的变量中。
insz = inlayer.InputSize  % 输入层的输入图像大小

2.3.4  图像维度


输入图像是彩色图像,尺寸为:227×227×3。灰度图像的尺寸为227×227。

将网络的最后一层(输出层)提取到名为 outlayer 的变量中。

outlayer = ly(end)

2.3.5  提取输出层的类属性

提取网络最后一层的 Classes 属性(存储在变量 outlayer 中)。将结果存储在名为 categorynames 的变量中。
categorynames = outlayer.Classes  % 得到一个列向量,表示Alexnet的1000个类的名字

2.4 研究预测


2.4.1  预测分数

使用 classify 函数和预训练的 AlexNet 网络 net 来预测变量 img 中存储的图像的主题类别。将网络的预测存储在名为 pred 的变量中,并将所有预测分数存储在名为 scores 的变量中。上面的分类函数classify只是将输入图像预测为某一类,并不知道输入图像是该类的概率。该任务不仅会得到预测分类,还会得出预测分数。

前期输入:

img = imread('file01.jpg');

imshow(img)

net = alexnet;

categorynames = net.Layers(end).ClassNames;

分数预测:

[pred,scores] = classify(net,img)   % 得到的分数是一个行向量,表示1000个类的预测分数

2.4.2  创建预测分类的条形图

创建预测分数的条形图。
bar(scores)%因为有 1000 个预测分数,所创建的条形图会难以阅读。

2.4.3  挑出主要分数

创建一个逻辑数组 highscores,其中的值 1 (true) 对应于 scores 大于 0.01 的情况。

highscores = (scores > 0.01)   或者 highscores = scores > 0.01  % 将scrs数组中大于0.01的元素赋为1,其他为0

2.4.4  显示挑选预测分数后的条形图

使用逻辑索引创建高于阈值 0.01 的预测值的条形图。

bar(scores(highscores))   %scores(highscores)返回大于0.01的类别的预测分数

2.4.5  为x轴增加类别标签

使用逻辑索引和 xticklabels 函数为条形图添加对应的预测类名标签。类名的完整列表存储在变量 categorynames 中。
xticklabels(categorynames(highscores)) % categorynames(highscores) 返回大于0.01的类别的名字

3 管理数据集:使用已创建和训练后的网络执行分类


3.1 图像数据存储

ls *.jpg

net = alexnet;

3.1.1  使用imageDatastore创建数据存储(DataStore)

创建一个名为 imds 的数据存储,该数据存储引用当前文件夹中文件名从 file01.jpg 到 file12.jpg 的图像文件。(请注意,在此文件夹中,只有这些图像文件的名称为 filenn.jpg 形式。)

imds = imageDatastore('*.jpg')  % 使用通配符*指定多个文件。

3.1.2  数据存储的属性包含有关数据文件的元信息

使用数据存储 imds 的 Files 属性提取图像的文件名。将结果存储在名为 fname 的变量中。
fname = imds.Files  

3.1.3  从数据存储(DataStore)中导入某幅图像

使用 readimage 函数导入 file07.jpg 中的图像(数据存储中的第 7 个文件)。将导入的图像存储在名为 img 的变量中。

img =  readimage(imds,7)

使用函数: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  预测数据存储(DataStore)中的所有图像

使用 AlexNet(作为变量 net 加载)对数据集中所有图像的内容进行分类。将结果存储在名为 preds 的变量中。
请注意,classify 函数会用 AlexNet 分析 12 个图像。执行可能需要几秒钟。
preds = classify(net, imds)

3.2 准备输入图像

由于不同的网络对输入图像的要求不同,所以需要对输入图像进行预处理后再输入网络。

img = imread('file01.jpg');

imshow(img)

3.2.1  查看图像大小

使用 size 函数查看图像 img 的大小。将结果保存到变量 sz 中。

sz = size(img)  % 返回图像的高度、宽度、通道数

3.2.2  网络的输入层指定网络要求的图像大小

导入 AlexNet。提取网络的第一层的 InputSize 属性。将结果存储在名为 insz 的变量中

net = alexnet

insz = net.Layers(1).InputSize

3.2.3  将输入图像调整至要求大小并显示

使用 imresize 函数将变量 img 中存储的图像的大小调整为 227×227。将结果存储回变量 img 中。
然后用 imshow 显示调整大小后的图像。

img = imresize(img,[227 227])          %【行数(高度),列数(宽度)】

imshow(img)

 

3.3 处理数据存储(DataStore)中的图像


上面是对单个图像进行预处理,但平常的数据集中的图像数量相当之大。因此,直接对整个图像数据集进行处理就显得很有必要了。

ls *.jpg

net = alexnet

3.3.1  创建增强的图像数据存储(DataStore)

(1)创建一个名为 imds 的图像数据存储,该数据存储引用当前文件夹中扩展名为 .jpg 的图像文件。

imds = imageDatastore('*.jpg')

(2)增强的图像数据存储对整个集合图像预处理

从 imds 创建一个增强的图像数据存储,它会将图像大小调整为 227×227。将新数据存储命名为 auds

auds = augmentedImageDatastore([227 227], imds)  % 将数据存储(DataStore)中所有图像的大小统一调整到[227 227]大小 无逗号隔开

(3)增强的图像数据存储对整个集合图像分类

使用 classify 函数和在变量 net 中存储的网络,对 auds 中的图像进行分类。将预测存储在变量 preds 中。

preds = classify(net,auds)

3.3.2  使用增强的图像数据存储(DataStore)进行颜色预处理

ls *.jpg
net = alexnet

imds = imageDatastore('file*.jpg')

(1)使用函数 montage 显示数据存储 imds 中的图像。蒙太奇(montage)

montage(imds)  % 使用蒙太奇手法显示数据存储(DataStore)中的所有图像

(2)创建增强图像数据存储(DataStore)

基于图像数据存储 imds 创建一个增强的图像数据存储。将图像预处理为 227×227×3。
将增强的图像数据存储命名为 auds

auds = augmentedImageDatastore([227 227],imds,'ColorPreprocessing','gray2rgb')

这里做的增强除了调整大小之外,还有灰色图像转换为彩色图像

(3)对预处理后的图像数据存储(DataStore)进行分类

使用 classify 函数对 auds 中的图像进行分类。AlexNet 存储在变量 net 中。将预测存储在变量 preds 中。

preds = classify(net, auds)

注意:图像必须满足网络的图像输入层指定的大小。图像大小正确无误后,您就可以使用预训练网络对数据进行分类!

当您训练网络时,还可以使用其他方法,例如图像增强。查看文档,了解您还可以使用增强的图像数据存储做些什么:
预处理图像以进行深度学习

3.4 用子文件夹创建一个数据存储(DataStore)


将每一类的图像放在一个子文件夹下,图像已经按照这种格式放置,而非按照这种方式去创建。

net = alexnet;

3.4.1  创建数据存储(Data Store)

创建一个数据存储 flwrds,它引用 Flowers 文件夹的子文件夹中的所有图像。

flwrds = imageDatastore('Flowers','IncludeSubfolders',true)     % 'Flowers'为图像数据集的路径,使用“IncludeSubfolders”选项在给定文件夹的子文件夹中查找图像。

3.4.2  分类预测

使用 AlexNet(作为变量 net 加载)对数据集中所有图像的内容进行分类。将结果存储在名为 preds 的变量中。
请注意,classify 函数会用 AlexNet 分析 15 个图像。执行可能需要几秒钟。

preds = classify(net,flwrds)

4 迁移学习:修改预训练网络对图像分类

4.1 什么是迁移学习?

像 AlexNet 这样的预训练网络虽然非常容易上手,但是您不能灵活地控制网络的工作方式,可能无法有效解决您的确切问题。

您可以从网络架构和随机权重开始,自行构建和训练网络。不过,要取得理想的结果需要付出很多努力:(1) 具备网络架构的知识和经验,(2) 拥有大量的训练数据,以及 (3) 耗费大量的计算时间。

通过迁移学习可以有效解决许多问题。其训练需要一些数据和一定的计算时间,但与从头开始训练相比要少得多,而且您可以获得适合解决您具体问题的网络。

4.2 迁移学习所需的组件

4.3 准备训练数据

4.3.1  标记图像

oad pathToImages  % 加载数据集文件pathToImages.mat

flwrds = imageDatastore(pathToImages,'IncludeSubfolders', true);

flowernames = flwrds.Labels

(1)重新创建数据存储 flwrds,其中包含变量 pathToImages 中所存储文件夹路径的子文件夹中的所有图像,这次使用文件夹名称作为图像标签。工作区中已有 pathToImages

flwrds = imageDatastore(pathToImages,'IncludeSubfolders',true,'LabelSource','foldernames')  %训练所需的标签可以存储在图像数据存储库的标签属性中。默认情况下,标签属性为空。通过指定“LabelSource”选项,可以让数据存储自动确定文件夹名称中的标签。如果指定了 'foldernames',将根据文件夹名称分配标签并存储在 Labels 属性中。您以后可以通过直接访问 Labels 属性来修改标签。

(2)将 flwrds 的 Labels 属性提取到名为 flowernames 的变量中。

flowernames = flwrds.Labels

4.3.2  拆分训练和测试

(1)将数据存储 flwrds 拆分为两个数据存储 flwrTrain 和 flwrTest,使每个类别中 60% 的文件划分到 flwrTrain 中。

[flwrTrain,flwrTest] = splitEachLabel(flwrds,0.6)

[ds1,ds2] = splitEachLabel(imds,p)  % flwrds是创建的数据存储,0.6是比例,返回的flwrTrain是imds的p倍,剩下的imds分配给ds2,即ds2是imds的(1-p)倍

(2)随机拆分数据;将数据存储 flwrds 拆分为两个数据存储 flwrTrain 和 flwrTest,使每个类别中随机选择的 80% 的文件在 flwrTrain 中。

[flwrTrain,flwrTest] = splitEachLabel(flwrds,0.8,'randomized')

(3)不平衡的训练数据

在某些应用中,属于一个类的图像数量远超另一类的图像是很常见的。例如,当尝试检测次品时,通常很容易获得许多非次品图像,而很难获得次品图像。

在这种情况下,按类成比例地划分数据将导致网络主要基于非次品图像进行训练。这可能会使训练产生偏差,导致网络“玩概率游戏”,而不是真正学习识别次品特征。

将数据存储 flwrds 拆分为两个数据存储 flwrTrain 和 flwrTest,使每个类别中的 50 个文件在 flwrTrain 中。

[flwrTrain,flwrTest] = splitEachLabel(flwrds,50)

4.4 修改网络层

 

前面提过,前馈网络在 MATLAB 中表示为一个层数组。这便于用户对网络层进行索引和更改。

anet = alexnet;

layers = anet.Layers

4.4.1  使用fullyConnectedLayer函数创建一个新的全连接层

使用 12 个神经元(针对 12 种花)创建一个新的全连接层 fc

fc = fullyConnectedLayer(n)  % n是新建全连接层的神经元个数

4.4.2  对层的数组通过索引进行修改

用您刚刚创建的新层 fc 替换数组 layers 表示的网络的最后一个全连接层(第 23 个层)。
layers(23) = fc  % 将Alexnet的第23层修改为上述新建的全连接层

4.4.3  将输出层与前面的层(第23层)进行匹配

将输出层与先前的层进行匹配。。。当前,输出层仍然使用 AlexNet 网络的 1000 个类标签。当信息从您刚创建的新(12 类)全连接层传递到该层时,会出现问题。要解决此问题,您需要用新的空白输出层替换输出层。网络会在训练期间根据训练数据标签来确定这 12 个类。

用新的分类层替换数组 layers 表示的网络的最后一层(输出层)。

layers(end) = classificationLayer  % 使用classificationLayer函数新建一个分类层,并赋给最后一层(输出层),该函数将自动确定输出层的神经元个数

4.5 设置训练选项


4.5.1  使用trainingOptions来查看所选训练算法的可用选项(一定要查看帮助手册)

创建一个包含 SGDM 优化器的默认训练算法的变量 opts。可以省略行尾的分号以显示结果。

opts = trainingOptions('sgdm')
解释: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')

'Plots'设置为'training-progress'时有下图

4.5.2  设置初始学习率

通常,您首先会尝试使用大多数选项的默认值来进行训练。但是,在执行迁移学习时,您通常希望将 InitialLearnRate 设置为一个比其默认值 0.01 小的值。

opts = trainingOptions('sgdm','InitialLearnRate',0.001)

解释:opts = trainingOptions('sgdm','Name', value)  % 指定训练选项的名称'Name'和值value(相当于字典的键值对)

4.6 训练网络

4.6.1  mini-batch小批量

在每次迭代中,网络都会使用训练图像的一个子集来更新权重,这个子集称为小批量。每次迭代都采用不同的小批量。如果整个训练集都被使用过了,则称为完成了一轮,这样的一个周期称为epoch。训练多少个周期可以通过设置'MaxEpochs'来实现。

您可以在训练算法选项中设置的参数是最大轮数 (MaxEpochs) 和小批量的大小 (MiniBatchSize)。

请注意,训练期间报告的损失和准确度针对的是当前迭代中使用的小批量数据。

默认情况下,图像在分成小批量之前会进行一次乱序处理。您可以使用 Shuffle 选项来控制此行为。

值得注意的是,损失和准确率是针对当前的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  评估训练和测试性能


(1)画出训练损失(位于info的TrainingLoss中)

load pathToImages

load trainedFlowerNetwork flowernet info

plot(info.TrainingLoss)

(2)分类图像

dsflowers =imageDatastore(pathToImages,'IncludeSubfolders',true,'LabelSource', 'foldernames');

[trainImgs,testImgs] = splitEachLabel(dsflowers,0.98);

flwrPreds = classify(flowernet,testImgs)

4.7.2  调查测试性能


(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是对数据存储进行划分得到的,所以它们具有数据存储的相关属性

(2)计算正确个数

numCorrect = nnz(flwrActual == flwrPreds)  % nnz函数返回的是矩阵非零元素的数目,flwrActual == flwrPreds将得到一个0-1矩阵

(3)计算正确率

fracCorrect = numCorrect/numel(flwrPreds)  % 就是正确个数除以测试数据的个数

上面的计算有些麻烦,先改写为:

mean(flwrActual == flwrPreds)

(4)显示预测分类的混淆矩阵

混淆矩阵又称误差矩阵,矩阵中的元素(j,k)表示第j个类被预测为第k个类的数目,主对角线的元素表示正确预测,其余元素表示误分类。

confusionchart(knownclass,predictedclass)  % 第一个参数为已知类,即flwrActual;第二个参数为预测类,即flwrPreds

4.8 迁移学习摘要

迁移学习函数摘要

创建网络

函数 说明
alexnet 加载预训练网络“AlexNet”
支持的网络 查看可用的预训练网络列表
fullyConnectedLayer 创建新的全连接网络层
classificationLayer 为分类网络创建新输出层

 

获取训练图像

函数 说明
imageDatastore 创建引用图像文件的数据存储
augmentedImageDatastore 预处理图像文件集合
splitEachLabel 将数据存储划分为多个数据存储

 

设置训练算法选项

函数 说明
trainingOptions 创建包含训练算法选项的变量

 

执行训练

函数 说明
trainNetwork 执行训练

 

使用经过训练的网络执行分类

函数 说明
classify 获取经过训练的网络对输入图像的分类

 

评估经过训练的网络

函数 说明
nnz 统计数组中的非零元素
confusionchart 计算混淆矩阵
heatmap 将混淆矩阵可视化为热图

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap