本页面提供的是上一版软件的文档。当前版本中已删除对应的英文页面。

深度学习网络的代码生成

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

前提条件

  • 支持 CUDA® 的 NVIDIA® GPU,计算能力为 3.2 或更高。

  • NVIDIA CUDA 工具包和驱动程序。

  • NVIDIA cuDNN 库。

  • 编译器和库的环境变量。有关支持的编译器和库的版本的信息,请参阅Third-party Products (GPU Coder)。有关设置环境变量的信息,请参阅Setting Up the Prerequisite Products (GPU Coder)。

  • GPU Coder Interface for Deep Learning Libraries 支持包。要安装此支持包,请使用附加功能资源管理器

验证 GPU 环境

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

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 函数创建一个 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: To view the report, open('codegen/mex/mobilenetv2_predict/html/report.mldatx').

生成的代码说明

串行网络生成为一个 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')

视频的分类

所包含的辅助函数 mobilenet_live.m 从网络摄像头抓取帧,执行预测,并在每个捕获的视频帧上显示分类结果。此示例使用由 MATLAB® Support Package for USB Webcams™ 支持的 函数。您可以通过支持包安装程序下载并安装支持包。

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

function mobilenet_live

% Connect to a camera
camera = webcam; 

% The labels with top 5 prediction scores are 
% mapped to corresponding labels
net = mobilenetv2();
classnames = net.Layers(end).ClassNames;

imfull = zeros(224,400,3, 'uint8');

fps = 0;

ax = axes;

while true
    % Take a picture
    ipicture = camera.snapshot;       
    
    % Resize and cast the picture to single        
    picture = imresize(ipicture,[224,224]);  
    
    % Call MEX function for MobileNet-v2 prediction
    tic;    
    pout = mobilenetv2_predict(single(picture));
    newt = toc;
       
    % fps 
    fps = .9*fps + .1*(1/newt);
    
    % top 5 scores
    [top5labels, scores] = getTopFive(pout,classnames);
    
    % display
    if isvalid(ax)
        dispResults(ax, imfull, picture, top5labels, scores, fps);   
    else
        break;
    end
end

end

function dispResults(ax, imfull, picture, top5labels, scores, fps)
for k = 1:3
    imfull(:,177:end,k) = picture(:,:,k);
end

h = imshow(imfull, 'InitialMagnification',200, 'Parent', ax);
scol = 1;
srow = 20;
text(get(h, 'Parent'), scol, srow, sprintf('MobileNet-v2 Demo'), 'color', 'w', 'FontSize', 20);
srow = srow + 20;

text(get(h, 'Parent'), scol, srow, sprintf('Fps = %2.2f', fps), 'color', 'w', 'FontSize', 15);
srow = srow + 20;
for k = 1:5
    t = text(get(h, 'Parent'), scol, srow, top5labels{k}, 'color', 'w','FontSize', 15);
    pos = get(t, 'Extent');
    text(get(h, 'Parent'), pos(1)+pos(3)+5, srow, sprintf('%2.2f%%', scores(k)), 'color', 'w', 'FontSize', 15);
    srow = srow + 20;
end

drawnow;
end

function [labels, scores] = getTopFive(predictOut,classnames)
[val,indx] = sort(predictOut, 'descend');
scores = val(1:5)*100;
labels = classnames(indx(1:5));
end

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

clear mex;

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

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

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: To view the report, open('codegen/mex/resnet_predict/html/report.mldatx').

对输入图像调用 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 模型。要下载并安装该支持包,请使用附加功能资源管理器。要了解有关查找和安装附加功能的详细信息,请参阅获取附加功能 (MATLAB)

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: To view the report, open('codegen/mex/googlenet_predict/html/report.mldatx').

对输入图像调用 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;

相关主题