Генерация кода для сети от последовательности к последовательности LSTM

Этот пример демонстрирует, как сгенерировать код CUDA® для сети долгой краткосрочной памяти (LSTM). Пример генерирует приложение MEX, которое делает предсказания на каждом шаге входа timeseries. Продемонстрированы два метода: метод с помощью стандартной сети LSTM и метода, усиливающего поведение с сохранением информации той же сети LSTM. Этот пример использует данные о датчике акселерометра из смартфона, продолжил тело и делает предсказания на действии владельца. Пользовательские перемещения классифицируются в одну из пяти категорий, а именно, танца, выполнения, нахождения, положения и обхода. Пример использует предварительно обученную сеть LSTM. Для получения дополнительной информации об обучении смотрите, что Классификация Последовательностей Использует пример Глубокого обучения от Deep Learning Toolbox™.

Сторонние необходимые условия

Необходимый

Этот пример генерирует MEX CUDA и имеет следующие сторонние требования.

  • CUDA включил NVIDIA® графический процессор и совместимый драйвер.

Дополнительный

Для сборок неMEX, таких как статические, динамические библиотеки или исполняемые файлы, этот пример имеет следующие дополнительные требования.

Проверьте среду графического процессора

Используйте 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-2021 The MathWorks, Inc. 

persistent mynet;

if isempty(mynet)
    mynet = coder.loadDeepLearningNetwork('lstmnet.mat');
end

% pass in input   
out = predict(mynet,in); 

Сгенерируйте MEX CUDA

Сгенерировать MEX CUDA для lstmnet_predict.m функция точки входа, создайте настройку графического процессора, возражают и задают цель, чтобы быть MEX. Установите выходной язык на C++. Создайте объект настройки глубокого обучения, который задает целевую библиотеку как cuDNN. Присоедините этот объект настройки глубокого обучения к объекту настройки графического процессора.

cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');

Во время компиляции GPU Coder™ должен знать типы данных всех входных параметров к функции точки входа. Задайте тип и размер входного параметра к codegen (MATLAB Coder) команда при помощи coder.typeof (MATLAB Coder) функция. В данном примере вход имеет двойной тип данных со значением размерности признаков три и переменная длина последовательности. Определение длины последовательности как переменного размера позволяет нам выполнить предсказание на входной последовательности любой длины.

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

Запустите codegen команду.

codegen -config cfg lstmnet_predict -args {matrixInput} -report
Code generation successful: View report

Запустите сгенерированный MEX на тестовых данных

Загрузите HumanActivityValidate Matfile. Этот MAT-файл хранит переменную XValidate это содержит демонстрационный timeseries показаний датчика, на которых можно протестировать сгенерированный код. Вызовите lstmnet_predict_mex на первом наблюдении.

load HumanActivityValidate
YPred1 = lstmnet_predict_mex(XValidate{1});

YPred1 5 53888 числовая матрица, содержащая вероятности этих пяти классов для каждого из этих 53 888 временных шагов. Для каждого временного шага найдите предсказанный класс путем вычисления индекса максимальной вероятности.

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

Сопоставьте индексы макс. вероятности к соответствующей метке. Отобразите первые десять меток. От результатов вы видите, что сеть предсказала человека, чтобы находиться для первых десяти временных шагов.

labels = categorical({'Dancing', 'Running', 'Sitting', 'Standing', 'Walking'});
predictedLabels1 = labels(maxIndex);
disp(predictedLabels1(1:10)')
     Sitting 
     Sitting 
     Sitting 
     Sitting 
     Sitting 
     Sitting 
     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"])

Вызовите сгенерированный MEX на наблюдении с различной длиной последовательности

Вызовите lstmnet_predict_mex на втором наблюдении с различной длиной последовательности. В этом примере, XValidate{2} имеет длину последовательности 64 480 тогда как XValidate{1} имел длину последовательности 53 888. Сгенерированный код обрабатывает предсказание правильно, потому что мы задали размерность длины последовательности, чтобы быть переменным размером.

YPred2 = lstmnet_predict_mex(XValidate{2});
[~, maxIndex] = max(YPred2, [], 1);
predictedLabels2 = labels(maxIndex);
disp(predictedLabels2(1:10)')
     Sitting 
     Sitting 
     Sitting 
     Sitting 
     Sitting 
     Sitting 
     Sitting 
     Sitting 
     Sitting 
     Sitting 

Сгенерируйте MEX, который берет в Нескольких Наблюдениях

Если вы хотите выполнить предсказание на многих наблюдениях целиком, можно собрать в группу наблюдения в массиве ячеек и передать массив ячеек для предсказания. Массив ячеек должен быть массивом ячейки столбца, и каждая ячейка должна содержать одно наблюдение. Каждое наблюдение должно иметь ту же размерность признаков, но длины последовательности могут варьироваться. В этом примере, 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
Code generation successful: View report
YPred3 = lstmnet_predict_mex(XValidate);

Выход является массивом ячеек 5 на 1 предсказаний для этих пяти наблюдений, переданных в.

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

Сгенерируйте MEX с LSTM с сохранением информации

Вместо того, чтобы передать целый timeseries, чтобы предсказать за один шаг, мы можем запустить предсказание на входе путем потоковой передачи в один такт за один раз, использования функционального predictAndUpdateState Эта функция берет во входе, производит выходное предсказание и обновляет внутреннее состояние сети так, чтобы будущие предсказания приняли этот начальный вход во внимание.

Функция точки входа lstmnet_predict_and_update.m берет во входе одно такта и обрабатывает вход с помощью predictAndUpdateState функция. predictAndUpdateState выводит предсказание в течение входного такта и обновляет сеть так, чтобы последующие входные параметры были обработаны как последующие такты той же выборки. После передачи во все такты по одному, эквивалентен получившийся выход, если все такты были переданы в как один вход.

type('lstmnet_predict_and_update.m')
function out = lstmnet_predict_and_update(in) %#codegen

% Copyright 2019-2021 The MathWorks, Inc. 

persistent mynet;

if isempty(mynet)
    mynet = coder.loadDeepLearningNetwork('lstmnet.mat');
end

% pass in input
[mynet, out] = predictAndUpdateState(mynet,in);

Запустите codegen на этом новом файле проекта. Поскольку мы принимаем в один такт каждый звонок, мы задаем matrixInput иметь фиксированную размерность последовательности 1 вместо переменной длины последовательности.

matrixInput = coder.typeof(double(0),[3 1]);
codegen -config cfg lstmnet_predict_and_update -args {matrixInput} -report
Code generation successful: View report

Запустите сгенерированный 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