主要内容

基于小波散射和深度学习的寄生虫分类

该实例展示了如何利用小波图像散射和深度学习对Giemsa染色图像中的寄生虫感染进行分类。该数据集对深度网络具有挑战性,因为它只包含48张图像。这些图像被平均分为三类寄生虫感染:巴贝虫病、疟原虫-配子体细胞病和锥虫病。

数据

从MATLAB®文件交换中获取数据:将深度神经网络部署到嵌入式图形处理器然后解压缩文件。该文件位于与本示例相同的文件夹中。

url =“//www.tatmou.com/matlabcentral/mlc-downloads/downloads/”+...“5918495 - 0009 - 419 - e - 8 - e10 - 77 b06e3fe553/844e43fa网- 7 - 4 - f88 a435 f0afe04fc3a3 /”+...“包/ zip”;websave (“classifyBloodSmearImages.zip”url);解压缩(“classifyBloodSmearImages.zip”

创建一个ImageDatastore来管理吉姆萨染色图像的访问。这些图像采用RGB格式,一般大小为300 × 300 × 3。

Imagedir = fullfile(“classifyBloodSmearImages”“BloodSmearImages”);Imds = imageDatastore(imagedir,“IncludeSubFolders”,真的,“FileExtensions”...“jpg”“LabelSource”“foldernames”);总结(Imds.Labels)
巴贝西虫病16疟原虫-配子体细胞16锥虫病16

三种寄生虫类型各有16张图片。将数据分成训练集和保留测试集,70%的图像在训练集中,30%在测试集中。为重现性设置随机数生成器。

rng默认的[trainImds,testImds] = splitEachLabel(Imds,0.7);

验证每个寄生虫类在训练集和测试集中所包含的数量相等。

总结(trainImds.Labels)
巴贝西虫病11疟原虫配子体病11锥虫病11
对测试集执行相同的操作。总结(testImds.Labels)
5巴贝西虫病5疟原虫-配子体细胞病5锥虫病

因为这是一个小数据集,所以整个训练集和测试集都适合内存。读取这两组的所有图像。

trainImages = readall(trainImds);testImages = readall(testImds);

从训练数据中绘制一些样本图像。

Idx = randperm(33,6);数字ii = 1:长度(idx) im = trainImages{idx(ii)};subplot(3,2,ii) imshow(im,[]) title(string(trainImds.Labels(idx(ii))));结束

小波散射网络

在本例中,您使用小波散射变换作为机器学习方法的特征提取器。小波散射变换有助于降低数据的维数,增加类间的不相似性。构造一个40 × 40像素不变尺度的两层图像散射网络。在第一层中每八度使用两个小波,在第二层中每八度使用一个小波。每层使用两次小波旋转。

sn =小波散射2(“图象尺寸”(300 300),“InvarianceScale”现年40岁的...“QualityFactors”(2 - 1),“NumRotations”(2 - 2));[~,npaths] = paths(sn);总和(npaths)
Ans = 27
coefficientSize (sn)
ans =1×238 38

指定的小波散射网络有27条路径。每个散射路径上的图像被缩减为38 × 38 × 3。即使没有进一步平均散射系数,每个图像的内存大小也减少了2倍以上。然而,为了分类,我们形成了一个特征向量,在空间和通道维度上平均散射系数。这导致特征向量只有27个元素,每个散射路径都有一个实值标量。这表示每张图像的元素数量减少了10,000倍。

下面的代码计算训练集和测试集的小波散射特征向量。把特征向量连接起来,这样你就有了N-by-27矩阵,其中N是训练集或测试集中的示例数,每一行是一个示例的小波散射特征向量。

trainfeatures = cellfun(@(x)helperScatImages_mean(sn,x),trainImages,“大学”, 0);testfeatures = cellfun(@(x)helperScatImages_mean(sn,x),testImages,“大学”, 0);Trainfeatures = cat(1, Trainfeatures {:});Testfeatures = cat(1, Testfeatures {:});

支持向量机分类

使用带有散射特征的支持向量机分类器。选择一个三次多项式核。使用一个对所有的编码方案。

template = templateSVM(...“KernelFunction”多项式的...“PolynomialOrder”3,...“KernelScale”, 1...“BoxConstraint”, 314,...“标准化”,真正的);classificationSVM = fitcecoc(训练特征,训练imds。标签,...“学习者”模板,“编码”“onevsall”);

使用5倍交叉验证来估计训练集上的准确性。

kfoldmodel = crossval(classificationSVM,“KFold”5);损失= kfoldLoss(kfoldmodel)*100;crossvalAccuracy = 100-loss
crossvalAccuracy =81.8182

交叉验证的准确率约为80%。现在检查保留测试集的准确性,并绘制混淆图。

[predLabels,scores] = predict(classificationSVM,testfeatures);testAccuracy =...总和(分类(predLabels) = = testImds.Labels) /元素个数(testImds.Labels) * 100
testAccuracy = 80
figure cchart = confusionchart(testImds.Labels,predLabels);cchart。Title =...“小波混淆图”“使用支持向量机的散射特征”};cchart。RowSummary =“row-normalized”;cchart。ColumnSummary =“column-normalized”

支持向量机模型的总体测试精度为80%。每个类的召回率为80%。这种精确度对疟原虫-配子体细胞和锥虫病寄生虫也有好处,但对巴贝西虫病更差。检查每个班级的F1分数。

f1SVM = f1score(cchart.NormalizedValues);disp (f1SVM)
F1 _______巴贝虫病0.72727疟原虫-配子体细胞0.88889锥虫病0.8

所有F1分数都在0.7到0.9之间。

具有散射特征的PCA分类器

金宝app支持向量机是用于不可线性可分特征的强大技术,但它们是为二元分类而设计的,对于多类问题可能不是最优的。这里通过使用具有相同小波散射特征的简单PCA(线性)分类器来补充SVM分析。的helperPCAModel函数决定了numcomp训练集中各病原体小波散射特征协方差矩阵最大特征值对应的特征向量与类均值。

helperPCAClassifier对每个测试样本进行分类。它通过从测试数据集中的每个小波散射特征向量中减去模型类均值,并将中心特征向量投影到模型中每个类的协方差矩阵特征向量上来实现这一点。helperPCAClassifier将每个测试示例分配给误差或残差最小的病原体。这是一个主成分分析(PCA)分类器。

从每个特征向量中去除0阶散射特征。设置主成分(特征向量)个数为6。

Numcomp = 6;model = helppcamodel (trainfeatures(:,2:end)',numcomp,trainImds.Labels);PCALabels = helperPCAClassifier(testfeatures(:,2:end)',model);testPCAacc = sum(PCALabels==testImds.Labels)/numel(testImds.Labels)*100
testPCAacc = 86.6667

使用PCA分类器的测试准确率约为87%。绘制困惑图,计算每个班级的F1分数。

figure cchart = confusionchart(testImds.Labels,PCALabels);cchart。Title ={小波散射特征的混淆图...“使用PCA分类器”};cchart。RowSummary =“row-normalized”;cchart。ColumnSummary =“column-normalized”

f1PCA = f1score(cchart.NormalizedValues);disp (f1PCA)
F1 _______巴贝虫病0.90909疟原虫-配子体细胞0.88889锥虫病0.8

带有小波散射特征的PCA分类器F1得分相当强,得分都在0.8到1之间。

卷积深度网络

在本节中,您将尝试使用深度卷积网络进行相同的分类。深度网络为大型数据集的分类问题提供了最先进的结果,并能够学习复杂的非线性映射,但在小型数据集上,它们的性能通常会受到影响。为了缓解这个问题,可以使用图像增强器。imageDataAugmenter扰动每个时代的数据,实际上是创建新的训练示例。

augmenter = imageDataAugmenter(“RandRotation”180年[0],“RandXTranslation”, [-5 5],...“RandYTranslation”5 [5]);augimds = augmentedImageDatastore([300 300 3],trainImds,“DataAugmentation”、增压器);

定义一个小的CNN,由两个卷积层组成,然后是批处理归一化层和RELU激活。在最后的RELU激活之后,使用最大池化、全连接和softmax层。

layers = [imageInputLayer([300 300 3]) convolution2dLayer(7,16) batchNormalizationLayer reluLayer convolution2dLayer(3,20) batchNormalizationLayer reluLayer maxPooling2dLayer(4) fullyConnectedLayer(3) softmaxLayer classificationLayer];

使用10个小批量的随机梯度下降。对每个纪元的数据进行洗牌。运行100个epoch的训练。

opts = trainingOptions(“个”...“InitialLearnRate”, 0.0001,...“MaxEpochs”, 100,...“MiniBatchSize”10...“洗牌”“every-epoch”...“阴谋”“训练进步”...“详细”假的,...“ExecutionEnvironment”“cpu”);

培训网络。

trainedNet = trainNetwork(augimds,layers,opts);

在保留测试集上检查网络的性能。

ypred = trainednet . category (testImds);cnnAccuracy = sum(ypred == testImds.Labels)/ nummel (testImds.Labels)*100
cnnAccuracy = 66.6667
figure cchart = confusionchart(testImds.Labels,ypred);cchart。Title =“CNN深度困惑表”;cchart。RowSummary =“row-normalized”;cchart。ColumnSummary =“column-normalized”

f1CNN = f1score(cchart.NormalizedValues);disp (f1CNN)
F1 _______巴贝虫病0.75疟原虫-配子体0.76923锥虫病0.44444

尽管使用了增强数据集进行训练,但CNN对训练集存在过拟合,F1得分明显低于具有小波散射特征的SVM或PCA模型。

接下来,使用SqueezeNet进行迁移学习。修改最后的卷积层,以适应有三类病原体的事实。构造SqueezeNet是为了识别1000个类。

网=挤压网;lgraphSQZ = layerGraph(net);numClasses = numel(categories(trainImds.Labels));oldFinalConv = lgraphSQZ.Layers(end-4);newFinalConv = convolution2dLayer(1,numClasses,...“名字”“new_conv”);setLearnRateFactor (newFinalConv“重量”10);setLearnRateFactor (newFinalConv“偏见”, 10)
ans = Convolution2DLayer with properties: Name: 'new_conv'超参数FilterSize: [1 1] NumChannels: 'auto' NumFilters: 3 Stride: [1 1] DilationFactor: [1 1] PaddingMode: 'manual' PaddingSize: [0 0 0 0 0] PaddingValue: 0 Learnable Parameters Weights: [] Bias:[]显示所有属性
lgraphSQZ = replaceLayer(lgraphSQZ, oldfinalcon . name,newFinalConv);oldClassLayer = lgraphSQZ.Layers(结束);newClassLayer = classificationLayer(“名字”“new_classoutput”);lgraphSQZ = replaceLayer(lgraphSQZ,oldClassLayer.Name,newClassLayer);

重置训练和测试数据存储。修改数据存储读取功能,以调整图像的大小,使其与SqueezeNet兼容,它期望227 × 227 × 3的图像。设置图像增强器并训练网络。

重置(trainImds);重置(testImds);trainImds。ReadFcn = @ imresize(imread(x),“OutputSize”227年[227]);testImds。ReadFcn = @ imresize(imread(x),“OutputSize”227年[227]);augmenter = imageDataAugmenter(“RandRotation”180年[0],“RandXTranslation”, [-5 5],...“RandYTranslation”5 [5]);augimds = augmentedImageDatastore([227 227 3],trainImds,...“DataAugmentation”、增压器);trainedNet = trainNetwork(augimds,lgraphSQZ,opts);

获得SqueezeNet精度,绘制混淆图,并计算F1分数。

ypred = trainednet . category (testImds);sqznetAccuracy = sum(ypred == testImds.Labels)/numel(testImds.Labels)*100
sqznetAccuracy = 73.3333
figure cchart = confusionchart(testImds.Labels,ypred);cchart。Title ={《迁移学习困惑图》“与SqueezeNet”};cchart。RowSummary =“row-normalized”;cchart。ColumnSummary =“column-normalized”

f1SqueezeNet = f1score(cchart.NormalizedValues);disp (f1SqueezeNet)
F1 _______巴贝虫病0.72727疟原虫-配子体细胞0.8锥虫病0.66667

在锥虫病F1评分方面,SqueezeNet的表现优于简单的CNN,但在小波散射特征下的PCA分类器的精度方面,表现不如简单的PCA分类器。

总结

在本例中,采用小波散射变换和深度学习框架对Giemsa染色图像中的病原体进行分类。有限的数据集大小为训练深度学习分类器提供了挑战,即使使用数据增强。算例表明,小波散射变换在这种情况下可以为深度网络提供一种有用的替代方法。在从小波散射变换形成特征向量时,我们将每个变换输出从27 × 38 × 38 × 3张量减少到27元向量。因此,我们使用了散射系数的全局池。可以利用其他池化方案,从而产生更好的结果。

附录-配套功能金宝app

函数features = helperScatImages_mean(sn,x)特征= mean(smat,2:4);Features = Features ';结束函数F1scores = f1score(cchartVal)“所有”);probT = sum(chartval)./N;classProbEst = diag(chartval)./N;Prec = classProbEst'./probT;probC = [5/15 5/15 5/15];Recall = classProbEst'./probC;F1scores = harmmean([Prec;记得]);F1scores = F1scores';F1scores = table(“VariableNames”, {“F1”},...“RowNames”, {“巴贝西虫病”“plasmodium-gametocyte”锥虫病的});结束函数标签= helperPCAClassifier(特征,模型)此函数仅支持小波图像散射的例子金宝app小波工具箱。它可能会在未来的版本中被更改或删除。% model是一个结构数组,包含字段M、mu、v和Labels% features为测试数据的Ns × l矩阵,Ns为的个数%散射路径,L为测试样例数。的每一列% features是一个测试示例。版权所有2018-2021labelIdx = determineClass(特征,模型);labels = model.Labels(labelIdx);%作为列向量返回,以与imageDatastore Labels一致标签=标签(:);%--------------------------------------------------------------------------函数labelIdx = determineClass(特征,模型)确定类的数量Nclasses = numel(model.Labels);初始化错误矩阵errMatrix = Inf(Nclasses,size(features,2));nc = 1:表示Nclasses形心%Mu = model.mu{nc};u = model.U{nc};% 1-by-LerrMatrix(nc,:) = projectionError(features,mu,u);结束沿类维确定最小值[~,labelIdx] = min(errMatrix,[],1);%--------------------------------------------------------------------------函数totalerr = projectionError(特征,mu,u)Npc = size(u,2);L =尺寸(特征,2);减去类均值:Ns-by-L - Ns-by-1S = features-mu;% 1-by-LnormSqX = sum(abs(s).^2,1)';err = Inf(Npc+1,L);err(1,:) = normSqX;Err (2:end,:) = -abs(u'*s).^2;% 1-by-LTotalerr =√(sum(err,1));结束结束结束函数model = helppcamodel(特征,M,标签)此函数仅支持小波图像散射的例子金宝app小波工具箱。它可能会在未来的版本中被更改或删除。% model = helppcamodel(特征,M,标签)版权所有2018-2021初始化结构数组以保存仿射模型模型= struct(“暗”[],“亩”[],“U”[],“标签”分类([]),“年代”[]);模型。Dim = M;获取类的数量LabelCategories =类别(标签);Nclasses = number(类别(标签));kk = 1:Nclasses类= LabelCategories{kk};找到每个类对应的索引idxClass =标签==类;提取每个类的特征向量tmpFeatures = features(:,idxClass);确定每个类的平均值模型。mu{kk} = mean(tmpFeatures,2);[model.U {kk},模型。S{kk}] = scatPCA(tmpFeatures);如果size(model. u {kk},2) > M型号。U{kk} = model.U{kk}(:,1:M);模型。S{kk} = model.S{kk}(1:M);结束model.Labels(kk) = Class;结束函数[u,s,v] = scatPCA(x)计算x沿二次元的主成分。[u,d] = eig(cov(x'));协方差矩阵特征值降序排序[s,ind] = sort(diag(d),“下”);%对特征向量矩阵进行排序U = U (:,ind);结束结束

另请参阅

相关的例子

更多关于