В этом примере показано, как создать код CUDA ® для сети LSTM. Пример создает приложение MEX, которое делает прогнозы на каждом шаге входных временных серий. Демонстрируются два метода: метод, использующий стандартную сеть LSTM, и метод, использующий поведение с учетом состояния той же сети LSTM. В этом примере используются данные датчика акселерометра со смартфона, переносимого на тело, и производится прогноз активности пользователя. Движения пользователей подразделяются на одну из пяти категорий, а именно танцы, бег, сидение, стояние и ходьба. В примере используется предварительно обученная сеть LSTM. Дополнительные сведения об обучении см. в разделе Пример классификации последовательностей с использованием глубокого обучения из Toolbox™ глубокого обучения.
Необходимый
В этом примере создается CUDA MEX со следующими требованиями сторонних производителей.
Графический процессор NVIDIA ® с поддержкой CUDA и совместимый драйвер.
Дополнительный
Для построений, отличных от MEX, таких как статические, динамические библиотеки или исполняемые файлы, этот пример имеет следующие дополнительные требования.
Инструментарий NVIDIA.
Библиотека NVIDIA cuDNN.
Переменные среды для компиляторов и библиотек. Дополнительные сведения см. в разделах Аппаратное обеспечение сторонних производителей (GPU Coder) и Настройка необходимых продуктов (GPU Coder).
Используйте coder.checkGpuInstall Функция (GPU Coder) для проверки правильности настройки компиляторов и библиотек, необходимых для выполнения этого примера.
envCfg = coder.gpuEnvConfig('host'); envCfg.DeepLibTarget = 'cudnn'; envCfg.DeepCodegen = 1; envCfg.Quiet = 1; coder.checkGpuInstall(envCfg);
lstmnet_predict Функция точки входаСеть LSTM «последовательность-последовательность» позволяет делать различные прогнозы для каждого отдельного временного шага последовательности данных. Функция начальной точки lstmnet_predict.m принимает входную последовательность и передает ее в обученную сеть LSTM для прогнозирования. В частности, функция использует сеть LSTM, обученную классификации последовательности с использованием глубокого обучения. Функция загружает сетевой объект из lstmnet_predict.mat в постоянную переменную и повторно использует постоянный объект при последующих вызовах прогнозирования.
Для отображения интерактивной визуализации сетевой архитектуры и информации о сетевых уровнях используйте analyzeNetwork функция.
type('lstmnet_predict.m')
function out = lstmnet_predict(in) %#codegen
% Copyright 2019 The MathWorks, Inc.
persistent mynet;
if isempty(mynet)
mynet = coder.loadDeepLearningNetwork('lstmnet.mat');
end
% pass in input
out = predict(mynet,in);
Создание CUDA MEX для lstmnet_predict.m функция начальной точки, создайте объект конфигурации графического процессора и укажите конечный объект, который должен быть MEX. Установите целевой язык на C++. Создайте объект конфигурации глубокого обучения, определяющий целевую библиотеку как cuDNN. Присоедините этот объект конфигурации глубокого обучения к объекту конфигурации графического процессора.
cfg = coder.gpuConfig('mex'); cfg.TargetLang = 'C++'; cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
Во время компиляции GPU Coder™ должен знать типы данных всех входов в функцию точки входа. Укажите тип и размер входного аргумента для codegen (Кодер MATLAB) с помощью команды coder.typeof (Кодер MATLAB). В этом примере входные данные имеют двойной тип данных со значением размера элемента три и переменной длиной последовательности. Задание длины последовательности как переменной величины позволяет выполнять прогнозирование для входной последовательности любой длины.
matrixInput = coder.typeof(double(0),[3 Inf],[false true]);
Выполните команду codegen.
codegen -config cfg lstmnet_predict -args {matrixInput} -report
Code generation successful: To view the report, open('codegen/mex/lstmnet_predict/html/report.mldatx').
Загрузить HumanActivityValidate MAT-файл. В этом MAT-файле хранится переменная XValidate содержит примеры временных интервалов показаний датчика, по которым можно протестировать сгенерированный код. Звонить lstmnet_predict_mex о первом наблюдении.
load HumanActivityValidate
YPred1 = lstmnet_predict_mex(XValidate{1});
YPred1 представляет собой числовую матрицу 5 на 53888, содержащую вероятности пяти классов для каждого из 53888 временных шагов. Для каждого временного шага найдите прогнозируемый класс путем вычисления индекса максимальной вероятности.
[~, maxIndex] = max(YPred1, [], 1);
Свяжите индексы максимальной вероятности с соответствующей меткой. Отображение первых десяти меток. Из результатов видно, что сеть предсказала, что человек будет сидеть первые десять шагов.
labels = categorical({'Dancing', 'Running', 'Sitting', 'Standing', 'Walking'});
predictedLabels1 = labels(maxIndex);
disp(predictedLabels1(1:10))
Columns 1 through 6
Sitting Sitting Sitting Sitting Sitting Sitting
Columns 7 through 10
Sitting Sitting Sitting Sitting
Используйте график для сравнения выходных данных MEX с данными теста.
figure plot(predictedLabels1,'.-'); hold on plot(YValidate{1}); hold off xlabel("Time Step") ylabel("Activity") title("Predicted Activities") legend(["Predicted" "Test Data"])

Звонить lstmnet_predict_mex на втором наблюдении с другой длиной последовательности. В этом примере: XValidate{2} имеет длину последовательности 64480, тогда как XValidate{1} имеет длину последовательности 53888. Сгенерированный код правильно обрабатывает предсказание, поскольку мы указали измерение длины последовательности как переменный размер.
YPred2 = lstmnet_predict_mex(XValidate{2});
[~, maxIndex] = max(YPred2, [], 1);
predictedLabels2 = labels(maxIndex);
disp(predictedLabels2(1:10))
Columns 1 through 6
Sitting Sitting Sitting Sitting Sitting Sitting
Columns 7 through 10
Sitting Sitting Sitting Sitting
Если требуется выполнить прогнозирование сразу для многих наблюдений, можно сгруппировать наблюдения в массив ячеек и передать массив ячеек для прогнозирования. Массив ячеек должен быть массивом ячеек столбцов, и каждая ячейка должна содержать одно наблюдение. Каждое наблюдение должно иметь одинаковый размер элемента, но длина последовательности может изменяться. В этом примере: XValidate содержит пять наблюдений. Чтобы создать MEX, который может принять XValidate в качестве входных данных укажите тип входных данных, который должен быть массивом ячеек 5 на 1. Кроме того, укажите, что каждая ячейка должна иметь тот же тип, что и matrixInput, тип, указанный для одного наблюдения в предыдущем codegen команда.
matrixInput = coder.typeof(double(0),[3 Inf],[false true]);
cellInput = coder.typeof({matrixInput}, [5 1]);
codegen -config cfg lstmnet_predict -args {cellInput} -report
YPred3 = lstmnet_predict_mex(XValidate);
Code generation successful: To view the report, open('codegen/mex/lstmnet_predict/html/report.mldatx').
Выходные данные представляют собой массив предсказаний 5 на 1 для пяти переданных наблюдений.
disp(YPred3)
{5×53888 single}
{5×64480 single}
{5×53696 single}
{5×56416 single}
{5×50688 single}
Вместо передачи всей временной последовательности для прогнозирования за один шаг, мы можем запустить прогнозирование на входе путем потоковой передачи в один временной интервал за один раз, используя функцию predictAndUpdateState Эта функция принимает входные данные, производит прогнозирование выходных данных и обновляет внутреннее состояние сети так, чтобы будущие прогнозы учитывали эти исходные данные.
Функция начальной точки lstmnet_predict_and_update.m принимает вход в один временной интервал и обрабатывает вход с помощью predictAndUpdateState функция. predictAndUpdateState выводит прогноз для входного временного интервала и обновляет сеть так, чтобы последующие входные сигналы рассматривались как последующие временные интервалы той же выборки. После прохождения всех временных интервалов по одному, результирующий выходной сигнал будет таким же, как если бы все временные интервалы были переданы как один вход.
type('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');
end
% pass in input
[mynet, out] = predictAndUpdateState(mynet,in);
Запустите кодеген для этого нового файла конструкции. Поскольку мы принимаем один временной интервал для каждого вызова, мы указываем matrixInput чтобы иметь фиксированную размерность последовательности 1 вместо переменной длины последовательности.
matrixInput = coder.typeof(double(0),[3 1]); codegen -config cfg lstmnet_predict_and_update -args {matrixInput} -report
Code generation successful: To view the report, open('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 = labels(maxIndex)
predictedLabelsStateful1 =
categorical
Sitting
Сравните выходную метку с истинностью земли.
YValidate{1}(1)
ans =
categorical
Sitting