写在前面
俗话说的好,没有什么是MATLAB干不了的,今天笔者就将给大家带来一个使用MATLAB实现迁移学习的实例
数据集选取及简介
考虑到Alexnet输入的色彩通道为3,因此笔者未使用数据集为灰度图的数据集,如MNIST,转而使用的是本身就就为RGB图像的CIFAR-10,下载地址在此处。
CIFAR-10 数据集由 10 个类别的 60000 张 32x32 彩色图像组成,每类 6000 张图像。有 50000 张训练图像和 10000 张测试图像。数据集分为五个训练批次和一个测试批次,每个批次有 10000 张图像。
数据集处理
下载数据集
这里采用了从数据集官网下载数据集的方式,有如下:
%% 下载 CIFAR-10
if ~exist('cifar-10-batches-mat','dir')
cifar10Dataset = 'cifar-10-matlab';
disp('Downloading 174MB CIFAR-10 dataset...');
websave([cifar10Dataset,'.tar.gz'],...
['https://www.cs.toronto.edu/~kriz/',cifar10Dataset,'.tar.gz']);
gunzip([cifar10Dataset,'.tar.gz'])
delete([cifar10Dataset,'.tar.gz'])
untar([cifar10Dataset,'.tar'])
delete([cifar10Dataset,'.tar'])
end
下载后的数据集格式为:
针对每一个mat文件格式有:
其中3072 = 32 _ 32 _ 3,表示图像高长均为32,3个色彩通道,10000个数据
数据集整齐化
由于下载的数据集是.mat
格式,我们需要将其变为整齐的图像格式(jpg
)文件夹,有如下代码:
%% 准备 CIFAR-10
if ~exist('cifar10Train','dir')
disp('Saving the Images in folders. This might take some time...');
saveCIFAR10AsFolderOfImages('cifar-10-batches-mat', pwd, true);
end
其中saveCIFAR10AsFolderOfImages
为自己设计的函数,其中包含了另外自己编写的子函数,有如下代码,功能见代码注释:
function saveCIFAR10AsFolderOfImages(inputPath, outputPath, varargin)
% 将 CIFAR-10 数据集转化为图片格式的文件夹
% saveCIFAR10AsFolderOfImages(inputPath, outputPath) 采用CIFAR-10
% 位于 inputPath 的数据集并将其作为图像文件夹保存到
% 目录输出路径。如果 inputPath 或 outputPath 为空字符串,则
% 假定应使用当前文件夹。
% 将保存CIFAR-10 数据,以便将具有相同标签的实例保存到
% 带有该标签名称的子目录。
% 输入路径是否有效
if(~isempty(inputPath))
assert(exist(inputPath,'dir') == 7);
end
if(~isempty(outputPath))
assert(exist(outputPath,'dir') == 7);
end
% 检查我们是否要将具有相同标签的每个集合保存到自己的集合中
if(isempty(varargin))
labelDirectories = false;
else
assert(nargin == 3);
labelDirectories = varargin{1};
end
% 设置目录名称
trainDirectoryName = 'cifar10Train';
testDirectoryName = 'cifar10Test';
% 创建文件夹用于存放图片
mkdir(fullfile(outputPath, trainDirectoryName));
mkdir(fullfile(outputPath, testDirectoryName));
if(labelDirectories)
labelNames = {'airplane','automobile','bird','cat','deer','dog','frog','horse','ship','truck'};
iMakeTheseDirectories(fullfile(outputPath, trainDirectoryName), labelNames);
iMakeTheseDirectories(fullfile(outputPath, testDirectoryName), labelNames);
for i = 1:5
iLoadBatchAndWriteAsImagesToLabelFolders(fullfile(inputPath,['data_batch_' num2str(i) '.mat']), fullfile(outputPath, trainDirectoryName), labelNames, (i-1)*10000);
end
iLoadBatchAndWriteAsImagesToLabelFolders(fullfile(inputPath,'test_batch.mat'), fullfile(outputPath, testDirectoryName), labelNames, 0);
else
for i = 1:5
iLoadBatchAndWriteAsImages(fullfile(inputPath,['data_batch_' num2str(i) '.mat']), fullfile(outputPath, trainDirectoryName), (i-1)*10000);
end
iLoadBatchAndWriteAsImages(fullfile(inputPath,'test_batch.mat'), fullfile(outputPath, testDirectoryName), 0);
end
end
function iMakeTheseDirectories(outputPath, directoryNames)
for i = 1:numel(directoryNames)
mkdir(fullfile(outputPath, directoryNames{i}));
end
end
function iLoadBatchAndWriteAsImagesToLabelFolders(fullInputBatchPath, fullOutputDirectoryPath, labelNames, nameIndexOffset)
load(fullInputBatchPath);
data = data'; %#ok<NODEF>
data = reshape(data, 32,32,3,[]);
data = permute(data, [2 1 3 4]);
for i = 1:size(data,4)
imwrite(data(:,:,:,i), fullfile(fullOutputDirectoryPath, labelNames{labels(i)+1}, ['image' num2str(i + nameIndexOffset) '.png']));
end
end
function iLoadBatchAndWriteAsImages(fullInputBatchPath, fullOutputDirectoryPath, nameIndexOffset)
load(fullInputBatchPath);
data = data'; %#ok<NODEF>
data = reshape(data, 32,32,3,[]);
data = permute(data, [2 1 3 4]);
for i = 1:size(data,4)
imwrite(data(:,:,:,i), fullfile(fullOutputDirectoryPath, ['image' num2str(i + nameIndexOffset) '.png']));
end
end
function iLoadBatchAndWriteAsImages(fullInputBatchPath, fullOutputDirectoryPath, nameIndexOffset)
load(fullInputBatchPath);
data = data'; %#ok<NODEF>
data = reshape(data, 32,32,3,[]);
data = permute(data, [2 1 3 4]);
for i = 1:size(data,4)
imwrite(data(:,:,:,i), fullfile(fullOutputDirectoryPath, ['image' num2str(i + nameIndexOffset) '.png']));
end
end
数据集预览
处理后的数据集有如下显示:
利用代码随机选取20个图片其中代码见下图:
figure; %打开figure界面
perm = randperm(100, 20); %从1-100内任选20个数
for i = 1:20
subplot(4, 5, i); %将figure界面分割为4*5个小格,并选中第i个小格
imshow(image.Files{perm(i)}); %在第i个小格上显示标号为i的图片
end
显示效果有如下图所示:
加载数据集
其中数据集的最终处理包括:
1.将尺寸为32X32X3的图像,转化为227X227X3的能被Alexnet处理的图像
2.进行数据增强
3.加载这些图像作为图像数据存储,转化为imageDatestore
格式的图像格式
4.划分训练集与测试集
ImageDatastore图像格式简介
imageDatastore
根据文件夹名称自动标注图像,并将数据存储为 ImageDatastore
对象。通过图像数据存储可以存储大图像数据,包括无法放入内存的数据,并在卷积神经网络的训练过程中高效分批读取图像,这里跟pytorch
中的torchvision.datasets.ImageFolder
功能比较相似
转化格式
matlab为我们提供了函数用来将文件夹内的图片自动标注,并转化为imagedatastore
格式,有如下代码:
image = imageDatastore('cifar10','IncludeSubfolders',true,'LabelSource','foldernames');
参数说明
1.cifar10
:数据集所在文件夹路径
2.IncludeSubfolders
:子文件夹包含标记,指定 true
可包含每个文件夹中的所有文件和子文件夹,默认为false
3.LabelSource
:提供标签数据的源,指定了 'foldernames'
,将根据文件夹名称分配标签并存储在 Labels
属性中
划分数据集
利用matlab现有函数,splitEachLabel
将 images
数据存储拆分为两个新的数据存储,程序中划分训练集:训练集 = 3:1
[imageTrain,imageTest] = splitEachLabel(image,0.75,'randomized');
转换格式与数据增强
利用augmentedImageDatastore
函数,转换图像大小,并且进行数据增强,有如下代码:
imageTrain = augmentedImageDatastore([227 227 3], imageTrain);
imageTest = augmentedImageDatastore([227 227 3], imageTest);
Alexnet迁移学习
加载预训练网络
首先需要安装 _Deep Learning Toolbox Model for AlexNet Network_,加载预训练网络
net = alexnet;
替换最终层(全连接层)
由于已加载的预训练网络 net
的最后三层是针对 1000 个类进行配置,而对于本实验是需要进行5个类的分类,所以需要调整这三个层
首先从预训练网络中提取除最后三层之外的所有层:
layersTransfer = net.Layers(1:end-3);
接着将最后三层替换为全连接层、softmax 层和分类输出层,将层迁移到新分类任务
同时我们需要根据新数据指定新的全连接层的选项。将全连接层设置为大小与新数据中的类数相同,即为5
同时要使新层中的学习速度快于迁移的层,增大全连接层的 WeightLearnRateFactor
和 BiasLearnRateFactor
layers = net.Layers(1:end-3);
new_layers = [layers
fullyConnectedLayer(5,'WeightLearnRateFactor',20,'BiasLearnRateFactor',20)
softmaxLayer
classificationLayer];
通过analyzeNetwork
以交互可视方式呈现网络变化前后架构以及有关网络层的详细信息:
训练
对于迁移学习,保留预训练网络的较浅层中的特征(迁移的层权重)
同时要减慢迁移的层中的学习速度,将初始学习速率设置为较小的值。在上一步骤中,我们增大了全连接层的学习率因子,以加快新的最终层中的学习速度
这种学习率设置组合只会加快新层中的学习速度,对于其他层则会减慢学习速度。执行迁移学习时,所需的训练轮数相对较少
一轮训练是对整个训练数据集的一个完整训练周期,可以发现准确率随着epoch
的次数的增加而明显上升
指定小批量大小和验证数据。软件在训练过程中每 ValidationFrequency
次迭代验证一次网络
ops = trainingOptions('sgdm', ...
'InitialLearnRate',0.0001, ...
'ValidationData',imageTest, ...
'Plots','training-progress', ...
'MiniBatchSize',5, ...
'MaxEpochs',12,...
'ValidationPatience',Inf,...
'Verbose',false);
%开始训练
tic
net_train = trainNetwork(imageTrain,new_layers,ops);
toc
如下是可视化界面,准确率达到了70%以上:
验证
选取bird
和automobile
类别各一张进行验证实验:
可以发现效果良好
写在最后
在本博客中,笔者使用MATLAB实现了alexnet在CIFAR-10数据集的迁移学习,可以看出,MATLAB有关神经网络的高级API也是比较简洁和清晰的
评论(0)
您还未登录,请登录后发表或查看评论