主要内容

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

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

第三方的先决条件

要求

本例生成CUDA MEX,第三方需求如下。

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

可选

对于非mex构建,例如静态、动态库或可执行文件,此示例具有以下附加要求。

检查GPU环境

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

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

lstmnet_predict入口点函数

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

要显示网络体系结构和有关网络层的信息的交互式可视化,请使用analyzeNetwork(深度学习工具箱)函数。

类型(“lstmnet_predict.m”
版权所有2019-2021 The MathWorks, Inc. persistent mynet;if isempty(mynet) mynet = code . loaddeeplearningnetwork ('lstmnet.mat');End % pass in input out = predict(mynet,in);

生成CUDA MEX

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

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

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

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

执行codegen命令。

codegen配置cfglstmnet_predictarg游戏{matrixInput}报告
代码生成成功:查看报告

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

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

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

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

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

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

标签=分类({“跳舞”“奔跑”“坐”“站”“走”});predictedLabels1 = labels(maxIndex);disp (predictedLabels1(1: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)”)
坐,坐,坐,坐,坐,坐,坐

生成包含多个观察值的MEX

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

matrixInput = code .typeof(double(0),[3 Inf],[false true]);cellInput =编码器。typeof({matrixInput}, [5 1]);codegen配置cfglstmnet_predictarg游戏{cellInput}报告
代码生成成功:查看报告
YPred3 = lstmnet_predict_mex(XValidate);

输出是一个5乘1单元格数组,其中包含传递进来的5个观测值的预测结果。

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

使用有状态LSTM生成MEX

我们不需要在一步中传递整个时间序列来进行预测,而是可以利用该函数,通过每次输入一个时间步来运行预测predictAndUpdateState(深度学习工具箱)该函数接收输入,产生输出预测,并更新网络的内部状态,以便将来的预测考虑到这个初始输入。

入口函数lstmnet_predict_and_update.m方法接收单时间步输入并处理输入predictAndUpdateState(深度学习工具箱)函数。predictAndUpdateState输出对输入时间步长的预测并更新网络,以便后续输入被视为同一样本的后续时间步。每次传入一个时间步骤之后,得到的输出与作为单个输入传入的所有时间步骤相同。

类型(“lstmnet_predict_and_update.m”
版权所有2019-2021 The MathWorks, Inc. persistent mynet;if isempty(mynet) mynet = code . loaddeeplearningnetwork ('lstmnet.mat');[mynet, out] = predictAndUpdateState(mynet,in);

在这个新设计文件上运行代码原。由于每次调用都采用单一的时间步长,因此我们指定matrixInput有一个固定的序列维数为1,而不是可变的序列长度。

matrixInput = code .typeof(double(0),[3 1]);codegen配置cfglstmnet_predict_and_updatearg游戏{matrixInput}报告
代码生成成功:查看报告

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

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

比较输出标签和基本真实值。

YValidate {1} (1)
ans =分类坐着

另请参阅

功能

对象

相关的例子

更多关于