主要内容

使用YOLO v3深度学习的对象检测

这个例子展示了如何训练YOLO v3意思对象探测器。

深度学习是一种强大的机器学习技术,可以用来训练健壮的目标探测器。有几种用于物体检测的技术,包括Faster R-CNN、you only look once (YOLO) v2和single shot detector (SSD)。这个例子展示了如何训练YOLO v3对象检测器。YOLO v3在YOLO v2的基础上进行了改进,增加了多尺度的检测,帮助检测更小的对象。将用于训练的损失函数分解为边界盒回归的均方误差和用于目标分类的二叉交叉熵,以提高检测精度。

注意:这个例子需要计算机视觉工具箱™模型用于YOLO v3对象检测。您可以从附加组件资源管理器中安装用于YOLO v3对象检测的计算机视觉工具箱模型。有关安装附加组件的详细信息,请参见获取和管理附加组件

下载Pretrained网络

使用helper函数下载预先训练过的网络downloadPretrainedYOLOv3Detector以避免等待训练完成。如果你想训练网络,设置doTraining变量来真正的

doTraining = false;如果~doTraining preTrainedDetector = downloadPretrainedYOLOv3Detector();结束

加载数据

本例使用一个包含295张图像的小标记数据集。这些图像中有许多来自加州理工学院汽车1999年和2001年的数据集,可以在加州理工学院计算视觉中心获得网站,由Pietro Perona创作并获得许可使用。每个图像包含一个或两个已标记的车辆实例。较小的数据集对于研究YOLO v3训练过程很有用,但在实践中,需要更多标记的图像来训练健壮的网络。

解压缩车辆图像,加载车辆地面真实数据。

解压缩vehicleDatasetImages.zipdata =负载(“vehicleDatasetGroundTruth.mat”);vehicleDataset = data.vehicleDataset;将完整路径添加到本地车辆数据文件夹。vehicleDataset。imageFilename = fullfile(pwd,车辆数据集。imageFilename);

注意:在多个类的情况下,数据还可以组织为三列,其中第一列包含带有路径的图像文件名,第二列包含边界框,第三列必须是包含与每个边界框对应的标签名称的单元格向量。有关如何排列边框和标签的更多信息,请参见boxLabelDatastore

所有的边界框必须在表单中[x y宽度高度].这个向量指定左上角和边界框的大小(以像素为单位)。

将数据集分割为训练网络的训练集和评估网络的测试集。将60%的数据用于训练集,其余数据用于测试集。

rng (0);shuffledIndices = randperm(高度(vehicleDataset));idx = floor(0.6 * length(shuffledIndices));trainingDataTbl =车辆数据集(shuffledIndices(1:idx),:);testDataTbl = vehicleDataset(shuffledIndices(idx+1:end),:);

创建用于加载图像的图像数据存储。

imdsTrain = imageDatastore (trainingDataTbl.imageFilename);imdsTest = imageDatastore (testDataTbl.imageFilename);

创建一个数据存储为地面真理边界框。

bldsTrain = boxLabelDatastore(trainingDataTbl(:, 2:end));bldsTest = boxLabelDatastore(testDataTbl(:, 2:end));

合并图像和框标签数据存储。

trainingData = combine(imdsTrain, bldsTrain);testData = combine(imdsTest, bldsTest);

使用validateInputData检测无效图像、边框或标签,例如,

  • 带有无效图像格式或包含nan的示例

  • 包含0 / nan / info /空的包围框

  • 失踪/ non-categorical标签。

边界框的值应该是有限的、正的、非分数的、非nan的,并且应该在图像边界内,高度和宽度都是正的。任何无效的样品必须丢弃或固定以进行适当的培训。

validateInputData (trainingData);validateInputData (testData);

数据增加

在训练过程中,通过随机变换原始数据来提高网络的精度。通过使用数据增广,您可以向训练数据添加更多种类,而不必实际增加已标记训练样本的数量。

使用变换函数将自定义数据增强应用于训练数据。的augmentData示例最后列出的Helper函数对输入数据应用以下扩展。

  • HSV空间的颜色抖动增强

  • 随机水平翻转

  • 随机10%的比例

augmentedTrainingData = transform(trainingData, @augmentData);

读相同的图像四次,并显示增强的训练数据。

%可视化增强图像。augmentedData =细胞(4,1);k = 1:4 data = read(augmentedTrainingData);augmentedData {k} = insertShape(数据{1 1},“矩形”、数据{1,2});重置(augmentedTrainingData);结束图蒙太奇(augmentedData,“BorderSize”, 10)

定义YOLO v3对象检测器

本例中的YOLO v3探测器基于SqueezeNet,采用了SqueezeNet中的特征提取网络,并在最后增加了两个检测头。第二个检测头的尺寸是第一个检测头的两倍,所以它能更好地检测小物体。注意,您可以根据您想要检测的对象的大小指定任意数量的不同大小的检测头。YOLO v3检测器使用使用训练数据估计的锚盒,以获得更好的对应于数据集类型的初始先验,并帮助检测器学习准确预测锚盒。有关锚框的信息,请参见用于对象检测的锚盒

YOLO v3探测器中的YOLO v3网络如下图所示。

您可以使用深层网络设计师(深度学习工具箱)创建图中所示的网络。

指定网络输入大小。在选择网络输入尺寸时,考虑网络本身运行所需的最小尺寸、训练图像的尺寸以及在选定尺寸下处理数据所需要的计算代价。在可行的情况下,选择一个与训练图像尺寸相近且大于网络所需输入尺寸的网络输入尺寸。为了减少运行示例的计算成本,指定网络输入大小为[227 227]。

networkInputSize = [227 227 3];

首先,使用变换对训练数据进行预处理,以便计算锚盒,因为本例中使用的训练图像大于227 × 227,且大小不同。将锚的数量指定为6,以在锚的数量和平均IoU之间实现良好的权衡。使用estimateAnchorBoxes函数来估计锚盒。有关锚盒估计的详细信息,请参见根据训练数据估计锚盒.在使用预先训练的YOLOv3对象检测器的情况下,需要指定在特定训练数据集上计算的锚盒。注意,评估过程是不确定的。为了防止估计锚盒在调优其他超参数时发生变化,在使用rng进行估计之前设置随机种子。

rng(0) trainingdatafreestimation = transform(trainingData, @(data)preprocessData(data, networkInputSize));numAnchors = 6;[锚,meanIoU] = estimateAnchorBoxes(trainingdatafestimation, numAnchors)
锚=6×241 34 163 130 98 93 144 125 33 24 69 66
meanIoU = 0.8507

指定anchorBoxes用于两个探测头。anchorBoxes为[mx]单元阵列,其中M为检测头数。每个检测头由的[Nx2]矩阵组成,其中N是要使用的锚的数量。选择anchorBoxes基于特征图大小对每个检测头进行检测。使用更大的规模更小在更高的规模。为此,对首先使用较大的锚盒,并将前三个锚盒分配给第一个检测头,将后三个锚盒分配给第二个检测头。

区域=锚(:,1).*锚(:,2);[~, idx] = sort(area,“下”);锚=锚(idx,:);anchorBoxes ={锚(1:3,:)锚(4:6,:)};

在Imagenet数据集上加载预先训练好的SqueezeNet网络,然后指定类名。您还可以选择在COCO数据集上加载不同的预训练网络,例如tiny-yolov3-cocodarknet53-coco或Imagenet数据集,如MobileNet-v2或ResNet-18。当您使用预先训练过的网络时,YOLO v3的性能更好,训练更快。

baseNetwork = squeezenet;一会= trainingDataTbl.Properties.VariableNames(2:结束);

接下来,创建yolov3ObjectDetector对象,通过添加检测网络源。选择最优的检测网络源需要反复试验,可以使用analyzeNetwork查找网络内潜在探测网络源的名称。在本例中,使用fire9-concatfire5-concat层,DetectionNetworkSource

yolov3Detector = yolov3ObjectDetector(baseNetwork, classNames, anchorBoxes,“DetectionNetworkSource”, {“fire9-concat”“fire5-concat”});

另外,与上面使用SqueezeNet创建的网络不同,使用MS-COCO等更大的数据集训练的其他预先训练的YOLOv3架构可以用来在自定义目标检测任务中迁移学习检测器。迁移学习可以通过改变类名和锚盒来实现。

训练数据进行预处理

对增强后的训练数据进行预处理,为训练做准备。的进行预处理方法yolov3ObjectDetector,对输入数据应用以下预处理操作。

  • 通过保持宽高比来调整图像到网络输入的大小。

  • 在范围内缩放图像像素[0 1]

preprocesedtrainingdata = transform(augmentedTrainingData, @(data)preprocess(yolov3Detector, data));

读取预处理后的训练数据。

data =阅读(preprocessedTrainingData);

显示带有边框的图像。

我={1 1}数据;bbox ={1,2}数据;annotatedImage = insertShape(我“矩形”, bbox);annotatedImage = imresize (annotatedImage 2);图imshow (annotatedImage)

重置数据存储。

重置(preprocessedTrainingData);

指定培训选项

指定这些培训选项。

  • 设置纪元数为80。

  • 设置最小批量大小为8.当使用更高的小批量时,稳定的训练可能具有更高的学习率不过,这应该根据可用内存进行设置。

  • 学习率设置为0.001。

  • 设置预热时间为1000迭代。该参数表示根据公式指数增加学习率的迭代次数 learningRate × 迭代 warmupPeriod 4 .它有助于在较高的学习速率下稳定梯度。

  • 设置L2正则化系数为0.0005。

  • 指定惩罚阈值为0.5。与地面真实值重叠小于0.5的检测将被扣分。

  • 初始化梯度的速度为[].这是SGDM用来存储梯度的速度。

numEpochs = 80;miniBatchSize = 8;learningRate = 0.001;warmupPeriod = 1000;l2Regularization = 0.0005;penaltyThreshold = 0.5;速度= [];

火车模型

在GPU上训练(如果有的话)。使用GPU需要并行计算工具箱™和支持CUDA®的NVIDIA®GPU。有关支持的计算能力的信息,请参见金宝appGPU支金宝app持情况(并行计算工具箱)

使用minibatchqueue函数,对预处理后的训练数据进行批量分割,并提供支持功能金宝appcreateBatchData它返回与各自类id相结合的批处理图像和包围框。为了更快地提取训练所需的批处理数据,dispatchInBackground应该设置为“true”,以确保使用并行池。

minibatchqueue自动检测GPU可用性。如果你没有图形处理器,或者不想使用图形处理器进行训练,请设置OutputEnvironment参数“cpu”

如果canUseParallelPool dispatchInBackground = true;其他的dispatchInBackground = false;结束mbqTrain = minibatchqueue(preprocesedtrainingdata, 2,)...“MiniBatchSize”miniBatchSize,...“MiniBatchFcn”, @(images, boxes, labels) createBatchData(images, boxes, labels, classNames),...“MiniBatchFormat”, (“SSCB”""],...“DispatchInBackground”dispatchInBackground,...“OutputCast”, (""“替身”]);

使用辅助功能创建培训进度图金宝appconfigureTrainingProgressPlotter在使用自定义训练循环训练检测器对象时查看情节。

最后,指定自定义训练循环。每一次迭代:

  • minibatchqueue.如果它没有更多的数据,重置minibatchqueue和洗牌。

  • 使用dlfevalmodelGradients函数。这个函数modelGradients,作为支持函数列出,返回相对金宝app于中的可学习参数的损失梯度,对应的小批损失,以及当前批的状态。

  • 在正则化梯度上应用权值衰减因子以获得更健壮的训练。

  • 确定学习率基于迭代使用piecewiseLearningRateWithWarmup金宝app支持功能。

  • 方法更新检测器参数sgdmupdate函数。

  • 更新状态具有移动平均的检测器参数。

  • 显示每次迭代的学习速率、总损耗和个体损耗(盒损耗、对象损耗和类损耗)。这些可以用来解释在每个迭代中各自的损失是如何变化的。例如,在几次迭代后盒子丢失的突然峰值意味着预测中有Inf或nan。

  • 更新培训进度图。

如果损失在少数时期达到饱和,培训也可以终止。

如果doTraining%创建学习率和小批量损失的子图。无花果=图;[lossPlotter, learningrateful plotter] = configureTrainingProgressPlotter(fig);迭代= 0;%自定义训练循环。纪元= 1:numEpochs reset(mbqTrain);洗牌(mbqTrain);(hasdata(mbqTrain))迭代=迭代+ 1;[XTrain, YTrain] = next(mbqTrain);使用dlfeval和% modelGradients函数。[gradient, state, lossInfo] = dlfeval(@modelGradients, yolov3Detector, XTrain, YTrain, penaltyThreshold);%应用L2正则化。gradient = dlupdate(@(g,w) g + l2Regularization*w, gradient, yolov3Detector.Learnables);%确定当前学习率值。currenttlr = piecewiselearningretwithwarmup (iteration, epoch, learningRate, warmupPeriod, numEpochs);%使用SGDM优化器更新检测器可学习参数。[yolov3Detector。= sgdmupdate(yolov3检测器。学习性,梯度,速度,当前tlr);%更新dlnetwork的状态参数。yolov3Detector。=状态;%显示进展。displayLossInfo(epoch, iteration, currenttlr, lossInfo);%用新的点数更新训练图。updateplot (lossPlotter, learningrateful plotter, iteration, currenttlr, lossInfo.totalLoss);结束结束其他的yolov3Detector = preTrainedDetector;结束

评估模型

计算机视觉工具箱™提供对象检测器评估功能,以测量常见的指标,如平均精度(evaluateDetectionPrecision)和日志平均遗漏率(evaluateDetectionMissRate).在本例中,使用的是平均精度度量。平均精度提供了一个单一的数字,该数字包括探测器进行正确分类的能力(精度)和探测器找到所有相关对象的能力(回忆)。

结果=检测(yolov3Detector testData,“MiniBatchSize”8);使用平均精度度量来评估物体探测器。[据美联社、召回、精密]= evaluateDetectionPrecision(结果,testData);

精确召回(PR)曲线显示了探测器在不同召回级别上的精确程度。理想情况下,所有召回级别的精度都是1。

绘制精度-召回率曲线。图绘制(召回、精密)包含(“回忆”) ylabel (“精度”网格)标题(sprintf ('平均精度= %.2f'据美联社)),

使用YOLO v3检测对象

使用检测器进行对象检测。

%读取数据存储。data =阅读(testData);%获取图像。我={1}数据;[bboxes、分数、标签]=检测(yolov3Detector,我);%在图像上显示检测结果。我= insertObjectAnnotation (,“矩形”bboxes,分数);图imshow(我)

金宝app支持功能

模型梯度函数

这个函数modelGradientsyolov3ObjectDetector对象,输入数据的小批处理XTrain与相应的地面真理箱YTrain中指定的惩罚阈值作为输入参数,并返回损失相对于中可学习参数的梯度yolov3ObjectDetector,对应的小批丢失信息,以及当前批的状态。

模型梯度函数通过执行这些操作来计算总损失和梯度。

  • 生成预测从输入的一批图像使用向前方法。

  • 收集CPU上的预测以进行后处理。

  • 将YOLO v3网格单元坐标的预测转换为边界框坐标,以方便与地面真实数据进行比较anchorBoxGenerator的方法yolov3ObjectDetector

  • 利用转换后的预测和地面真实数据生成损失计算目标。这些目标是针对边界框位置(x, y,宽度,高度),对象可信度和类别概率生成的。见支持函数金宝appgenerateTargets

  • 计算预测的边界盒坐标与目标盒的均方误差。见支持函数金宝appbboxOffsetLoss

  • 确定预测对象置信度与目标对象置信度的二元交叉熵。见支持函数金宝appobjectnessLoss

  • 确定预测类目标与目标的二元交叉熵。见支持函数金宝appclassConfidenceLoss

  • 以所有损失的总和计算总损失。

  • 计算可学习内容相对于总损失的梯度。

函数[gradient, state, info] = modelGradients(detector, XTrain, YTrain, penaltyThreshold) inputImageSize = size(XTrain,1:2);%在CPU中收集地面真相进行后期处理YTrain =收集(extractdata (YTrain));%从检测器中提取预测。[gatheredPredictions, YPredCell, state] = forward(检测器,XTrain);%从地面真实数据生成预测目标。[boxTarget, objectnessTarget, classTarget, objectMaskTarget, boxErrorScale] = generatettargets (gatheredPredictions,...YTrain inputImageSize,探测器。AnchorBoxes penaltyThreshold);%计算损失。boxLoss = bboxOffsetLoss(YPredCell(:,[2 3 7 8]),boxTarget,objectMaskTarget,boxErrorScale);objLoss = objectnessLoss (YPredCell (: 1), objectnessTarget, objectMaskTarget);clsLoss = classConfidenceLoss (YPredCell (:, 6), classTarget, objectMaskTarget);totalLoss = boxLoss + objLoss + clsLoss;信息。boxLoss = boxLoss;信息。objLoss = objLoss;信息。clsLoss = clsLoss; info.totalLoss = totalLoss;%计算可学习物品相对于损失的梯度。gradient = dlgradient(totalLoss, detector.Learnables);结束函数boxLoss = bboxOffsetLoss(boxPredCell, boxDeltaTarget, boxMaskTarget, boxErrorScaleTarget)限定框位置的均方误差。lossX = sum(cellfun(@(a,b,c,d) mse(a.*c.*d,b.*c.*d),boxPredCell(:,1),boxDeltaTarget(:,1),boxMaskTarget(:,1),boxErrorScaleTarget));lossY = sum(cellfun(@(a,b,c,d) mse(a.*c.*d,b.*c.*d),boxPredCell(:,2),boxDeltaTarget(:,2),boxMaskTarget(:,1),boxErrorScaleTarget));lossW = sum(cellfun(@(a,b,c,d) mse(a.*c.*d,b.*c.*d),boxPredCell(:,3),boxDeltaTarget(:,3),boxMaskTarget(:,1),boxErrorScaleTarget));lossH = sum(cellfun(@(a,b,c,d) mse(a.*c.*d,b.*c.*d),boxPredCell(:,4),boxDeltaTarget(:,4),boxMaskTarget(:,1),boxErrorScaleTarget));boxLoss = lossX +损耗+ lossW + lossH;结束函数objLoss = objectnessLoss(objectnessPredCell, objectnessDeltaTarget, boxMaskTarget)%客观分数的二元交叉熵损失。objLoss = sum(cellfun(@(a,b,c)) crossentropy(a.*c,b.*c,))“TargetCategories”“独立”)、objectnessPredCell objectnessDeltaTarget boxMaskTarget (:, 2)));结束函数clsLoss = classconfenceloss (classPredCell, classTarget, boxMaskTarget)类置信度的二元交叉熵损失。clsLoss = sum(cellfun(@(a,b,c)) crossentropy(a.*c,b.*c,))“TargetCategories”“独立”)、classPredCell classTarget boxMaskTarget (:, 3)));结束

增强和数据处理功能

函数data = augmentData (A)%应用随机水平翻转和随机X/Y缩放。盒子,如果重叠大于0.25,则在边界外缩放的%被截断。同时,抖动图像颜色。data =细胞(大小(A));ii = 1:size(A,1) I = A{ii,1};bboxes = {ii, 2};标签= {ii, 3};深圳=大小(I);如果numel(sz) == 3 && sz(3) == 3 I = jitterColorHSV(I,...“对比”, 0.0,...“颜色”, 0.1,...“饱和”, 0.2,...“亮度”, 0.2);结束%随机翻转图像。tform = randomAffine2d (“XReflection”,真的,“规模”1.1 [1]);tform溃败= affineOutputView(深圳,“BoundsStyle”“centerOutput”);我= imwarp (tform,“OutputView”,溃败);对方框应用相同的转换。[bboxes,指数]= bboxwarp (bboxes、tform溃败,“OverlapThreshold”, 0.25);标签=标签(指标);%仅当所有的框被扭曲时返回原始数据。如果isempty(indices) data(ii,:) = A(ii,:);其他的data(ii,:) = {I, bboxes, labels};结束结束结束函数data = preprocessData(data, targetSize)%调整图像的大小和缩放像素到0和1之间。同时规模%对应的边界框。ii = 1:size(data,1) I = data{ii,1};imgSize =大小(I);将单通道输入图像转换为3通道。如果nummel (imgSize) < 3 I = repmat(I,1,1,3);结束bboxes = {ii, 2}数据;我= im2single (imresize(我targetSize (1:2)));规模= targetSize(1:2)。/ imgSize (1:2);bboxes = bboxresize (bboxes、规模);data(ii, 1:2) = {I, bboxes};结束结束函数[XTrain, YTrain] = createBatchData(data, groundTruthBoxes, groundTruthClasses, classNames)%返回在XTrain和中沿着批处理维度组合的图像在YTrain中用classid连接的归一化包围盒%沿批处理尺寸连接图像。XTrain = cat(4, data{:,1});%从类名获取类id。classNames = repmat({classical (classNames')}, size(groundTruthClasses));[~, classIndices] = cellfun(@(a,b))ismember(a,b), groundTruthClasses, classNames,“UniformOutput”、假);%添加标签索引和训练图像大小到缩放的边界框%并创建一个响应单元格数组。@(bbox, classid)[bbox, classid], groundTruthBoxes, classIndices,“UniformOutput”、假);len = max(cellfun(@(x)size(x,1), combinedResponses));paddeddbboxes = cellfun(@(v)) padarray(v,[len-size(v,1),0],0,“职位”)、combinedResponses“UniformOutput”、假);YTrain = cat(4, paddeddbboxes {:,1});结束

学习率Schedule命令功能

函数currenttlr = piecewiselearningretwithwarmup (iteration, epoch, learningRate, warmupPeriod, numEpochs)% piecewiselearningrateful withwarmup函数计算当前%基于迭代次数的学习率。持续的warmUpEpoch;如果迭代< = warmupPeriod%在预热阶段增加迭代次数的学习率。currentLR = learningRate * (((iteration/warmupPeriod)^4); / /循环周期warmUpEpoch =时代;elseif迭代>= warmupPeriod && epoch < warmUpEpoch+floor(0.6*(numEpochs-warmUpEpoch))%在热身期结束后,如果剩余纪元数小于60%,则保持学习率不变。currentLR = learningRate;elseifepoch >= warmUpEpoch+floor(0.6*(numEpochs-warmUpEpoch)) && epoch < warmUpEpoch+floor(0.9*(numEpochs-warmUpEpoch))%剩余纪元数超过60%但少于60%90%以上的学习率乘以0.1。currentLR = learningRate * 0.1;其他的如果剩余的时代是90%以上乘以学问%率0.01。currentLR = learningRate * 0.01;结束结束

效用函数

函数[lossPlotter, learningrateful plotter] = configureTrainingProgressPlotter(f)%创建子图来显示丢失和学习率。图(f);clf次要情节(2,1,1);ylabel (学习速率的);包含(“迭代”);learningRatePlotter = animatedline;次要情节(2,1,2);ylabel (“全损”);包含(“迭代”);lossPlotter = animatedline;结束函数displayLossInfo(epoch, iteration, currenttlr, lossInfo)显示%显示每个迭代的损失信息。disp (”时代:“+时代+“|迭代:”+迭代+|学习率:+ currentLR +...|全损:+双(收集(extractdata (lossInfo.totalLoss))) +...“|箱损:”+双(收集(extractdata (lossInfo.boxLoss))) +...“|物体丢失:”+双(收集(extractdata (lossInfo.objLoss))) +...|等级损失:+双(收集(extractdata (lossInfo.clsLoss))));结束函数updateplot (lossPlotter, learningrateful plotter, iteration, currenttlr, totalLoss)%更新损失和学习速率图。addpoints (lossPlotter、迭代、双(extractdata(收集(totalLoss))));addpoints (learningRatePlotter迭代,currentLR);drawnow结束函数探测器= downloadPretrainedYOLOv3Detector ()下载一个经过训练的yolov3探测器。如果~ (“yolov3SqueezeNetVehicleExample_21aSPKG.mat”“文件”如果~ (“yolov3SqueezeNetVehicleExample_21aSPKG.zip”“文件”) disp (“下载pretrained探测器…”);pretrainedURL =“https://ssd.mathworks.com/金宝appsupportfiles/vision/data/yolov3SqueezeNetVehicleExample_21aSPKG.zip”;websave (“yolov3SqueezeNetVehicleExample_21aSPKG.zip”, pretrainedURL);结束解压缩(“yolov3SqueezeNetVehicleExample_21aSPKG.zip”);结束pretrained =负载(“yolov3SqueezeNetVehicleExample_21aSPKG.mat”);探测器= pretrained.detector;结束

参考文献

雷蒙德,约瑟夫和阿里·法哈迪。“YOLOv3:一个渐进的改进。”预印本,2018年4月8日提交。https://arxiv.org/abs/1804.02767。

另请参阅

||||(深度学习工具箱)||

相关的话题