利用NVIDIA-NGC中的MATLAB容器加速语义分割
利用NVIDIA-NGC中的MATLAB容器加速语义分割
Speeding Up Semantic Segmentation Using MATLAB Container from NVIDIA NGC
使用单一GPU训练深度学习模式的时代已经一去不复返了。对于计算密集型算法(如语义分割),单个GPU可能需要几天时间来优化模型。但多GPU硬件很贵。不会再有了;NVIDIA的云上多GPU硬件实例,比如AWS P3,只允许你支付你使用的东西。云实例允许您利用支持Tensor核心的最新一代硬件,以适度的投资实现显著的性能引导。您可能听说过设置云实例很困难,但NVIDIA NGC使生活变得更轻松。NGC是用于深度学习、机器学习和HPC的GPU优化软件的中心。NGC负责所有的管道,因此开发人员和数据科学家可以专注于生成可操作的见解。
这篇文章通过在云实例上使用NVIDIA GPUs和从NGC获得的用于深入学习的MATLAB容器,走过了加速语义分割的最简单路径。首先,我们将解释语义分割。接下来,我们将使用NGC提供的MATLAB R2018b容器在两个不同的P3实例上展示在MATLAB中训练的语义分割模型的性能结果。最后,我们将在MATLAB中介绍一些技巧,这些技巧使深入学习变得容易,并有助于管理内存使用。
What is Semantic Segmentation?
用于深度学习的语义分割算法为图像中的每个像素分配一个标签或类别。与传统的包围盒方法相比,这种密集的识别方法在某些应用中提供了关键的能力。在自动驾驶中,它是标记为“道路”的广义区域与精确的、像素级的确定道路可行驶表面之间的区别。在医学成像中,它意味着将矩形区域标记为“癌细胞”与知道细胞的确切形状和大小之间的区别。

Figure 1. Example of an image with semantic labels for every pixel
我们使用MATLAB对语义分割进行了测试,训练出一个SegNet模型,该模型具有四个编码层和四个解码层的编解码结构。与该模型相关的数据集是CamVid数据集,它是一个驱动数据集,每个像素都用一个语义类(例如天空、道路、车辆等)标记。与原研究不同的是,我们使用随机梯度下降法进行训练,并对预先训练的VGG-16模型的层和权重进行了预初始化。
Performance Testing Using MATLAB on P3 Instances with NVIDIA GPUs
虽然语义分割是有效的,但它需要付出巨大的计算和内存代价。我们使用AWS P3实例和NGC提供的MATLAB容器运行测试。使用容器需要一个AWS帐户和一个有效的MATLAB许可证。您可以获得免费的云使用的试用版MATLAB许可证。Mathworks提供了如何在AWS上设置MATLAB容器的可用说明。
最初的SegNet在2015年的实现花费了大约一周的时间运行在作者使用的Tesla K40上,正如在最初的论文中提到的。下面是在一个p3.2xlarge实例上使用一个V100 NVIDIA GPU在MATLAB中进行语义分割网络训练的过程图。图2显示了它花费了大约121分钟,这比原来的论文要快得多。

接下来,我们使用p3.16xlarge实例上可用的八个V100 NVIDIA gpu执行相同的测试。MATLAB代码中唯一需要更改的是:将训练选项参数ExecutionEnvironment设置为multi-gpu。图3展示了一个训练图,显示这个过程现在花费了37分钟,比使用p3.2xlarge实例快3.25倍。

Figure 3. Training Progress for SegNet in MATLAB on eight V100 NVIDIA GPUs
性能提升了3.25倍,显示了最新的NVIDIA多GPU硬件的强大功能,并带有Tensor内核,使原本“大约一周”的时间缩短至37分钟。我敢打赌,SegNet的作者们在开发算法的时候,一定希望有这样的硬件!
Making Deep Learning Easier with MATLAB
现在让我们深入探讨为什么应该使用MATLAB开发深层学习算法,如语义分割。MATLAB包含许多有用的工具和命令,以便于执行深入学习。最有用的MATLAB命令之一是imageDatastore,它允许您有效地管理大量图像。该命令创建一个数据库,允许将整个数据集作为单个对象处理。MiniBatchSize参数对于语义分割尤其重要,它决定了每次迭代使用多少图像。默认值256会占用太多内存进行语义分割,因此我们将该值设置为4。
如imageDataAugmenter函数所示,数据增强代表了MATLAB中另一种强大的深度学习能力。数据扩充通过使用翻译、旋转、反射、缩放、裁剪等向网络提供更多示例来扩展数据集。这有助于提高模型精度。这使用随机左/右反射的数据增强和正负10像素的X/Y转换。这种数据扩充被合并到一个pixelLabelDatastore中,这样每次迭代时操作都会发生,并且避免了不必要的数据集副本。
How We Performed Semantic Segmentation in MATLAB
本节介绍了我们用于上述测试的代码的关键部分。本测试中使用的完整的MATLAB代码在这里提供。最后一行是训练的地方。
以下代码下载数据集并在本地计算机上解压它。
imageURL = '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,'CamVid');
if ~exist(outputFolder, 'dir')
mkdir(outputFolder)
labelsZip = fullfile(outputFolder,'labels.zip');
imagesZip = fullfile(outputFolder,'images.zip');
disp('Downloading 16 MB CamVid dataset labels...');
websave(labelsZip, labelURL);
unzip(labelsZip, fullfile(outputFolder,'labels'));
disp('Downloading 557 MB CamVid dataset images...');
websave(imagesZip, imageURL);
unzip(imagesZip, fullfile(outputFolder,'images'));
end
此代码生成一个临时文件夹,用于解压缩实例上的文件。使用容器时,一旦容器关闭,这些文件将丢失。如果您想为数据维护一个一致的位置,您应该将代码更改为使用S3存储桶或其他永久位置。
下面的代码显示了用于训练语义分割网络的来自CamVid数据集的11个类。在原始数据集中,有32个类。
imgDir = fullfile(outputFolder,'images','701_StillsRaw_full');
imds = imageDatastore(imgDir);
classes = [
"Sky"
"Building"
"Pole"
"Road"
"Pavement"
"Tree"
"SignSymbol"
"Fence"
"Car"
"Pedestrian"
"Bicyclist"
];
labelIDs = camvidPixelLabelIDs();
labelDir = fullfile(outputFolder,'labels');
pxds = pixelLabelDatastore(labelDir,classes,labelIDs);
在下一节中,我们将根据SegNet的分辨率调整CamVid数据的大小,并将数据集划分为训练集和测试集。
imageFolder = fullfile(outputFolder,'imagesResized',filesep);
imds = resizeCamVidImages(imds,imageFolder);
labelFolder = fullfile(outputFolder,'labelsResized',filesep);
pxds = resizeCamVidPixelLabels(pxds,labelFolder);
[imdsTrain,imdsTest,pxdsTrain,pxdsTest] = partitionCamVidData(imds,pxds);
numTrainingImages = numel(imdsTrain.Files)
numTestingImages = numel(imdsTest.Files)
现在让我们创建一个SegNet网络。从VGG-16权重开始,调整它们以平衡类权重。
imageSize = [360 480 3];
numClasses = numel(classes);
lgraph = segnetLayers(imageSize,numClasses,'vgg16');
imageFreq = tbl.PixelCount ./ tbl.ImagePixelCount;
classWeights = median(imageFreq) ./ imageFreq;
pxLayer = pixelClassificationLayer('Name','labels','ClassNames',tbl.Name,'ClassWeights',classWeights);
lgraph = removeLayers(lgraph,'pixelLabels');
lgraph = addLayers(lgraph, pxLayer);
lgraph = connectLayers(lgraph,'softmax','labels');
接下来,选择培训选项。MiniBatchSize参数对于语义分割尤其重要,它决定了每次迭代使用多少图像。默认值256需要太多内存用于语义分段,因此我们将该值设置为4。ExecutionEnvironment选项设置为multi-gpu以使用p3.16xlarge实例上的多个V100 NVIDIA gpu。有关培训选项的更多详细信息,请参阅文档。
options = trainingOptions('sgdm', ...
'Momentum',0.9, ...
'ExecutionEnvironment','multi-gpu',...
'InitialLearnRate',1e-3, ...
'L2Regularization',0.0005, ...
'MaxEpochs',100, ...
'MiniBatchSize',4 * gpuDeviceCount, ...
'Shuffle','every-epoch', ...
'Plots','training-progress',...
'VerboseFrequency',2);
MATLAB中用于深度学习的另一个强大功能是imageDataAugmenter,它为网络提供了更多示例,有助于提高精度。此示例使用随机左/右反射的数据增强和正负10像素的X/Y转换。这将合并到一个pixelLabelDatastore中,以便在每次迭代时执行操作,并避免不必要的数据集副本。
augmenter = imageDataAugmenter('RandXReflection',true,...
'RandXTranslation',[-10 10],'RandYTranslation',[-10 10]);
pximds = pixelLabelImageDatastore(imdsTrain,pxdsTrain,...
'DataAugmentation',augmenter);
现在我们可以开始训练了。下一行用于训练的代码在p3.16xlarge实例上运行大约需要37分钟。我们在绘图窗口中测量训练所用的时间,以跟踪训练进度。请参阅图2和图3,查看在p3.2xlarge和p3.16xlarge实例上运行此函数所需的测量时间。
[net, info] = trainNetwork(pximds,lgraph,options);
结论
MATLAB使工程师能够很容易地训练深度学习模型,利用NVIDIA GPU加速训练过程。使用MATLAB,从单一GPU机器上的训练切换到多GPU机器只需要一行代码,如上面最后的代码片段所示。我们展示了如何通过在NGC上的MATLAB深度学习容器中训练神经网络来加速深度学习应用程序,该容器旨在充分利用高性能NVIDIAGPU。下一步,下载代码并在MATLAB中的awsp3实例上亲自尝试。
利用NVIDIA-NGC中的MATLAB容器加速语义分割的更多相关文章
- 利用NVIDIA NGC的TensorRT容器优化和加速人工智能推理
利用NVIDIA NGC的TensorRT容器优化和加速人工智能推理 Optimizing and Accelerating AI Inference with the TensorRT Contai ...
- Amazon SageMaker和NVIDIA NGC加速AI和ML工作流
Amazon SageMaker和NVIDIA NGC加速AI和ML工作流 从自动驾驶汽车到药物发现,人工智能正成为主流,并迅速渗透到每个行业.但是,开发和部署AI应用程序是一项具有挑战性的工作.该过 ...
- 用NVIDIA Tensor Cores和TensorFlow 2加速医学图像分割
用NVIDIA Tensor Cores和TensorFlow 2加速医学图像分割 Accelerating Medical Image Segmentation with NVIDIA Tensor ...
- 利用UltraScale和UltraScale+FPGA和MPSOC加速DSP设计生产力
利用UltraScale和UltraScale+FPGA和MPSOC加速DSP设计生产力 Accelerating DSP Design Productivity with UltraScale an ...
- C++ STL中的常用容器浅谈
STL是C/C++开发中一个非常重要的模板,而其中定义的各种容器也是非常方便我们大家使用.下面,我们就浅谈某些常用的容器.这里我们不涉及容器的基本操作之类,只是要讨论一下各个容器其各自的特点.STL中 ...
- Spring——Web应用中的IoC容器创建(WebApplicationContext根应用上下文的创建过程)
基于Spring-4.3.7.RELEASE Spring的配置不仅仅局限在XML文件,同样也可以使用Java代码来配置.在这里我使用XML配置文件的方式来粗略地讲讲WebApplicationCon ...
- c#中的Unity容器
DIP是依赖倒置原则:一种软件架构设计的原则(抽象概念).依赖于抽象不依赖于细节 IOC即为控制反转(Inversion of Control):传统开发,上端依赖(调用/指定)下端对象,会有依赖,把 ...
- 教你如何修改运行中的docker容器的端口映射
在docker run创建并运行容器的时候,可以通过-p指定端口映射规则.但是,我们经常会遇到刚开始忘记设置端口映射或者设置错了需要修改.当docker start运行容器后并没有提供一个-p选项或设 ...
- 深入解析C++ STL中的常用容器
转载:http://blog.csdn.net/u013443618/article/details/49964299 这里我们不涉及容器的基本操作之类,只是要讨论一下各个容器其各自的特点.STL中的 ...
随机推荐
- hdu3460 字典树(打印机)
题意: 给你一些名字,让你用一台打印机去打印这些名字,打印机只有三个操作 (1)打印的都是小写字母 (2)每次可以在当前字母的后面加一位,或删除一位. (3)打印当前串 问你最少多少步可 ...
- hdu4662 简单搜索打表
题意: 给你一个初始串"MI",这个串有三种操作, (1)M后卖弄可以直接复制 ,MI -> MII (2)三个III可以变成一个U,MUIII -> MUU ...
- C++扫雷小游戏(基于CMD命令行)
这个小游戏是笔者在大一C语言课程设计的时候写的,基于命令行,为了显得漂亮一些,特别加上了彩色特效~~~ 注意:Win10系统须将命令行调为旧版命令行,否则有可能会显示乱码! 代码示例: #includ ...
- 16.PHP_Ajax模拟服务器登录验证
Ajax模拟登陆验证 index.php <script language="javascript"> var http_request = false; ...
- (Py练习)判断101-200之间的素数个数并输出
判断素数的方法之一:用一个数分别去除以2到squrt(这个数),如果能被整除,则不是素数. import math h = 0 leap = 1 for m in range(101, 201): k ...
- 浅谈持续集成(CI)、持续交付(CD)、持续部署(CD)
CI/CD是实现敏捷和Devops理念的一种方法,具体而言,CI/CD 可让持续自动化和持续监控贯穿于应用的 整个生命周期(从集成和测试阶段,到交付和部署).这些关联的事务通常被统称为"CI ...
- 异常检测算法Robust Random Cut Forest(RRCF)关键定理引理证明
摘要:RRCF是亚马逊发表的一篇异常检测算法,是对周志华孤立森林的改进.但是相比孤立森林,具有更为扎实的理论基础.文章的理论论证相对较为晦涩,且没给出详细的证明过程.本文不对该算法进行详尽的描述,仅对 ...
- (数据科学学习手札121)Python+Dash快速web应用开发——项目结构篇
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- 分布式锁为什么要选择Zookeeper而不是Redis?
在分布式的应用中,为了防止单点故障,保障高可用,通常会采用主从结构,当主节点挂掉后,从节点可以代替主节点提供服务. Redis通过复制 + sentinel哨兵来实现主从模式. Zookeeper通过 ...
- [MySQL数据库之Navicat.pymysql模块、视图、触发器、存储过程、函数、流程控制]
[MySQL数据库之Navicat.pymysql模块.视图.触发器.存储过程.函数.流程控制] Navicat Navicat是一套快速.可靠并价格相当便宜的数据库管理工具,专为简化数据库的管理及降 ...