主要内容

序列到序列LSTM网络的代码生成

这个例子演示了如何为一个长短期记忆(LSTM)网络生成CUDA®代码。该示例生成一个MEX应用程序,该应用程序在输入时间序列的每一步进行预测。本文演示了两种方法:一种方法使用标准LSTM网络,另一种方法利用同一LSTM网络的有状态行为。这个例子利用携带在身上的智能手机上的加速度传感器数据,对穿戴者的活动进行预测。用户的动作分为跳、跑、坐、站、走五类。这个例子使用了一个预先训练的LSTM网络。有关培训的更多信息,请参见基于深度学习的序列分类Deep Learning Toolbox™中的例子。

第三方的先决条件

要求

这个示例生成CUDA MEX,并具有以下第三方需求。

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

可选

对于非mex构建,如静态、动态库或可执行文件,本示例有以下额外需求。

验证GPU环境

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

envCfg = coder.gpuEnvConfig (“主机”);envCfg。DeepLibTarget =“cudnn”;envCfg。DeepCodegen = 1;envCfg。安静= 1;coder.checkGpuInstall (envCfg);

lstmnet_predict入口点函数

序列到序列的LSTM网络使您能够对数据序列的每个时间步长做出不同的预测。的lstmnet_predict.m入口点函数接受一个输入序列,并将其传递到经过训练的LSTM网络进行预测。具体来说,该函数使用了在基于深度学习的序列到序列分类的例子。对象加载网络对象lstmnet_predict.mat文件到持久变量中,并在随后的预测调用中重用持久对象。

要显示有关网络层的网络架构和信息的交互式可视化,请使用analyzeNetwork函数。

类型(“lstmnet_predict.m”
function out = lstmnet_predict(in) %#codegen % Copyright 2019 The MathWorks, Inc. persistent mynet;if isempty(mynet) mynet = coder.loadDeepLearningNetwork('lstmnet.mat');* * * * * * * * * * * * * * * * * *

生成CUDA墨西哥人

为CUDA MEX生成lstmnet_predict.m入口点函数,创建一个GPU配置对象,并指定目标为MEX。将目标语言设置为c++。创建一个深度学习配置对象,将目标库指定为cuDNN。将这个深度学习配置对象绑定到GPU配置对象。

cfg = coder.gpuConfig (墨西哥人的);cfg。TargetLang =“c++”;cfg。DeepLearningConfig =编码器。DeepLearningConfig (“cudnn”);

在编译时,GPU编码器™必须知道所有输入到入口点函数的数据类型。属性的输入参数的类型和大小codegen(MATLAB编码器)命令,使用coder.typeof(MATLAB编码器)函数。对于本例,输入是双数据类型,特征维值为3,序列长度可变。将序列长度指定为可变大小,使我们能够对任意长度的输入序列执行预测。

matrixInput = coder.typeof(double(0),[3 Inf],[false true]);

执行codegen命令。

codegen配置cfglstmnet_predictarg游戏{matrixInput}报告
代码生成成功:要查看报告,打开('codegen/mex/lstmnet_predict/html/report.mldatx')。

在测试数据上运行生成的MEX

加载HumanActivityValidateMAT-file。这个mat文件存储这个变量XValidate它包含传感器读数的样本时间序列,您可以在上面测试生成的代码。调用lstmnet_predict_mex第一次观察。

负载HumanActivityValidateYPred1 = lstmnet_predict_mex (XValidate {1});

YPred1是一个5 × 53888的数字矩阵,包含了每一个53888时间步长的五个类的概率。对于每一个时间步,通过计算最大概率的指标来找到预测类。

[~, maxIndex] = max(YPred1, [], 1);

将最大概率的指标与相应的标签关联起来。显示前十个标签。从结果中可以看出,网络预测了人在前十个时间步是坐着的。

标签=分类({“跳舞”“奔跑”“坐”“站”“走”});predictedLabels1 =标签(maxIndex);disp (predictedLabels1 (1:10))
第7到10列坐着坐着坐着坐着

将预测结果与测试数据进行比较

使用图表将MEX输出数据与测试数据进行比较。

图绘制(predictedLabels1,“。”);持有情节(YValidate {1});持有包含(“时间步”) ylabel (“活动”)标题(“预测活动”)传说([“预测”“测试数据”])

在不同序列长度的观测上生成的MEX调用

调用lstmnet_predict_mex对不同序列长度的第二次观测。在这个例子中,XValidate {2}序列长度为64480,而XValidate {1}序列长度为53888。生成的代码正确地处理预测,因为我们将序列长度维度指定为可变大小。

YPred2 = lstmnet_predict_mex (XValidate {2});[~, maxIndex] = max(YPred2, [], 1);predictedLabels2 =标签(maxIndex);disp (predictedLabels2 (1:10))
第7到10列坐着坐着坐着坐着

生成接受多个观察的MEX

如果希望同时对许多观测执行预测,可以将这些观测分组到一个单元格阵列中,并传递单元格阵列进行预测。单元格阵列必须是列单元格阵列,并且每个单元格必须包含一个观察结果。每个观测必须具有相同的特征维数,但序列长度可能不同。在这个例子中,XValidate包含五个观察。生成一个可以接收XValidate作为输入,指定输入类型为5 × 1单元格数组。此外,指定每个单元格的类型与matrixInput,即您在前面为单个观察指定的类型codegen命令。

matrixInput = coder.typeof(double(0),[3 Inf],[false true]);cellInput =编码器。typeof ({matrixInput} 1 [5]);codegen配置cfglstmnet_predictarg游戏{cellInput}报告YPred3 = lstmnet_predict_mex (XValidate);
代码生成成功:要查看报告,打开('codegen/mex/lstmnet_predict/html/report.mldatx')。

输出是一个5 × 1单元格阵列,其中包含了传入的5个观测的预测。

disp (YPred3)
{5×53888 single} {5×64480 single} {5×53696 single} {5×56416 single} {5×50688 single}

使用有状态LSTM生成MEX

不需要在一个步骤中传递整个时间序列来进行预测,我们可以利用函数,通过每次一个时间步的流来对输入进行预测predictAndUpdateState这个函数接受一个输入,产生一个输出预测,并更新网络的内部状态,以便将来的预测考虑到这个初始输入。

的入口点函数lstmnet_predict_and_update.m获取单时间步输入并使用predictAndUpdateState函数。predictAndUpdateState输出对输入时间步长的预测,并更新网络,以便后续的输入被视为同一样本的后续时间步。每次一个传入所有时间步后,结果输出与将所有时间步作为单个输入传入相同。

类型(“lstmnet_predict_and_update.m”
function out = lstmnet_predict_and_update(in) %#codegen % Copyright 2019 The MathWorks, Inc. persistent mynet;if isempty(mynet) mynet = coder.loadDeepLearningNetwork('lstmnet.mat');/ /输入[mynet, out] = predictAndUpdateState(mynet,in);

在这个新设计文件上运行代码生成器。由于我们在每个调用中只接受一个时间步长,所以我们指定matrixInput固定的序列维数为1,而不是可变的序列长度。

matrixInput = coder.typeof(double(0),[3 1]);codegen配置cfglstmnet_predict_and_updatearg游戏{matrixInput}报告
代码生成成功:要查看报告,请打开('codegen/mex/lstmnet_predict_and_update/html/report.mldatx')。

在第一个验证示例的第一个时间步上运行生成的MEX。

firstSample = XValidate {1};firstTimestep = firstSample (: 1);YPredStateful = lstmnet_predict_and_update_mex (firstTimestep);[~, maxIndex] = max(YPredStateful, [], 1);predictedLabelsStateful1 =标签(maxIndex)
predictedLabelsStateful1 =分类坐

将输出标签与ground truth进行比较。

YValidate {1} (1)
ans =绝对坐姿