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

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

Предпосылки

  • CUDA включил NVIDIA®, графический процессор с вычисляет возможность 3.5 или выше.

  • NVIDIA инструментарий CUDA и драйвер.

  • Библиотека NVIDIA cuDNN.

  • Переменные окружения для компиляторов и библиотек. Для получения информации о поддерживаемых версиях компиляторов и библиотек, смотрите Сторонние продукты (GPU Coder). Для подготовки переменных окружения смотрите Подготовку Необходимых как условие продуктов (GPU Coder).

  • Интерфейс GPU Coder для Библиотек Глубокого обучения поддерживает пакет. Чтобы установить этот пакет поддержки, используйте Add-On Explorer.

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

Используйте coder.checkGpuInstall функция, чтобы проверить, что компиляторы и библиотеки, необходимые для выполнения этого примера, настраиваются правильно.

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); 

Сгенерируйте 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 команда при помощи coder.typeof функция. В данном примере вход имеет двойной тип данных со значением размерности признаков три и переменная длина последовательности. Определение длины последовательности как переменного размера позволяет нам выполнить предсказание на входной последовательности любой длины.

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').

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

Вызовите сгенерированный 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))
  Columns 1 through 6

     Sitting      Sitting      Sitting      Sitting      Sitting      Sitting 

  Columns 7 through 10

     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

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}

Сгенерируйте 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 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: 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