深度学习

理解和使用深度学习网络

基于深度学习的语义分割

今天我想给你们看一个文档示例这说明了如何使用深度学习和计算机视觉系统工具箱来训练语义分割网络。

语义分割网络对图像中的每个像素进行分类,从而对图像进行分类。语义分割的应用包括用于自动驾驶的道路分割和用于医疗诊断的癌细胞分割。想要了解更多,请看语义分割基础知识

为了说明训练过程,本例训练了用于语义图像分割的卷积神经网络(CNN) SegNet。其他类型的语义分割网络包括完全卷积网络(FCN)和U-Net。这里显示的训练过程也可以应用于这些网络。

此示例使用摄像机数据集这个数据集是一个包含在驾驶时获得的街道级视图的图像的集合。数据集为包括汽车、行人和道路在内的32个语义类提供像素级标签。

安装程序

本例创建了SegNet网络,从VGG-16网络初始化权重。要获得VGG-16,请安装神经网络工具箱™ VGG-16网络模型.安装完成后,运行以下代码来验证安装是否正确。

vgg16();

此外,下载一个预先训练过的赛格网版本。预先训练的模型允许您运行整个示例,而不必等待训练完成。

pretrainedURL =“//www.tatmou.com/金宝appsupportfiles/vision/data/segnetVGG16CamVid.mat”;pretrainedFolder = fullfile (tempdir,“预训练赛格网”);pretrainedSegNet = fullfile (pretrainedFolder,“segnetVGG16CamVid.mat”);如果~exist(预训练文件夹,“dir”)mkdir(预训练文件夹);disp(“下载预训练的SegNet (107 MB)……”);websave (pretrainedSegNet pretrainedURL);终止
下载预训练的SegNet (107 MB)…

强烈建议使用支持cuda的NVIDIA™GPU,且计算能力为3.0或更高。使用GPU需要并行计算工具箱™。

下载CamVid数据集

从以下URL下载CamVid数据集。

图像URL=“http://web4.cs.ucl.ac.uk/staff/g.brostow/MotionSegRecData/files/701_StillsRaw_full.zip”;labelURL ='http://web4.cs.ucl.ac.uk/staff/g.brostow/MotionSegRecData/data/LabeledApproved_full.zip';outputFolder = fullfile (tempdir,“摄像机”);如果~exist(outputFolder,“dir”mkdir(outputFolder) labelsZip = fullfile(outputFolder,“labels.zip”);imagesZip = fullfile (outputFolder,“images.zip”);disp (“下载16mb CamVid数据集标签……”);websave (labelsZip labelURL);解压缩(labelsZip fullfile (outputFolder“标签”)); disp('正在下载557 MB CamVid数据集图像…');websave (imagesZip imageURL);解压缩(imagesZip fullfile (outputFolder“图片”));终止

注意:数据的下载时间取决于您的Internet连接。上面使用的命令将阻止MATLAB,直到下载完成。或者,您可以使用web浏览器先将数据集下载到本地磁盘。若要使用从web下载的文件,请更改 outputFolder变量设置为下载文件的位置。

负载CamVid图片

使用imageDatastore加载摄像机图像。这个 imageDatastore使您能够有效地在磁盘上加载大型映像集合。

imgDir=fullfile(outputFolder,“图片”,701 _stillsraw_full);imd = imageDatastore (imgDir);

显示其中一个图像。

I = readimage (imd, 1);I = histeq(我);imshow(我)

加载CamVid像素标记图像

使用imageDatastore加载CamVid像素标签图像数据。一个 pixelLabelDatastore将像素标签数据和标签ID封装为类名映射。

按照原始SegNet论文(Badrinarayanan、Vijay、Alex Kendall和Roberto Cipolla.“SegNet:用于图像分割的深度卷积编码器-解码器体系结构。”arXiv预印本arXiv:1511.00561201)中使用的程序,将CamVid中的32个原始类分组为11个类。指定这些类。

类别=[“天空”“建筑物”“杆子”“道路”“路面”“树木”“标志符号”“栅栏”“汽车”“行人”“自行车手”];

为了将32个类减少到11个,将来自原始数据集的多个类分组在一起。例如,"Car"是"Car", "SUVPickupTruck", "Truck_Bus", "Train"和"OtherMoving"的组合。使用支持函数返回分组标签id金宝app camvidPixelLabelIDs,在本例末尾列出。

labelIDs=camvidPixelLabelIDs();

使用类和标签id来创建 像素标签数据库。

labelDir = fullfile (outputFolder,“标签”);pxds = pixelLabelDatastore (labelDir、类labelIDs);

读取和显示其中一个像素标记的图像,将其覆盖在图像的顶部。

C=读取图像(pxds,1);cmap=camvidColorMap;B=labeloverlay(I,C,“彩色地图”,提出);imshow (B) pixelLabelColorbar(提出、类);

没有颜色覆盖的区域没有像素标签,也不会在训练期间使用。

统计分析数据集

要查看CamVid数据集中类标签的分布,请使用countEachLabel. 此函数按类别标签统计像素数。

tbl=计数标签(pxds)
tbl=11×3表名称PixelCount ImagePixelCount ____________ __________ _______________ 'Sky' 76801167 483148800 'Building' 117373718 483148800 'Pole' 4798742 483148800 'Road' 140535728 484531200 'Pavement'树' 54258673 472089600 'SignSymbol' 5224247 468633600 'Fence' 6921061 251596800 'Car' 24436957 483148800 '行人' 3402909 444441600“骑自行车”2591222 261964800

按类可视化像素计数。

频率= tbl.PixelCount /笔(tbl.PixelCount);bar(1:numel(classes),frequency) xticks(1:numel(classes)) xticklabels(tbl.Name) xtickangle(45) ylabel(“频率”)

理想情况下,所有类别的观测值都是相等的。但是,CamVid中的类别是不平衡的,这是街道场景汽车数据集中的一个常见问题。此类场景的天空、建筑物和道路像素比行人和骑自行车的像素多,因为天空、建筑物和道路在图像中覆盖的面积更大。如果不进行处理,则显然,这种不平衡可能对学习过程有害,因为学习偏向于主导类。在本例后面,您将使用类权重来处理此问题。

调整CamVid数据

CamVid数据集中的图像为720 × 960。为了减少训练时间和内存使用,将图像和像素标签图像的大小调整为360 * 480。 resizeCamVidImages 调整摄像机像素标签的大小是本例末金宝app尾列出的支持函数。

imageFolder = fullfile (outputFolder,“imagesResized”, filesep);imd = resizeCamVidImages (imd, imageFolder);labelFolder = fullfile (outputFolder,“labelsResized”, filesep);pxds = resizeCamVidPixelLabels (pxds labelFolder);

准备培训和测试集

使用数据集中60%的图像对SegNet进行训练。其余的图像用于测试。下面的代码将图像和像素标签数据随机分割为训练集和测试集。

[imdsTrain, imdsTest pxdsTrain pxdsTest] = partitionCamVidData (imd, pxds);

60/40的分割结果为如下数量的训练和测试图像:

numTrainingImages=numel(imdsTrain.Files)
numTrainingImages=421
numTestingImages =元素个数(imdsTest.Files)
numTestingImages=280

创建网络

使用segnetLayers创建一个使用VGG-16权重初始化的SegNet网络。 segnetLayers自动执行从VGG-16转移权重所需的网络手术,并添加语义分割所需的额外层。

imageSize=[360 480 3];numClasses=numel(类);lgraph=segnetLayers(imageSize,numClasses,“vgg16”);

图像大小是根据数据集中图像的大小来选择的。根据CamVid中的类选择类数。

使用类权重平衡类

如前面所示,CamVid中的类是不平衡的。为了提高训练,你可以使用课程权重来平衡课程。使用前面计算的像素标签计数countEachLayer并计算中值频率类权重。

imageFreq =(资源。PixelCount。/ tbl.ImagePixelCount;classWeights = median(imageFreq) ./ imageFreq ./ imageFreq ./ imageFreq ./
类权重=11×10.318184709354742 0.208197860785155 5.092367332938507 0.174381825257403 0.710338097812948 0.417518560687874 4.537074815482926 1.838648261914560 1.000000000000000 6.605878573155874⋮

属性指定类权重像素分类层

pxLayer = pixelClassificationLayer (“姓名”,“标签”,“类名”资源描述。的名字,“ClassWeights”,类重量)
pxLayer=PixelClassificationLayer,属性:名称:'labels'类名:{11×1 cell}类权重:[11×1 double]OutputSize:'auto'超参数丢失函数:'crossentropyex'

更新SegNet网络与新的 像素分类层通过消除电流 像素分类层然后添加新图层。当前的 像素分类层被命名为“pixelLabels”。删除它使用搬运工,添加一个新的使用addLayers,并将新层连接到网络的其余部分connectLayers

lgraph=拆除层(lgraph,“pixelLabels”);lgraph = addLayers(lgraph, pxLayer);lgraph = connectLayers (lgraph,“softmax”,“标签”);

选择培训选项

用于训练的优化算法是带动量的随机梯度下降(SGDM)。使用trainingOptions来指定用于SGDM的超参数。

选择= trainingOptions (“sgdm”,...“动量”, 0.9,...“InitialLearnRate”1 e - 3,...“L2规范化”,0.0005,...“MaxEpochs”,100,...“MiniBatchSize”4...“洗牌”,“every-epoch”,...“VerboseFrequency”2);

小批量大小4用于减少培训时的内存使用。您可以根据系统上的GPU内存量增加或减少此值。

数据扩充

在训练过程中使用数据增强,为网络提供更多的例子,有助于提高网络的准确性。这里,随机左/右反射和随机X/Y平移+/- 10像素用于数据增强。

增量= imageDataAugmenter (“RandXReflection”,真的,...“随机翻译”-10年[10],“RandYTranslation”, -10年[10]);

图像数据增强器金宝app支持其他几种类型的数据扩充。其中的选择需要经验分析,是另一层次的超参数调优。

开始训练

结合训练数据和数据增强选择使用像素标签图像数据存储.的 像素标签图像数据存储读取成批的训练数据,应用数据增强,并将增强后的数据发送到训练算法中。

pximds=像素标签图像数据存储(imdsTrain,pxdsTrain,...“数据增强”增强器);

开始训练,如果 溺爱国旗是正确的。否则,加载预训练的网络。注意:在NVIDIA™Titan X上的培训大约需要5个小时,根据你的GPU硬件可能需要更长的时间。

doTraining = false;如果doTraining[net,info]=列车网络(pximds,lgraph,选项);其他的数据=负载(预训练SEGNET);网络=数据.net;终止

在一个图像上测试网络

作为快速的健全性检查,在一个测试映像上运行经过培训的网络。

我=读(imdsTest);C = semanticseg(I, net);

显示结果。

我= labeloverlay (C“彩色地图”,cmap,“透明”, 0.4);imshow (B) pixelLabelColorbar(提出、类);

比较 C与预期的地面真理 pxdsTest.绿色和品红区域突出了分割结果与预期地面真实值不同的区域。

expectedResult =阅读(pxdsTest);实际= uint8 (C);预期= uint8 (expectedResult);预计imshowpair(实际)

视觉上,对于道路、天空和建筑等类别,语义分割结果重叠良好。但是,行人和汽车等较小的对象则不那么准确。每个类别的重叠量可以使用联合交叉点(IoU)度量,也称为Jaccard索引。使用jaccard功能来衡量欠条。

iou = jaccard(C, expectedResult);表(类、借据)
ans=11×2表class iou ____________ __________________“Sky”0.926585343977038“Building”0.798698991022729“Pole”0.169776501947919“Road”0.951766120547122“Pavement”0.418766821629557“Tree”0.434014251781273“SignSymbol”0.325092056812204“Fence”0.49200469780468“Car”0.0687557042896258“行人”0“自行车”0

IoU指标证实了可视结果。道路、天空和建筑类的欠条分数较高,而行人和汽车等类的欠条分数较低。其他常见的细分指标包括骰子索引Boundary-F1轮廓匹配分数。

评估培训网络

要测量多个测试图像的准确性,请运行语义词组在整个测试集上。

pxdsResults=semanticseg(imdsTest,net,“MiniBatchSize”4“写位置”tempdir,“冗长”、假);

语义词组将测试集的结果返回为 pixelLabelDatastore对象。中的每个测试图像的实际像素标签数据 imdsTest将写入磁盘中由指定的位置 “写位置”参数。使用评价语义切分度量测试集结果上的语义分割度量。

指标= evaluateSemanticSegmentation (pxdsResults pxdsTest,“冗长”、假);

评价语义切分为整个数据集、单个类和每个测试映像返回各种指标。要查看数据集级别度量,请检查 指标。DataSetMetrics

指标。DataSetMetrics
ans=1×5表GlobalAccuracy MeanAccuracy MeanIoU WeightedIoU MeanBFScore  _________________ _________________ _________________ _________________ ________________ 0.882035049405331 0.850970241394654 0.608927281006314 0.797947090677593 0.60980715338674

数据集指标提供了网络性能的高级概述。要查看每个类对整体性能的影响,请检查使用的每个类度量 指标。ClassMetrics

指标。ClassMetrics
ans=11×3表“精度”是指一种分数的精度,精度是指指一种分数的精度,精度是指一种分数的精度,精度是指一种分数的精度,精度是指一个分数的精度,精度是指一个分数的精度,精度是指一个分数的精度,精度是指一个分数的精度,精度是指一个精度精度,精度是指一个分数分数的精度精度精度精度,精度是精度是指一个分数分数分数的精度精度精度,精度是指指指一个分数的精度,精度是精度是指指一个分数分数的精度,精度是一一一个分数的精度是一个分数的精度是一个分数的精度,精度是分数,精度是指指一个分数分数的精度是一个分数分数的精度是一个分数的精度,而精度是一个分数的精度,精度是分数的精度是指指指指一个分数的精度,精度是一个分数的精度,精度精度是一个分数分数的精度,精度是分数的精度是是是一个分数的精度2519568793497道路0.936763259117679 0.906720411900943 0.710433513101952路面0.9067407725591680.728650096831083 0.703619961786386树0.866574402823008 0.73746833451386 0.664211092196979标志符号0.755895966085333 0.345193190798607 0.434011059025598篱笆0.8280689896379 0.5059259289568 0.50829520978596汽车0.911873566421394 0.75001230335288 0.6424410899步行者0.8486631376790.3504675899自行车手459490.847049655538425 0.542083155989493 0.468181589716695

尽管总体数据集性能相当高,但类指标显示,像 行人, 骑自行车的,不像班级那样细分吗, 天空, 建筑物.包含更多代表性不足班级的样本的额外数据可能有助于改善结果。

金宝app支持功能

函数labelIDs = camvidPixelLabelIDs ()返回每个类对应的标签id。%%CamVid数据集有32个类。将它们分为以下11个类%原赛格网培训方法[1]。%%这11个类是:%的“天空”“建筑”,“极”,“路”,“路面”、“树”、“SignSymbol”,%“围栏”、“汽车”、“行人”和“自行车手”。%%CamVid像素标签ID作为RGB颜色值提供。将它们分组为%11个类,并将它们作为M-x-3矩阵的单元数组返回%原始CamVid类名与每个RGB值一起列出。笔记%表示Other/Void类被排除在下面。labelIDs = {...%“天空”[ 128 128 128;...%“天空”]%“建设”[000 128 064;...%“桥”128 000 000;...%“建设”064 192 000;...%的“墙”064 000 064;...%“隧道”192 000 128;...%“拱门”]%“极”[19219128;...%“立柱”000 000 064;...%”TrafficCone”]%道路[128 064 128;...%的“路”128 000 192;...%”LaneMkgsDriv”192 000 064;...%”LaneMkgsNonDriv”]%“路面”[ 000 000 192;...%“人行道”064 192 128;...%”ParkingBlock”128 128 192;...%“路肩”]%“树”[ 128 128 000;...%“树”192 192 000;...%“植被杂项”]%“符号”[ 192 128 128;...%“符号”128 128 064;...%“杂项文本”000 064 064;...%“交通灯”]%“栅栏”[064 064 128;...%“栅栏”]%的“汽车”[064 000 128;...%的“汽车”064 128 192;...%“SUVPickupTruck”192 128 192;...%”Truck_Bus”192 064 128;...%“火车”128 064 064;...%”OtherMoving”]%“行人”[064 064 000;...%“行人”192 128 064;...%“孩子”064 000 192;...%”CartLuggagePram”064 128 064;...%的“动物”]%“骑自行车的”[000 128 192;...%“骑自行车的”192 000 192;...%”MotorcycleScooter”]};终止函数一会pixelLabelColorbar(提出)%将颜色条添加到当前轴。颜色条已格式化%使用颜色显示类名。甘氨胆酸colormap(提出)%添加颜色栏到当前的数字。c=色条(“对等”甘氨胆酸,);%使用类名作为标记。c.TickLabels =一会;numClasses =大小(提出,1);%居中标记标签。c.Ticks = 1 / (numClasses * 2): 1 / numClasses: 1;%删除勾号。c、 长度=0;终止函数提出= camvidColorMap ()%定义CamVid数据集使用的颜色映射。Cmap = [128 128 128 .%天空128 0 0%的建筑192 192 192%极128 64 128%道路60 40 222%铺路128 128 0%的树192 128 128%符号64 64 128%的栅栏64 0 128%汽车64 64 0%行人0 128 192%骑自行车的];%在[0]和[1]之间进行规格化。Cmap = Cmap ./ 255;终止函数imds=调整大小的摄像机图像(imds,图像文件夹)%调整图像大小为[360 480]。如果~存在(imageFolder“dir”)mkdir(图像文件夹)其他的imd = imageDatastore (imageFolder);返回如果图像已经调整大小,则跳过终止重置(imds)hasdata(imds)%阅读图像。[I,info]=读取(imds);%调整图像大小。I=imresize(I[360 480]);%写入磁盘。[~,filename,ext]=fileparts(info.filename);imwrite(I,[imagefolderfilename ext])终止imd = imageDatastore (imageFolder);终止函数pxds=调整大小的摄像机像素标签(pxds,标签文件夹)%调整像素标签数据的大小为[360 480]。类= pxds.ClassNames;labelIDs = 1:元素个数(类);如果~存在(labelFolder“dir”mkdir (labelFolder)其他的pxds=像素标签数据存储(标签文件夹、类、标签ID);返回如果图像已经调整大小,则跳过终止重置(pxds)hasdata (pxds)%读取像素数据。[C,info]=读取(pxds);%转换从分类到uint8。L = uint8 (C);%调整数据大小。使用“最接近的”插值%保留标签id。L=imresize(L,[360 480],“最近的”);%将数据写入磁盘。[~, filename, ext] = fileparts(info.Filename);imwrite (L, [labelFolder文件名ext])终止labelIDs = 1:元素个数(类);pxds=像素标签数据存储(标签文件夹、类、标签ID);终止函数[imdsTrain,imdsTest,pxdsTrain,pxdsTest]=分区摄像机数据(imds,pxds)%对CamVid数据进行分区,随机选取60%的数据进行训练。的%rest用于测试。%设置初始随机状态,例如再现性。rng(0);numFiles=numel(imds.Files);shuffleddinces=randperm(numFiles);%使用60%的图像进行训练。N = round(0.60 * numFiles);trainingIdx = shuffledIndices (1: N);%其余的用于测试。testIdx = shuffledIndices (N + 1:结束);%创建用于培训和测试的图像数据存储。trainingImages = imds.Files (trainingIdx);testImages = imds.Files (testIdx);imdsTrain = imageDatastore (trainingImages);imdsTest = imageDatastore (testImages);%提取类和标签id信息。classes=pxds.ClassNames;labelIDs=1:numel(pxds.ClassNames);%创建用于培训和测试的像素标签数据存储。trainingLabels = pxds.Files (trainingIdx);testLabels = pxds.Files (testIdx);pxdsTrain = pixelLabelDatastore(trainingLabels, classes, labelid);pxdsTest = pixelLabelDatastore(testLabels, classes, labelid);终止
|
  • 打印
  • 发送电子邮件

评论

如需留言,请点击在这里登录到您的MathWorks帐户或创建新帐户。