Main Content

本页翻译不是最新的。点击此处可查看最新英文版本。

深度学习网络的代码生成

此示例说明如何为使用深度学习的图像分类应用程序执行代码生成。它使用 codegen 命令生成一个 MEX 函数,该函数使用图像分类网络(如 MobileNet-v2、ResNet 和 GoogLeNet)运行预测。

第三方前提条件

必需

此示例生成 CUDA® MEX,并具有以下第三方要求。

  • CUDA 支持 NVIDIA® GPU 和兼容驱动程序。

可选

对于非 MEX 编译,如静态、动态库或可执行文件,此示例有以下附加要求。

验证 GPU 环境

使用 coder.checkGpuInstall (GPU Coder) 函数验证运行此示例所需的编译器和库是否已正确设置。

envCfg = coder.gpuEnvConfig('host');
envCfg.DeepLibTarget = 'cudnn';
envCfg.DeepCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);

mobilenetv2_predict 入口函数

MobileNet-v2 是一个卷积神经网络,基于来自 ImageNet 数据库的超过一百万个图像进行训练。该网络有 155 层深,可以将图像分类至 1000 个目标类别(例如键盘、鼠标、铅笔和多种动物)。该网络的图像输入大小为 224×224。使用 analyzeNetwork 函数显示深度学习网络架构的交互式可视化。

net = mobilenetv2();
analyzeNetwork(net);

mobilenetv2_predict.m 入口函数以图像作为输入,并使用预训练的 MobileNet-v2 卷积神经网络对图像运行预测。该函数使用持久性对象 mynet 加载串行网络对象,并在后续调用中重用该持久性对象进行预测。

type('mobilenetv2_predict.m')
% Copyright 2017-2019 The MathWorks, Inc.

function out = mobilenetv2_predict(in) 
%#codegen

persistent mynet;

if isempty(mynet)
    mynet = coder.loadDeepLearningNetwork('mobilenetv2','mobilenetv2');
end

% pass in input   
out = mynet.predict(in);

运行 MEX 代码生成

要为 mobilenetv2_predict 入口函数生成 CUDA 代码,请为 MEX 目标创建一个 GPU 代码配置对象,并将目标语言设置为 C++。使用 coder.DeepLearningConfig (GPU Coder) 函数创建一个 CuDNN 深度学习配置对象,并将其赋给 GPU 代码配置对象的 DeepLearningConfig 属性。运行 codegen 命令,并指定输入大小为 [224,224,3]。该值对应于 MobileNet-v2 网络的输入层大小。

cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -config cfg mobilenetv2_predict -args {ones(224,224,3)} -report
Code generation successful: View report

生成的代码描述

串行网络生成为一个 C++ 类,其中包含由 155 个层类组成的数组以及用于设置、调用预测和清理网络的函数。

class b_mobilenetv2_0
{
   .... 
   public:
     b_mobilenetv2_0();
     void setup();
     void predict();
     void cleanup();
     ~b_mobilenetv2_0();
};

该类的 setup() 方法会设置句柄并为网络对象的每层分配内存。predict() 方法会对网络中的 155 个层逐层执行预测。

生成的代码文件 mobilenetv2_predict.cu 中的入口函数 mobilenetv2_predict() 构造 b_mobilenetv2 类类型的静态对象,并对该网络对象调用 setup 和 predict。

static b_mobilenetv2_0 mynet;
static boolean_T mynet_not_empty;
/* Function Definitions */
void mobilenetv2_predict(const real_T in[150528], real32_T out[1000])
{
  if (!mynet_not_empty) {
    DeepLearningNetwork_setup(&mynet);
    mynet_not_empty = true;
  }
   /*  pass in input    */
   DeepLearningNetwork_predict(&mynet, in, out);
 }

系统将为具有参数的层(如网络中的全连接层和卷积层)导出相应的二进制文件。例如,文件 cnn_mobilenetv2_conv*_w 和 cnn_mobilenetv2_conv*_b 对应于网络中卷积层的权重和偏置参数。要查看生成的文件列表,请使用:

dir(fullfile(pwd, 'codegen', 'mex', 'mobilenetv2_predict'))

运行生成的 MEX

加载输入图像。

im = imread('peppers.png');
imshow(im);

对输入图像调用 mobilenetv2_predict_mex

im = imresize(im, [224,224]);
predict_scores = mobilenetv2_predict_mex(double(im));

获得排名前五的预测分数及其标签。

[scores,indx] = sort(predict_scores, 'descend');
classNames = net.Layers(end).ClassNames;
classNamesTop = classNames(indx(1:5));

h = figure;
h.Position(3) = 2*h.Position(3);
ax1 = subplot(1,2,1);
ax2 = subplot(1,2,2);

image(ax1,im);
barh(ax2,scores(5:-1:1))
xlabel(ax2,'Probability')
yticklabels(ax2,classNamesTop(5:-1:1))
ax2.YAxisLocation = 'right';
sgtitle('Top Five Predictions That Use MobileNet-v2')

清除内存中已加载的静态网络对象。

clear mex;

使用 ResNet-50 网络进行图像分类

您也可以使用 DAG 网络 ResNet-50 进行图像分类。Deep Learning Toolbox™ 的 ResNet-50 支持包提供了适用于 MATLAB® 的预训练 ResNet-50 模型。要下载并安装该支持包,请使用附加功能资源管理器。要了解有关查找和安装附加功能的详细信息,请参阅获取和管理附加功能

net = resnet50;
disp(net)
  DAGNetwork with properties:

         Layers: [177×1 nnet.cnn.layer.Layer]
    Connections: [192×2 table]
     InputNames: {'input_1'}
    OutputNames: {'ClassificationLayer_fc1000'}

运行 MEX 代码生成

要为 resnet_predict.m 入口函数生成 CUDA 代码,请为 MEX 目标创建一个 GPU 代码配置对象,并将目标语言设置为 C++。此入口函数调用 resnet50 函数来加载网络并对输入图像执行预测。

cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -config cfg resnet_predict -args {ones(224,224,3)} -report
Code generation successful: View report

对输入图像调用 resnet_predict_mex

predict_scores = resnet_predict_mex(double(im));

获得排名前五的预测分数及其标签。

[scores,indx] = sort(predict_scores, 'descend');
classNames = net.Layers(end).ClassNames;
classNamesTop = classNames(indx(1:5));

h = figure;
h.Position(3) = 2*h.Position(3);
ax1 = subplot(1,2,1);
ax2 = subplot(1,2,2);

image(ax1,im);
barh(ax2,scores(5:-1:1))
xlabel(ax2,'Probability')
yticklabels(ax2,classNamesTop(5:-1:1))
ax2.YAxisLocation = 'right';
sgtitle('Top Five Predictions That Use ResNet-50')

清除内存中已加载的静态网络对象。

clear mex;

使用 GoogLeNet (Inception) 网络进行图像分类

Deep Learning Toolbox 的 GoogLeNet 支持包提供了适用于 MATLAB 的预训练 GoogLeNet 模型。要下载并安装该支持包,请使用附加功能资源管理器。要了解有关查找和安装附加功能的详细信息,请参阅获取和管理附加功能

net = googlenet;
disp(net)
  DAGNetwork with properties:

         Layers: [144×1 nnet.cnn.layer.Layer]
    Connections: [170×2 table]
     InputNames: {'data'}
    OutputNames: {'output'}

运行 MEX 代码生成

googlenet_predict.m 入口函数生成 CUDA 代码。此入口函数调用 googlenet 函数来加载网络并对输入图像执行预测。要从此入口函数生成代码,请为 MEX 目标创建一个 GPU 配置对象。

cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -config cfg googlenet_predict -args {ones(224,224,3)} -report
Code generation successful: View report

对输入图像调用 googlenet_predict_mex

im = imresize(im, [224,224]);
predict_scores = googlenet_predict_mex(double(im));

获得排名前五的预测分数及其标签。

[scores,indx] = sort(predict_scores, 'descend');
classNames = net.Layers(end).ClassNames;
classNamesTop = classNames(indx(1:5));

h = figure;
h.Position(3) = 2*h.Position(3);
ax1 = subplot(1,2,1);
ax2 = subplot(1,2,2);

image(ax1,im);
barh(ax2,scores(5:-1:1))
xlabel(ax2,'Probability')
yticklabels(ax2,classNamesTop(5:-1:1))
ax2.YAxisLocation = 'right';
sgtitle('Top Five Predictions That Use GoogLeNet')

清除内存中已加载的静态网络对象。

clear mex;

相关主题