深度学习网络的代码生成
此示例说明如何为使用深度学习的图像分类应用程序执行代码生成。它使用 codegen
命令生成一个 MEX 函数,该函数使用图像分类网络(如 MobileNet-v2、ResNet 和 GoogLeNet)运行预测。
第三方前提条件
必需
此示例生成 CUDA MEX,并具有以下第三方要求。
CUDA® 支持 NVIDIA® GPU 和兼容驱动程序。
可选
对于非 MEX 编译,如静态、动态库或可执行文件,此示例有以下附加要求。
NVIDIA 工具包。
NVIDIA cuDNN 库。
编译器和库的环境变量。有关详细信息,请参阅Third-Party Hardware (GPU Coder)和Setting Up the Prerequisite Products (GPU Coder)。
验证 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;