在计算机视觉领域,图像分类是最基础也最重要的任务之一。作为一名长期从事机器学习开发的工程师,我发现很多初学者在学习卷积神经网络(CNN)时,往往会被各种框架和复杂的理论吓退。实际上,使用Matlab这个强大的数学计算平台,我们可以用相对简单的代码实现一个完整的CNN图像分类项目。
这次我们要处理的是经典的"猫狗大战"数据集,包含4000张图像(2000张猫和2000张狗)。这个项目特别适合想要入门深度学习的朋友,因为它:
提示:虽然这个项目的网络结构比较简单,数据量也不大,但它的价值在于提供了一个清晰的学习模板。在实际应用中,你可以基于这个框架进行各种改进和优化。
猫狗大战数据集是一个经典的二分类数据集,包含猫和狗两类图像。在Matlab中,我们可以使用imageDatastore来高效地加载和管理这些图像数据。
matlab复制% 设置数据集路径
imageDir = 'path_to_cat_dog_dataset';
% 创建图像数据存储
imds = imageDatastore(imageDir, ...
'IncludeSubfolders', true, ...
'LabelSource', 'foldernames');
这里有几个关键点需要注意:
IncludeSubfolders设为true表示会包含子文件夹中的图像LabelSource设为'foldernames'表示使用文件夹名作为类别标签我们将数据集划分为三部分:
matlab复制% 获取图像总数
numImages = numel(imds.Files);
% 生成随机排列索引
idx = randperm(numImages);
% 划分索引
trainIdx = idx(1:round(numImages*0.7));
valIdx = idx(round(numImages*0.7)+1:round(numImages*0.8));
testIdx = idx(round(numImages*0.8)+1:end);
% 创建子数据集
trainDS = subset(imds, trainIdx);
valDS = subset(imds, valIdx);
testDS = subset(imds, testIdx);
注意:随机打乱数据非常重要,可以避免数据顺序带来的偏差。在划分前一定要先打乱顺序。
我们的GPU版本采用三层卷积结构,每层都包含:
matlab复制layers = [
% 输入层 - 假设图像已调整为224x224x3
imageInputLayer([224 224 3])
% 第一卷积块
convolution2dLayer(3, 16, 'Padding', 'same')
batchNormalizationLayer
reluLayer
maxPooling2dLayer(2, 'Stride', 2)
% 第二卷积块
convolution2dLayer(3, 32, 'Padding', 'same')
batchNormalizationLayer
reluLayer
maxPooling2dLayer(2, 'Stride', 2)
% 第三卷积块
convolution2dLayer(3, 64, 'Padding', 'same')
batchNormalizationLayer
reluLayer
maxPooling2dLayer(2, 'Stride', 2)
% 分类头
fullyConnectedLayer(2) % 二分类输出
softmaxLayer
classificationLayer];
网络设计要点解析:
考虑到CPU计算资源有限,我们对网络做了以下简化:
matlab复制smallLayers = [
imageInputLayer([224 224 3])
% 第一卷积块
convolution2dLayer(3, 16, 'Padding', 'same')
batchNormalizationLayer
reluLayer
maxPooling2dLayer(2, 'Stride', 2)
% 第二卷积块
convolution2dLayer(3, 32, 'Padding', 'same')
batchNormalizationLayer
reluLayer
maxPooling2dLayer(2, 'Stride', 2)
% 分类头
fullyConnectedLayer(2)
softmaxLayer
classificationLayer];
matlab复制options = trainingOptions('adam', ...
'MaxEpochs', 10, ...
'InitialLearnRate', 0.001, ...
'ValidationData', valDS, ...
'ValidationFrequency', 30, ...
'Verbose', false, ...
'Plots', 'training-progress', ...
'ExecutionEnvironment', 'auto');
关键参数说明:
matlab复制smallOptions = trainingOptions('adam', ...
'MaxEpochs', 10, ...
'InitialLearnRate', 0.001, ...
'Verbose', false, ...
'Plots', 'training-progress', ...
'ExecutionEnvironment', 'cpu');
主要区别:
GPU版本训练:
matlab复制net = trainNetwork(trainDS, layers, options);
CPU版本训练:
matlab复制smallNet = trainNetwork(smallTrainDS, smallLayers, smallOptions);
训练过程中,Matlab会显示一个训练进度窗口,包含以下重要信息:
损失不下降:
过拟合:
训练速度慢:
GPU版本评估代码:
matlab复制% 预测测试集
YPred = classify(net, testDS);
YTest = testDS.Labels;
% 计算准确率
accuracy = sum(YPred == YTest)/numel(YTest);
fprintf('测试准确率: %.2f%%\n', accuracy*100);
% 混淆矩阵
confMat = confusionmat(YTest, YPred);
figure;
confusionchart(confMat, {'Cat', 'Dog'});
title('分类混淆矩阵');
准确率解读:
混淆矩阵分析:
改进方向:
扩展到其他数据集:
性能优化技巧:
部署注意事项:
saveNetwork保存训练好的模型我在实际项目中总结的几个经验: