主要内容

代码生成量化深度学习网络

深度学习使用神经网络包含许多处理层的体系结构,包括卷积层。深度学习模型通常工作在大的带安全标签的数据集。这些模型训练和执行推理计算密集型,消耗大量的内存。神经网络使用内存来存储输入数据,参数(权重),激活每一层的输入通过网络传播。大多数pretrained神经网络和神经网络训练采用深度学习工具箱™使用单精度浮点数据类型。即使网络小需要大量的内存和硬件来执行这些浮点算术运算。这些限制可以抑制部署深度学习模型的设备计算能力较低,规模较小的内存资源。通过使用低精度存储重量和激活,你可以减少网络的内存需求。

您可以使用深度学习工具箱与深度学习工具箱模型量化库支持包减少内存占用的深层神经网络通过量化权重,偏见,和激活卷积层8位整数数据类型。金宝app然后,您可以使用生成优化的CUDA GPU编码器™®量化网络的代码。生成的代码利用了NVIDIA®CUDA深层神经网络库(cuDNN)或TensorRT™高性能推理库。生成的代码可以集成到你的项目源代码,静态或动态库,或可执行文件,您可以部署到各种各样的NVIDIA GPU平台。

GPU使用量化网络上的图像进行分类

在本例中,您使用GPU编码器生成CUDA代码量子化的卷积神经网络和图像进行分类。这个例子使用了pretrainedsqueezenet(深度学习工具箱)卷积神经网络演示转移学习、量化和CUDA代码生成量化的网络。

SqueezeNet已经在超过一百万个图像和训练可以分类图像到1000年对象类别(如键盘、咖啡杯、铅笔,和许多动物)。网络已经学会丰富广泛的图像特征表示。网络需要一个图像作为输入和输出图像中对象的标签一起为每个对象的类别的概率。

第三方的先决条件

要求

  • CUDA启用NVIDIA GPU®和兼容的驱动程序。

可选

等non-MEX构建静态、动态库或可执行文件,这个例子有以下额外的需求。

将学习使用SqueezeNet

执行一套新的图像分类,你调整一个pretrained SqueezeNet卷积神经网络通过学习转移。在转移学习,你可以把一个pretrained网络和使用它作为一个起点,学习新的任务。微调网络转移学习通常比训练一个网络快得多,也更容易与随机初始化权重从零开始。您可以快速学习功能转移到一个新的任务使用较少的训练图像。

负荷训练数据

解压缩和加载新的图像作为图像数据存储。的imageDatastore函数自动标签图像基于文件夹的名字和存储数据作为ImageDatastore对象。图像数据存储可以存储大量图像数据,包括数据,并不适合在内存中,有效地阅读批图像卷积神经网络在训练。将数据分为训练和验证数据集。使用70%的图片,培训为30%,验证。splitEachLabel分裂的洛桑国际管理发展学院数据存储到两个新的数据存储。

解压缩(“MerchData.zip”);imd = imageDatastore (“MerchData”,“IncludeSubfolders”,真的,“LabelSource”,“foldernames”);[imdsTrain, imdsValidation] = splitEachLabel (imd, 0.7,“随机”);numTrainImages =元素个数(imdsTrain.Labels);idx = randperm (numTrainImages 4);img = imtile (imd,“帧”,idx);图imshow (img)标题(“从训练数据集随机图像”);

负载Pretrained网络

加载pretrained SqueezeNet网络。如果您没有所需的支持包安装,软件提供了一个下载链接。金宝app

网= squeezenet;

的对象包含了DAGNetwork对象。图像输入层,第一层要求输入的图像大小227 - 227 - 3,3是颜色通道的数量。您可以使用analyzeNetwork(深度学习工具箱)函数来显示一个交互式可视化的网络架构,来检测网络中的错误和问题,并显示详细信息网络层。层信息包括层激活的大小和可学的参数,可学的参数的总数,复发性层的状态参数的大小。

inputSize = net.Layers (1) .InputSize;

取代最后一层

网络的卷积层提取图像特征,最后可学的一层一层和最后的分类使用对输入图像进行分类。这两个层,“conv10”“ClassificationLayer_predictions”SqueezeNet,包含的信息如何结合网络特性,提取类概率,损失价值,预测标签。

再培训pretrained网络分类的新图像,用新的替换这两个层层适应新的数据集。你可以手动或使用helper函数findLayersToReplace自动发现这些层。

lgraph = layerGraph(净);[learnableLayer, classLayer] = findLayersToReplace (lgraph);numClasses =元素个数(类别(imdsTrain.Labels));newConvLayer = convolution2dLayer (numClasses [1],“WeightLearnRateFactor”,10日,“BiasLearnRateFactor”10“名称”,“new_conv”);lgraph = replaceLayer (lgraph,“conv10”,newConvLayer);newClassificatonLayer = classificationLayer (“名字”,“new_classoutput”);lgraph = replaceLayer (lgraph,“ClassificationLayer_predictions”,newClassificatonLayer);

列车网络的

网络需要输入的图像大小227 - 227 - 3,但图像的图像数据存储有不同的大小。使用一个增强图像数据存储图像自动调整训练。指定额外增加操作执行培训图片:随机翻转训练图像沿垂直轴,,随便翻译一下30像素水平和垂直。数据增加有助于防止网络过度学习和记忆的训练图像的细节。

pixelRange = 30 [-30];imageAugmenter = imageDataAugmenter (“RandXReflection”,真的,“RandXTranslation”pixelRange,“RandYTranslation”,pixelRange);augimdsTrain = augmentedImageDatastore (inputSize (1:2), imdsTrain,“DataAugmentation”,imageAugmenter);

自动调整验证图像不执行进一步的数据,使用一个增强的图像数据存储不指定任何额外的预处理操作。

augimdsValidation = augmentedImageDatastore (inputSize (1:2), imdsValidation);

指定培训选项。转移学习,防止功能的早期层pretrained网络(传输层的重量)。放慢学习的传输层,设置初始学习速率小值。在前面的步骤中,您的学习速率因素增加卷积层加快学习在新的最后一层。这种组合的学习速率设置导致快速学习只有在新的层和慢学习其他层。当执行转移学习,你不需要训练尽可能多的时代。一个时代是一个完整的培训周期在整个训练数据集。指定mini-batch大小11,这样在每个时代你考虑所有的数据。软件验证网络的每一个ValidationFrequency迭代在训练。

选择= trainingOptions (“个”,“MiniBatchSize”11“MaxEpochs”7“InitialLearnRate”2的军医,“洗牌”,“every-epoch”,“ValidationData”augimdsValidation,“ValidationFrequency”3,“详细”假的,“阴谋”,“训练进步”);

训练网络,包括转移和新层。

netTransfer = trainNetwork (augimdsTrain、lgraph选项);

一会= netTransfer.Layers . class(结束);保存(“mySqueezenet.mat”,“netTransfer”);

数字转换网络

创建一个dlquantizer对象和指定网络数字转换。

quantObj = dlquantizer (netTransfer);

定义一个度量函数使用比较网络量化前后的行为。

类型(“hComputeModelAccuracy.m”);
函数精度= hComputeModelAccuracy (predictionScores,净,数据存储)% % %计算模型级精度统计信息负载地面实况tmp = readall(数据存储);groundTruth = tmp.response;%与预测标签与实际地面实况predictionError = {};idx = 1:元素个数(groundTruth)[~,类似]= max (predictionScores (idx:));yActual = net.Layers(结束). class(补贴);predictionError{结束+ 1}= (yActual = = groundTruth (idx));% #好结束%和所有预测错误。predictionError = [predictionError {}):;精度= (predictionError) /元素个数之和(predictionError);结束

指定的度量函数dlquantizationOptions对象。

quantOpts = dlquantizationOptions (“MetricFcn”,{@ (x) hComputeModelAccuracy (x, netTransfer augimdsValidation)});

使用校准功能锻炼与样本输入网络收集范围信息。的校准功能锻炼的网络和收集动态范围重量和偏见的卷积和完全连接层的网络和动态范围激活所有层的网络。函数返回一个表。表的每一行包含的范围信息可学的参数优化的网络。

calResults =校准(quantObj augimdsTrain);保存(“squeezenetCalResults.mat”,“calResults”);保存(“squeezenetQuantObj.mat”,“quantObj”);

您可以使用验证函数可学的参数进行量化在卷积网络和锻炼网络层。使用度量函数中定义的函数dlquantizationOptions对象比较网络量化前后的结果。

valResults =验证(quantObj augimdsValidation quantOpts);

创建一个入口点函数

在MATLAB编写一个入口点函数:

  • 使用coder.loadDeepLearningNetwork函数加载一个深度学习模型和构造和设置一个CNN类。有关更多信息,请参见负载Pretrained网络代码生成

  • 调用预测函数来预测反应。

类型(“predict_int8.m”);
函数= predict_int8 (netFile)持续mynet;如果isempty (mynet) mynet = coder.loadDeepLearningNetwork (netFile);结束了=预测(mynet);结束

一个持久化对象mynet加载DAGNetwork对象。在第一次调用的入口点函数,构造持久对象和设置。在随后的调用函数,要调用相同的对象被重复使用预测在输入,避免重建并重新加载网络对象。

请注意

确保所有的预处理操作校准和验证步骤包含在设计文件中。

代码生成通过使用codegen

等配置构建设置输出文件名称、位置和类型,您将创建编码器配置对象。创建对象,使用coder.gpuConfig函数。例如,当生成CUDA墨西哥人使用codegen命令,使用cfg = coder.gpuConfig(墨西哥人);

为cuDNN指定代码生成参数,设置DeepLearningConfig属性到一个coder.CuDNNConfig使用您创建的对象coder.DeepLearningConfig

cfg = coder.gpuConfig (墨西哥人的);cfg。TargetLang =“c++”;cfg.GpuConfig。ComputeCapability =“6.1”;cfg。DeepLearningConfig = coder.DeepLearningConfig (“cudnn”);cfg.DeepLearningConfig。自动调谐= true;cfg.DeepLearningConfig。CalibrationResultFile =“squeezenetQuantObj.mat”;cfg.DeepLearningConfig。数据类型=“int8”;

指定的位置MAT-file包含校准数据。

指定精度的推理计算通过使用支持层金宝app数据类型财产。8位整数,使用“int8”。使用ComputeCapability属性的配置对象的代码设置适当的计算能力值。

运行codegen命令。的codegen命令生成CUDA代码的predict_int8.mMATLAB入口点函数。

输入= {coder.Constant (“mySqueezenet.mat”),(inputSize,“uint8”)};codegen配置cfgarg游戏输入predict_int8
代码生成成功。

当代码生成成功,您可以通过单击视图生成的代码生成报告查看报告在MATLAB命令窗口。该报告是在报告中查看器显示窗口。如果在代码生成代码生成器检测错误或警告,这份报告描述了问题和提供有问题的MATLAB代码的链接。

运行生成的墨西哥人

你要分类的图像必须有相同的大小作为输入网络的大小。读到你想要的图片进行分类并调整输入网络的大小。这稍微调整图像的纵横比变化。

testImage = imread (“MerchDataTest.jpg”);testImage = imresize (testImage inputSize (1:2));

叫SqueezeNet预测输入图像。

predictScores(: 1) =预测(netTransfer testImage) ';predictScores (:, 2) = predict_int8_mex (“mySqueezenet.mat”,testImage);

显示标签及其相关预测概率直方图。

h =图;h.Position (3) = 2 * h.Position (3);ax₁=情节(1、2、1);ax2 =情节(1、2、2);图像(ax₁, testImage);barh (ax2 predictScores)包含(ax2,“概率”)yticklabels (ax2一会)ax2。XLim = 1.1 [0];ax2。YAxisLocation =“左”;传奇(“Matlab单”,cuDNN 8位整数的);sgtitle (“使用Squeezenet预测”)

辅助函数

函数[learnableLayer, classLayer] = findLayersToReplace (lgraph)% findLayersToReplace (lgraph)发现单一层和分类%前可学的(完全连接或卷积)层的层lgraph %图。如果~ isa (lgraph“nnet.cnn.LayerGraph”)错误(参数必须是LayerGraph对象。)结束%得到来源、目的地和层的名字。src =字符串(lgraph.Connections.Source);dst =字符串(lgraph.Connections.Destination);layerNames =字符串({lgraph.Layers.Name} ');%找到分类层。必须有一个单独的层图%分类层。isClassificationLayer = arrayfun(@(左)(isa (l,“nnet.cnn.layer.ClassificationOutputLayer”)| isa (l,“nnet.layer.ClassificationLayer”)),lgraph.Layers);如果总和(isClassificationLayer) ~ = 1错误(的一层一层图必须有一个分类。)结束classLayer = lgraph.Layers (isClassificationLayer);%导线层图反过来从分类%层。如果网络分支,抛出一个错误。currentLayerIdx =找到(isClassificationLayer);真正的如果元素个数(currentLayerIdx) ~ = 1味精= [的一层一层图必须有一个可学的“前分类层。”];错误(味精)结束currentLayerType =类(lgraph.Layers (currentLayerIdx));isLearnableLayer = ismember (currentLayerType,(“nnet.cnn.layer.FullyConnectedLayer”,“nnet.cnn.layer.Convolution2DLayer”]);如果isLearnableLayer learnableLayer = lgraph.Layers (currentLayerIdx);返回结束currentDstIdx =找到(layerNames (currentLayerIdx) = = dst);currentLayerIdx =找到(src (currentDstIdx) = = layerNames);结束结束

限制

  • 当执行推理在INT8NVIDIA精密使用cuDNN版本8.1.0、问题库可能会导致显著的性能退化。

  • 以下层不支持8位整数量化时针对NVIDIA CUDA深层神金宝app经网络库(cuDNN)库。

    • leakyReluLayer

    • clippedReluLayer

    • globalAveragePooling2dLayer

另请参阅

应用程序

功能

对象

相关的话题