主要内容

对象检测使用YOLO v3意思深入学习

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

深度学习是一个功能强大的机器学习技术,你可以用它来训练健壮的对象探测器。几个对象检测存在的技术,包括R-CNN更快,你只看一次(YOLO)意思v2,和单检测器(SSD)。这个例子展示了如何训练YOLO v3意思对象探测器。YOLO v3改善在YOLO v2意思意思通过添加检测在多个尺度来帮助检测更小的物体。损失函数用于培训分为均方误差为对象边界框回归和二叉分类来帮助提高检测精度。

注意:这个例子需要计算机视觉工具箱YOLO v3意思™模型对象检测。您可以安装的计算机视觉工具箱模型YOLO v3意思对象检测从附加的探险家。关于安装插件的更多信息,请参阅获取和管理插件

下载Pretrained网络

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

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

加载数据

这个例子使用一个小标签数据集,其中包含295张图片。这些图片来自加州理工学院的汽车1999年和2001年的数据集,可以在加州理工学院的计算机视觉网站由Pietro Perona一起提供,经允许使用。每个图像都包含一个或两个标签的实例。小的数据集是用于探索YOLO v3意思培训过程,但在实践中,需要更多的标签图片来训练一个健壮的网络。

解压缩车辆图像和车辆地面实况数据加载。

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

注意:多个类,数据也可以组织为三列,第一列包含图像文件的名称和路径,第二列包含边界框和第三列必须是一个细胞向量包含标签名称对应于每一个边界框。为更多的信息关于如何安排边界框和标签,看到的boxLabelDatastore

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

将数据集分为训练集训练网络,和一个测试集来评估网络。使用60%的数据训练集和测试集。

rng (0);shuffledIndices = randperm(高度(vehicleDataset));地板idx =(0.6 *长度(shuffledIndices));trainingDataTbl = vehicleDataset (shuffledIndices (1: idx):);testDataTbl = vehicleDataset (shuffledIndices (idx + 1:结束):);

创建一个图像数据存储加载的图像。

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

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

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

结合图片和盒子标签数据存储。

trainingData =结合(imdsTrain bldsTrain);testData =结合(imdsTest bldsTest);

使用validateInputData检测到无效的图像边界盒子或标签,例如,

  • 样品与无效的图像格式或包含nan

  • 边界框包含0 / nan /正/空的

  • 失踪/ non-categorical标签。

边界框的值应该是有限的,积极的,non-fractional, non-NaN图像边界内,应该积极的高度和宽度。任何无效的样本必须被丢弃或固定的适当的培训。

validateInputData (trainingData);validateInputData (testData);

数据增加

数据增加用于提高网络精度通过随机改变原始数据在训练。通过使用数据,您可以添加更多的各种训练数据而不必实际增加标记训练样本的数量。

使用变换功能应用定制数据对应的训练数据。的augmentDatahelper函数,列出的例子,下面的对应适用于输入数据。

  • 颜色抖动在HSV空间增大

  • 随机水平翻转

  • 随机比例10%

augmentedTrainingData =变换(trainingData @augmentData);

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

%可视化增强图像。augmentedData =细胞(4,1);k = 1:4 data =阅读(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实现很好的权衡的锚和意味着借据。使用estimateAnchorBoxes函数来估计锚盒子。在估计锚盒子的详细信息,请参见从训练数据估计锚箱。如果使用pretrained YOLOv3对象探测器,锚箱计算需要指定特定训练数据集。注意,估计过程是不确定的。防止锚盒子估计变化而调整其他hyperparameters估计使用rng之前设置随机种子。

rng (0) trainingDataForEstimation =变换(trainingData @(数据)preprocessData(数据、networkInputSize));numAnchors = 6;[锚,meanIoU] = estimateAnchorBoxes (trainingDataForEstimation numAnchors)
锚=6×241 34 163 130 98 93 144 125 24 69 66 33
meanIoU = 0.8507

指定anchorBoxes使用的检测。anchorBoxes是一个单元阵列(mx₁), M表示检测头的数量。每一个检测头由一个[Nx2]矩阵,其中N是主持人使用的数量。选择anchorBoxes基于特征映射为每个探测头的大小。使用更大的以较低的规模和小在更高的规模。为此,排序先用大锚箱,并将前三个分配给第一个检测头和未来三到第二个检测头。

面积=锚(:1)。*锚(:,2);[~,idx] =排序(区域,“下”);锚=锚(idx:);:anchorBoxes ={锚(1:3)锚(4:6 -:)};

加载SqueezeNet网络pretrained Imagenet数据集,然后指定类名。你也可以选择加载不同pretrained等可可数据集训练网络tiny-yolov3-cocodarknet53-coco或Imagenet MobileNet-v2或ResNet-18等数据集。YOLO v3执行更好和火车更快意思当你使用pretrained网络。

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

接下来,创建yolov3ObjectDetector通过添加检测网络源对象。选择最优检测网络源需要试验和错误,你可以使用analyzeNetwork寻找潜在的名字检测网络中源网络。对于这个示例,使用fire9-concatfire5-concat层,DetectionNetworkSource

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

或者,而不是使用SqueezeNet上面创建的网络,其他pretrained YOLOv3架构培训使用MS-COCO等更大的数据集可以用来转移学习自定义对象的探测器探测任务。转移学习可以实现通过改变类名和anchorBoxes。

训练数据进行预处理

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

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

  • 规模的图像像素的范围内[0 1]

preprocessedTrainingData =变换(augmentedTrainingData @(数据)进行预处理(yolov3Detector、数据));

阅读训练数据预处理。

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与地面真理处罚。

  • 初始化的速度梯度[]。这是用个存储的速度梯度。

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的可用性。如果你没有一个GPU,或不希望使用一个用于培训,设置OutputEnvironment参数“cpu”

如果canUseParallelPool dispatchInBackground = true;其他的dispatchInBackground = false;结束mbqTrain = minibatchqueue (preprocessedTrainingData 2“MiniBatchSize”miniBatchSize,“MiniBatchFcn”@(图片,盒子,标签)createBatchData(图片,盒子,标签,类名),“MiniBatchFormat”,(“SSCB”,”“),“DispatchInBackground”dispatchInBackground,“OutputCast”,(”“,“替身”]);

使用支持函数创建培训进展绘图仪金宝appconfigureTrainingProgressPlotter看到情节而培训探测器对象与一个定制的循环。

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

  • 读取的数据minibatchqueue。如果它没有任何更多的数据,重置minibatchqueue和洗牌。

  • 评估模型梯度使用dlfevalmodelGradients函数。这个函数modelGradients,列为支持函数,返回损失的梯金宝app度对可学的参数,相应的mini-batch损失,当前批的状态。

  • 应用权重衰减系数的梯度正则化更健壮的培训。

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

  • 更新探测器参数使用sgdmupdate函数。

  • 更新状态探测器与移动平均线的参数。

  • 显示学习速率,全损,个人损失(损失,对象和类损失损失)为每个迭代。这些可以用来解释如何改变在每个迭代中相应的损失。例如,突然几个迭代后的盒子损失意味着有正或nan的预测。

  • 更新培训进展阴谋。

培训也可以终止如果几个时代的损失已经饱和。

如果doTraining%为学习速率创建次要情节和mini-batch损失。无花果=图;[lossPlotter, learningRatePlotter] = configureTrainingProgressPlotter(图);迭代= 0;%的定制培训循环。时代= 1:numEpochs重置(mbqTrain);洗牌(mbqTrain);(hasdata (mbqTrain)) =迭代+ 1;[XTrain, YTrain] =下一个(mbqTrain);%计算模型使用dlfeval和梯度和损失% modelGradients函数。(渐变、州lossInfo) = dlfeval (@modelGradients、yolov3Detector XTrain, YTrain, penaltyThreshold);%应用L2正规化。梯度= dlupdate (@ (g, w) g + l2Regularization * w,渐变yolov3Detector.Learnables);%确定当前的学习速率值。currentLR = piecewiseLearningRateWithWarmup(迭代,时代、learningRate warmupPeriod, numEpochs);%更新使用个探测器可学的参数优化器。[yolov3Detector。可学的,速度]= sgdmupdate (yolov3Detector。可学的、渐变速度,currentLR);%更新dlnetwork的状态参数。yolov3Detector。=状态;%显示进展。displayLossInfo(时代、迭代,currentLR lossInfo);%绘制新的点更新培训。updatePlots (lossPlotter learningRatePlotter、迭代、currentLR lossInfo.totalLoss);结束结束其他的yolov3Detector = preTrainedDetector;结束

评估模型

计算机视觉工具箱™提供了对象探测器评价函数来测量常见的指标,如平均精度(evaluateDetectionPrecision)和log-average错过率(evaluateDetectionMissRate)。在这个示例中,使用的平均精度指标。平均精度提供了一个数字,包含探测器进行正确分类的能力(精度)和探测器的能力找到所有相关对象(回忆)。

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

precision-recall(公关)曲线显示了如何准确的探测器在不同级别的召回。理想情况下,精度为1的召回的水平。

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

使用YOLO v3意思检测对象

使用对象的检测器检测。

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

金宝app支持功能

模型梯度函数

这个函数modelGradientsyolov3ObjectDetectormini-batch对象的输入数据XTrain与相应的地面实况盒子YTrain,惩罚阈值作为输入参数,并返回指定渐变的损失对可学的参数yolov3ObjectDetector,相应的mini-batch损失信息,当前批的状态。

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

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

  • 对后处理收集CPU上的预测。

  • 转换的预测YOLO v3意思网格单元坐标边界框坐标允许容易与地面实况数据使用anchorBoxGenerator的方法yolov3ObjectDetector

  • 生成目标损失计算通过使用预测和地面实况数据转换。这些目标是生成的边界框的位置(x, y,宽度、高度),对象的信心,和类的概率。看到支持函数金宝appgenerateTargets

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

  • 决定了预测对象的二进制叉信心得分与目标对象信心得分。看到支持函数金宝appobjectnessLoss

  • 决定了二叉叉的预测与目标类的对象。看到支持函数金宝appclassConfidenceLoss

  • 计算总损失损失的总和。

  • 计算梯度可学的对总损失。

函数(梯度、状态信息)= modelGradients (YTrain,探测器,XTrain penaltyThreshold) inputImageSize =大小(XTrain 1:2);%收集地面真理CPU的处理YTrain =收集(extractdata (YTrain));%提取探测器的预测。[gatheredPredictions、YPredCell] =前进(探测器,XTrain);%从地面实况数据生成目标预测。[boxTarget, objectnessTarget classTarget、objectMaskTarget boxErrorScale] = generateTargets (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;%计算梯度可学的有关损失。梯度= dlgradient (totalLoss detector.Learnables);结束函数boxLoss = bboxOffsetLoss (boxPredCell boxDeltaTarget、boxMaskTarget boxErrorScaleTarget)%的均方误差边界框的位置。lossX =总和(cellfun (@ (a, b, c, d) mse (a。* c。* d b。* c。* d), boxPredCell (: 1), boxDeltaTarget (: 1), boxMaskTarget (: 1), boxErrorScaleTarget));有损=总和(cellfun (@ (a, b, c, d) mse (a。* c。* d b。* c。* d), boxPredCell (:, 2), boxDeltaTarget (:, 2), boxMaskTarget (: 1), boxErrorScaleTarget));lossW =总和(cellfun (@ (a, b, c, d) mse (a。* c。* d b。* c。* d), boxPredCell (:, 3), boxDeltaTarget (:, 3), boxMaskTarget (: 1), boxErrorScaleTarget));lossH =总和(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 =总和(cellfun (@ (a, b, c) crossentropy (。* c, b。* c,“TargetCategories”,“独立”)、objectnessPredCell objectnessDeltaTarget boxMaskTarget (:, 2)));结束函数clsLoss = classConfidenceLoss (classPredCell classTarget boxMaskTarget)%二进制叉损失类信心得分。clsLoss =总和(cellfun (@ (a, b, c) crossentropy (。* c, b。* c,“TargetCategories”,“独立”)、classPredCell classTarget boxMaskTarget (:, 3)));结束

增加和数据处理功能

函数data = augmentData (A)%应用随机水平翻转,和随机的X / Y缩放。盒子,%比例范围以外剪如果重叠高于0.25。同时,%抖动图像颜色。data =细胞(大小(A));2 = 1:尺寸(1)I = {ii, 1};bboxes = {ii, 2};标签= {ii, 3};深圳=大小(I);如果元素个数(深圳)= = 3 & &深圳(3)= = 3 = jitterColorHSV(我,我“对比”,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);bboxes =圆(bboxes);标签=标签(指标);%返回原始数据只有当所有盒子都被扭曲。如果isempty(指数)数据(ii):) = (ii):);其他的数据(ii):) ={我bboxes标签};结束结束结束函数targetSize data = preprocessData(数据)%改变图像的大小和规模在0和1之间的像素。同时规模%相应的边界框。2 = 1:尺寸数据(数据,1)I = {ii, 1};imgSize =大小(I);%与单通道输入图像转换为3频道。如果元素个数(imgSize) < 3 I = repmat(我,1,1,3);结束bboxes = {ii, 2}数据;我= im2single (imresize(我targetSize (1:2)));规模= targetSize (1:2)。/ imgSize (1:2);bboxes = bboxresize (bboxes、规模);数据(ii, 1:2) ={我bboxes};结束结束函数[XTrain, YTrain] = createBatchData(数据、groundTruthBoxes groundTruthClasses一会)%返回沿着XTrain批尺寸和图片相结合%规范化边框连接YTrain classIDs%连接图像沿批维度。XTrain =猫(4、数据{:1});%获得类id和类名称。一会= repmat({分类(类名)},大小(groundTruthClasses));[~,classIndices] = cellfun (@ (a, b) ismember (a、b), groundTruthClasses,一会,“UniformOutput”、假);%附加标签索引和训练图像尺寸按比例缩小的边界框%和创建一个单一单元阵列的响应。combinedResponses = cellfun (@ (bbox, classid) [bbox, classid], groundTruthBoxes, classIndices,“UniformOutput”、假);len = max (cellfun (@ (x)大小(x, 1), combinedResponses));paddedBBoxes = cellfun (@ (v) padarray (v, [len-size (v, 1), 0], 0,“职位”)、combinedResponses“UniformOutput”、假);YTrain =猫(4,paddedBBoxes {: 1});结束

学习速率调度功能

函数currentLR = piecewiseLearningRateWithWarmup(迭代,时代、learningRate warmupPeriod, numEpochs)% piecewiseLearningRateWithWarmup函数计算电流%学习速率基于迭代数。持续的warmUpEpoch;如果迭代< = warmupPeriod%提高学习速率在预热阶段的迭代次数。currentLR = learningRate *((迭代/ warmupPeriod) ^ 4);warmUpEpoch =时代;elseif迭代> = < warmUpEpoch warmupPeriod & &时代+地板(0.6 * (numEpochs-warmUpEpoch))%在热身期间,保持学习速率常数如果剩余数量的时代还不到60%。currentLR = learningRate;elseif时代> = warmUpEpoch +地板(0.6 * (numEpochs-warmUpEpoch)) & & <时代warmUpEpoch +地板(0.9 * (numEpochs-warmUpEpoch))%如果剩余数量的时代但不超过60%% 90%学习速率乘以0.1。currentLR = learningRate * 0.1;其他的%如果超过90%乘以剩余的时代学习% 0.01。currentLR = learningRate * 0.01;结束结束

效用函数

函数[lossPlotter, learningRatePlotter] = configureTrainingProgressPlotter (f)%创建一个次要情节显示丧失和学习速率。图(f);clf次要情节(2,1,1);ylabel (学习速率的);包含(“迭代”);learningRatePlotter = animatedline;次要情节(2,1,2);ylabel (“全损”);包含(“迭代”);lossPlotter = animatedline;结束函数displayLossInfo(时代、迭代,currentLR lossInfo)%显示损失信息为每个迭代。disp (”时代:“+时代+”|迭代:“+迭代+“|学习速率:“+ currentLR +”|全损:“+双(收集(extractdata (lossInfo.totalLoss))) +“|盒子损失:“+双(收集(extractdata (lossInfo.boxLoss))) +“|对象损失:“+双(收集(extractdata (lossInfo.objLoss))) +“|类损失:“+双(收集(extractdata (lossInfo.clsLoss))));结束函数updatePlots (lossPlotter learningRatePlotter、迭代、currentLR totalLoss)%更新丧失和学习速率的情节。addpoints (lossPlotter、迭代、双(extractdata(收集(totalLoss))));addpoints (learningRatePlotter迭代,currentLR);drawnow结束函数探测器= downloadPretrainedYOLOv3Detector ()%下载pretrained 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;结束

引用

[1]Redmon,约瑟夫和阿里蒂。“YOLOv3:增量改进。“预印本,2018年4月8日提交。https://arxiv.org/abs/1804.02767。

另请参阅

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

相关的话题