В этом примере показано, как сгенерировать код для предварительно обученной сети долгой краткосрочной памяти (LSTM), которая использует ARM ® Compute Library и развертывает код на цели Raspberry Pi™. В этом примере сеть LSTM предсказывает оставшийся полезный срок службы (RUL) машины. Сеть принимает в качестве входных наборов данных временных рядов, которые представляют различные датчики в двигателе. Сеть возвращает Оставшийся Полезный Срок Работы двигателя, измеренный в циклах, в качестве своего выхода.
Этот пример использует набор данных моделирования деградации Engine Turbofan, как описано в [1]. Этот набор данных содержит 100 обучающих наблюдений и 100 тестовых наблюдений. Обучающие данные содержат моделируемые данные временных рядов для 100 двигателей. Каждая последовательность имеет 17 функции, изменяется в длине и соответствует полному запуску в отказ (RTF) образца. Эти тестовые данные содержат 100 частичных последовательности и соответствующие значения оставшегося полезного срока службы в конце каждой последовательности.
Этот пример использует предварительно обученную сеть LSTM. Для получения дополнительной информации о том, как обучить сеть LSTM, смотрите пример Классификация последовательности с использованием глубокого обучения (Deep Learning Toolbox).
Этот пример демонстрирует два различных подхода для выполнения предсказания с использованием сети LSTM:
Первый подход использует стандартную сеть LSTM и запускает вывод на наборе данных временных рядов.
Второй подход использует поведение той же сети LSTM с учетом состояний. В этом методе вы передаете один временной интервал данных за раз и получаете, чтобы сеть обновляла свое состояние на каждом временном шаге.
Этот пример использует рабочий процесс, основанный на PIL, чтобы сгенерировать MEX-функцию, которая, в свою очередь, вызывает исполняемый файл, сгенерированный на целевом компьютере из MATLAB.
Примечания:
Код, линии в этом примере, комментируется. Раскомментируйте их перед запуском примера.
Версия библиотеки ARM Compute, которую использует этот пример, может быть не последней версией, которая поддержки генерацию кода. Информацию о поддерживаемых версиях компиляторов и библиотек см. в разделе Оборудование и программное обеспечение сторонних производителей.
Этот пример не поддерживается в MATLAB Online.
MATLAB ® Coder™
Embedded Coder ®
Deep Learning Toolbox™
Интерфейс MATLAB Coder для библиотек глубокого обучения. Для установки этого пакета поддержки используйте браузер Add-On Explorer.
Пакет поддержки MATLAB для оборудования Raspberry Pi. Для установки этого пакета поддержки используйте браузер Add-On Explorer.
Оборудование Raspberry Pi
ARM Compute Library (на целевом оборудовании ARM)
Переменные окружения для компиляторов и библиотек. Для настройки переменных окружений смотрите Окружение Переменные.
Чтобы сгенерировать функцию PIL MEX для указанной функции точки входа, создайте объект строения кода для статической библиотеки и установите режим верификации на 'PIL'. Установите целевой язык на C++.
% cfg = coder.config('lib', 'ecoder', true); % cfg.VerificationMode = 'PIL'; % cfg.TargetLang = 'C++';
Создайте coder.ARMNEONConfig
объект. Укажите версию вычислительной библиотеки. В данном примере предположим, что ARM Compute Library в оборудовании Raspberry Pi является версией 19.05.
% dlcfg = coder.DeepLearningConfig('arm-compute'); % dlcfg.ArmComputeVersion = '19.05';
Установите DeepLearningConfig
свойство объекта строения генерации кода объекту строения глубокого обучения.
% cfg.DeepLearningConfig = dlcfg;
Используйте функцию MATLAB Поддержки Package for Raspberry Pi Поддержки Package, raspi
, для создания соединения с Raspberry Pi. В следующем коде замените:
raspiname
с именем вашего Raspberry Pi
username
с вашим именем пользователя
password
с вашим паролем
% r = raspi('raspiname','username','password');
Создайте coder.Hardware
объект для Raspberry Pi и присоедините его к объекту строения генерации кода.
% hw = coder.hardware('Raspberry Pi'); % cfg.Hardware = hw;
В этом подходе вы генерируете код для функции точки входа rul_lstmnet_predict
.
Функция точки входа rul_lstmnet_predict.m принимает весь набор данных временных рядов как вход и передает его в сеть для предсказания. В частности, функция использует сеть LSTM, которая обучена в примере Классификация последовательности с использованием глубокого обучения (Deep Learning Toolbox). Функция загружает сетевой объект из rul_lstmnet.mat
файл в постоянную переменную и повторно использует этот постоянный объект в последующих вызовах предсказания. Сеть LSTM от последовательности к последовательности позволяет вам делать различные предсказания для каждого отдельного временного шага последовательности данных.
Чтобы отобразить интерактивную визуализацию сетевой архитектуры и информацию о слоях сети, используйте analyzeNetwork
(Deep Learning Toolbox) функция.
type('rul_lstmnet_predict.m')
function out = rul_lstmnet_predict(in) %#codegen % Copyright 2019 The MathWorks, Inc. persistent mynet; if isempty(mynet) mynet = coder.loadDeepLearningNetwork('rul_lstmnet.mat'); end out = mynet.predict(in);
Чтобы сгенерировать код при помощи codegen
команда, используйте coder.typeof
функция для определения типа и размера входного параметра для функции точки входа. В этом примере вход имеет двойной тип данных со значением размерности признаков 17 и длину переменной последовательности. Задайте длину последовательности как переменный размер, чтобы выполнить предсказание для входа последовательности любой длины.
% matrixInput = coder.typeof(double(0),[17 Inf],[false true]);
Запустите команду codegen, чтобы сгенерировать основанную на PIL MEX-функцию rul_lstmnet_predict_pil
на хост-платформе.
% codegen -config cfg rul_lstmnet_predict -args {matrixInput} -report
Загрузите MAT-файл RULTestData
. Этот MAT-файл хранит переменные XTest
и YTest
которые содержат выборочный timeseries датчика, на которых можно протестировать сгенерированный код. Эти тестовые данные взяты из примера Классификация последовательности с использованием глубокого обучения (Deep Learning Toolbox) после предварительной обработки данных.
load RULTestData;
The XTest
переменная содержит 100 входных наблюдений. Каждое наблюдение имеет 17 функции с различной длиной последовательности.
XTest(1:5)
ans=5×1 cell array
{17×31 double}
{17×49 double}
{17×126 double}
{17×106 double}
{17×98 double}
The YTest
переменная содержит 100 выходных наблюдений, которые соответствуют XTest
входная переменная. Каждое выходное наблюдение является значением остаточного полезного срока службы (RUI), измеренным в циклах, для каждого временного шага данных в целом последовательности.
YTest(1:5)
ans=5×1 cell array
{[ 142 141 140 139 138 137 136 135 134 133 132 131 130 129 128 127 126 125 124 123 122 121 120 119 118 117 116 115 114 113 112]}
{[ 146 145 144 143 142 141 140 139 138 137 136 135 134 133 132 131 130 129 128 127 126 125 124 123 122 121 120 119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100 99 98]}
{[150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 149 148 147 146 145 144 143 142 141 140 139 138 137 136 135 134 133 132 131 130 129 128 127 126 125 124 123 122 121 120 119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69]}
{[ 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 149 148 147 146 145 144 143 142 141 140 139 138 137 136 135 134 133 132 131 130 129 128 127 126 125 124 123 122 121 120 119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82]}
{[ 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 149 148 147 146 145 144 143 142 141 140 139 138 137 136 135 134 133 132 131 130 129 128 127 126 125 124 123 122 121 120 119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100 99 98 97 96 95 94 93 92 91]}
Запустите сгенерированную MEX-функцию rul_lstmnet_predict_pil
на наборе случайных тестовых данных.
% idx = randperm(numel(XTest), 1); % inputData = XTest{idx}; % YPred1 = rul_lstmnet_predict_pil(inputData);
Используйте график, чтобы сравнить выходные данные MEX с тестовыми данными.
% figure('Name', 'Standard LSTM', 'NumberTitle', 'off'); % % plot(YTest{idx},'--') % hold on % plot(YPred1,'.-') % hold off % % ylim([0 175]) % title("Test Observation " + idx) % xlabel("Time Step") % ylabel("RUL measured in cycles")
% clear rul_lstmnet_predict_pil;
Вместо передачи всех данных timeseries сразу в predict
, можно запустить предсказание путем потоковой передачи входных данных сегментно при помощи predictAndUpdateState
функция.
Функция точки входа rul_lstmnet_predict_and_update.m принимает однократный вход и обрабатывает его при помощи predictAndUpdateState
(Deep Learning Toolbox) функция. predictAndUpdateState
возвращает предсказание для входного временного интервала и обновляет сеть так, чтобы последующие части входа рассматривались как последующие временные интервалы той же выборки.
type('rul_lstmnet_predict_and_update.m')
function out = rul_lstmnet_predict_and_update(in) %#codegen % Copyright 2019 The MathWorks, Inc. persistent mynet; if isempty(mynet) mynet = coder.loadDeepLearningNetwork('rul_lstmnet.mat'); end [mynet, out] = predictAndUpdateState(mynet, in); end
Создайте тип входа для codegen
команда. Потому что rul_lstmnet_predict_and_update
принимает отдельные данные временного интервала в каждом вызове, задает тип входа matrixInput
иметь фиксированную длину последовательности 1 вместо переменной длины последовательности.
% matrixInput = coder.typeof(double(0),[17 1]);
Запуск codegen
команда для генерации основанной на PIL MEX-функции rul_lstmnet_predict_and_update_pil
на хост-платформе.
% codegen -config cfg rul_lstmnet_predict_and_update -args {matrixInput} -report
% Run generated MEX function(|rul_lstmnet_predict_and_update_pil|) for each % time step data in the inputData sequence. % sequenceLength = size(inputData,2); % YPred2 = zeros(1, sequenceLength); % for i=1:sequenceLength % inTimeStep = inputData(:,i); % YPred2(:, i) = rul_lstmnet_predict_and_update_pil(inTimeStep); % end
После того, как вы передаете все временные интервалы, по одному, в rul_lstmnet_predict_and_update
функция, результат выхода такой же, как в первом подходе, в котором вы прошли все входы сразу.
Используйте график, чтобы сравнить выходные данные MEX с тестовыми данными.
% figure('Name', 'Statefull LSTM', 'NumberTitle', 'off'); % % % plot(YTest{idx},'--') % hold on % plot(YPred2,'.-') % hold off % % ylim([0 175]) % title("Test Observation " + idx) % xlabel("Time Step") % ylabel("RUL measured in cycles")
% clear rul_lstmnet_predict_and_update_pil;
[1] Саксена, Абхинав, Кай Гебель, Дон Симон и Нил Эклунд. Моделирование распространения повреждений для симуляции пробега двигателя самолета до отказа. В прогнозах и управлении здоровьем, 2008. PHM 2008. Международная конференция, стр. 1-9. IEEE, 2008.
coder.ARMNEONConfig
| coder.DeepLearningConfig
| coder.hardware
| predictAndUpdateState
(Deep Learning Toolbox)