利用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容器加速语义分割的更多相关文章

  1. 利用NVIDIA NGC的TensorRT容器优化和加速人工智能推理

    利用NVIDIA NGC的TensorRT容器优化和加速人工智能推理 Optimizing and Accelerating AI Inference with the TensorRT Contai ...

  2. Amazon SageMaker和NVIDIA NGC加速AI和ML工作流

    Amazon SageMaker和NVIDIA NGC加速AI和ML工作流 从自动驾驶汽车到药物发现,人工智能正成为主流,并迅速渗透到每个行业.但是,开发和部署AI应用程序是一项具有挑战性的工作.该过 ...

  3. 用NVIDIA Tensor Cores和TensorFlow 2加速医学图像分割

    用NVIDIA Tensor Cores和TensorFlow 2加速医学图像分割 Accelerating Medical Image Segmentation with NVIDIA Tensor ...

  4. 利用UltraScale和UltraScale+FPGA和MPSOC加速DSP设计生产力

    利用UltraScale和UltraScale+FPGA和MPSOC加速DSP设计生产力 Accelerating DSP Design Productivity with UltraScale an ...

  5. C++ STL中的常用容器浅谈

    STL是C/C++开发中一个非常重要的模板,而其中定义的各种容器也是非常方便我们大家使用.下面,我们就浅谈某些常用的容器.这里我们不涉及容器的基本操作之类,只是要讨论一下各个容器其各自的特点.STL中 ...

  6. Spring——Web应用中的IoC容器创建(WebApplicationContext根应用上下文的创建过程)

    基于Spring-4.3.7.RELEASE Spring的配置不仅仅局限在XML文件,同样也可以使用Java代码来配置.在这里我使用XML配置文件的方式来粗略地讲讲WebApplicationCon ...

  7. c#中的Unity容器

    DIP是依赖倒置原则:一种软件架构设计的原则(抽象概念).依赖于抽象不依赖于细节 IOC即为控制反转(Inversion of Control):传统开发,上端依赖(调用/指定)下端对象,会有依赖,把 ...

  8. 教你如何修改运行中的docker容器的端口映射

    在docker run创建并运行容器的时候,可以通过-p指定端口映射规则.但是,我们经常会遇到刚开始忘记设置端口映射或者设置错了需要修改.当docker start运行容器后并没有提供一个-p选项或设 ...

  9. 深入解析C++ STL中的常用容器

    转载:http://blog.csdn.net/u013443618/article/details/49964299 这里我们不涉及容器的基本操作之类,只是要讨论一下各个容器其各自的特点.STL中的 ...

随机推荐

  1. 本地使用apache设置绑定多个域名

    Apache开启了使用虚拟主机的功能: 打开Apache安装目录下conf/httpd.conf文件,找到 #LoadModule vhost_alias_module modules/mod_vho ...

  2. hdu2363 枚举最短路

    (1) 二分     把所有的高度都拿过来,组合起来,sort一遍,然后二分,找到能连通的最小的那个,但这里存在一起情况,就是遇到高度差相等的时候会bug.... (2) 枚举 连通直接break   ...

  3. hdu4020简单想法题

    题意:       给你一些人,这些人有很多广告,每个广告有自己的点击率和长度,每次有m组询问,问每个人点击率前K名的广告的总长度是多少. 思路:       数据很大,很容易超时,总的想法还是先so ...

  4. UVA11039

    题意:      给你一个序列,由n个数字组成,每个数字的绝对值都不相同,然后让你从这n个数中拿出一些数,组成一个绝对值递增并且正负交替的最大序列,问组成的最大序列的最大长度是多少? 思路:     ...

  5. android添加账户源码浅析

    上篇粗略的分析android添加账号的流程,本篇深入的解析下执行步骤.先来看图片,取自深入理解android卷2: 上图详细的分析了addAccount的流程,下面我们结合源码来理解它 1.addAc ...

  6. R3获取kernel32地址

    获取Kernel32地址 如果是搞PE变形或者PE重构,再或者代码注入,很多时候我们要动态获取Loadlibrary()以及GetPeocAddress()两个函数的地址,通过这两个函数再动态获取其他 ...

  7. React-状态提升

    通常,多个组件需要反映相同的变化数据,这时建议将共享状态提升到最近的共同父组件中去. <!DOCTYPE html> <html> <head> <meta ...

  8. 密码学系列之:memory-hard函数

    密码学系列之:memory-hard函数 目录 简介 为什么需要MHF Memory hard的评估方法 MHF的种类 MHF的密码学意义 memory-hard在MHF中的应用 简介 Memory ...

  9. CentOS8.2集成的megaraid_sas版本不支持IBM X3850 X5内置RAID卡。需要更新https://docs.broadcom.com/docs/MR_LINUX_DRIVER_7.15-07.715.02.00-1-PUL.tgz

    CentOS8.2集成的megaraid_sas版本不支持IBM X3850 X5内置RAID卡.需要更新https://docs.broadcom.com/docs/MR_LINUX_DRIVER_ ...

  10. Java 常见转义字符

    什么是转义符 计算机某些特殊字符是无法直接用字符表示,可以通过转义符 ( \ ) 的方式表示,也就是将原字符的含义转为其他含义. 比如,如果想要输出一个单引号,你可能会想到 char letter = ...