Kaggle猫狗数据集猫与狗用于训练的图片(train)分别12500张,每张图片的尺寸大小都是有差异的,图片的命名格式为标签+标号。
【数据集度云链接】
链接:https://pan.baidu.com/s/17c4K04kDKDUsuXdLkPecKA
提取码:8rhn
在这里,将两种图片分别放在两个文件夹下,文件夹用标签命名。这样做主要是便于使用Matlab自身构建数据集的函数。(下文中将标注)
直接在命令窗口输入下列命令,若没有该网络结构,软件会报错并提示下载。下载方法不在这里赘述。
net = alexnet;
imds = imageDatastore('E:\kaggle\train', ...
'IncludeSubfolders',true, ...
'LabelSource','foldernames');
imds = imageDatastore(location,Name,Value)
location 数据集位置(文件夹地址)
IncludeSubfolders 子文件夹包含标记(使用前文中提到的文件夹分类并命名)true为指定,false为不指定,默认不指定
FileExtensions 图像文件扩展名,指定读取某一类型的图片文件,这里不指定
在这里使用IncludeSubfolders标定图片的标签可以省去很多不必要的步骤。但不是很适合训练集打乱的情况。
numTrainImages = numel(imds.Labels);
这一行代码实质是打印数据集中所有的标签,再统计标签总数以达到统计训练集图片总数。
AlexNet默认输入图片尺寸为227×227×3,其中3指的是彩色图片的三通道。所以我们需要把数据集中的图片统一比例与像素大小。
for i = 1:numTrainImages
s = string(imds.Files(i));
I = imread(s);
I = imresize(I,[227,227]);
imwrite(I,s);
s
end
这个循环函数,imds.Files的作用是读取数据集中所有图片的地址,然后逐一读取改尺寸。
在这里有两种方式生成训练数据集与测试数据集:
1.按比例分割数据集
2.使用官方测试数据集
[imdsTrain,imdsValidation] = splitEachLabel(imds,0.7,'randomized');
这行代码主要功能是将原数据集imds按7:3分割为训练数据集imdsTrain与测试数据集imdsValidation,分割挑去方式为随机。
imdsTrain = imds
imdsValidation = imageDatastore('E:\kaggle\test', ...
'IncludeSubfolders',true, ...
'LabelSource','foldernames');
读取方法与第一步的方法相同。
在这里使用第一种方法
net = alexnet;
inputSize = net.Layers(1).InputSize
layersTransfer = net.Layers(1:end-3);
numClasses = numel(categories(imdsTrain.Labels));
inputSize 读取该网络输入图片的尺寸
layersTransfer 获取AlexNet后三层之外的网络,保持不变
numClasses 获取以确定的数据集标签数(即分类数量,猫狗分类数量为2)
layers = [
layersTransfer
fullyConnectedLayer(numClasses,'WeightLearnRateFactor',20,'BiasLearnRateFactor',20)
softmaxLayer
classificationLayer];
这里主要是更改最后全连接层。
指定训练选项。对于迁移学习,请保留预训练网络的较浅层中的特征(迁移的层权重)。要减慢迁移的层中的学习速度,请将初始学习速率设置为较小的值。在上一步中增大了全连接层的学习率因子,以加快新的最终层中的学习速度。这种学习率设置组合只会加快新层中的学习速度,对于其他层则会减慢学习速度。执行迁移学习时,所需的训练轮数相对较少。一轮训练是对整个训练数据集的一个完整训练周期。指定小批量大小和验证数据。软件在训练过程中每 ValidationFrequency 次迭代验证一次网络。
options = trainingOptions('sgdm', ...
'MiniBatchSize',10, ...
'MaxEpochs',6, ...
'InitialLearnRate',1e-4, ...
'Shuffle','every-epoch', ...
'ValidationData',augimdsValidation, ...
'ValidationFrequency',3, ...
'Verbose',false, ...
'Plots','training-progress');
训练网络
netTransfer = trainNetwork(augimdsTrain,layers,options);
其实由于AlexNet本身的结构问题,Accuracy基本上也就是在92%上下波动,再加上迁移学习可以节省很多时间,所以其实可以使用很少的数据集,100张左右都是差不了太多的。(训练25000张其实最终结果没太大差别)
idx = randperm(numel(imdsValidation.Files),20);
在上文中提到的测试数据集中随机抽取20张作为本次测试的数据集idx。
figure
for i = 1:20
subplot(5,4,i)
I = readimage(imdsValidation,idx(i));
imshow(I)
label = YPred(idx(i));
title(string(label));
end
逐一测试并展示出来
肉眼检测一下,发现左下角的小黑狗被错误识别成猫了。但是整体结果还算可以。
总的来说,通过AlexNet迁移学习猫狗分类是相当简单的。只需要改少许代码,就可以实现其他的多分类任务。
这里只是核心代码,做一下GUI便是可以作为某一期末课程设计了。在这里附上简单的GUI界面:
imds = imageDatastore('E:\kaggle\train', ...
'IncludeSubfolders',true, ...
'LabelSource','foldernames');
numTrainImages = numel(imds.Labels);
for i = 1:numTrainImages
s = string(imds.Files(i));
I = imread(s);
I = imresize(I,[227,227]);
imwrite(I,s);
s
end
[imdsTrain,imdsValidation] = splitEachLabel(imds,0.7,'randomized');
net = alexnet;
inputSize = net.Layers(1).InputSize
layersTransfer = net.Layers(1:end-3);
numClasses = numel(categories(imdsTrain.Labels));
layers = [
layersTransfer
fullyConnectedLayer(numClasses,'WeightLearnRateFactor',20,'BiasLearnRateFactor',20)
softmaxLayer
classificationLayer];
augimdsValidation = augmentedImageDatastore(inputSize(1:2),imdsValidation);
options = trainingOptions('sgdm', ...
'MiniBatchSize',10, ...
'MaxEpochs',10, ...
'InitialLearnRate',1e-4, ...
'Shuffle','every-epoch', ...
'ValidationData',augimdsValidation, ...
'ValidationFrequency',3, ...
'Verbose',false, ...
'Plots','training-progress');
netTransfer = trainNetwork(augimdsTrain,layers,options);