В этом примере показано, как создать код для предварительно подготовленной сети долговременной памяти (LSTM), использующей вычислительную библиотеку ARM ®, и развернуть код на целевом устройстве Raspberry Pi™. В этом примере сеть LSTM прогнозирует оставшийся срок службы (RUL) машины. Сеть принимает в качестве входных наборов данных временных рядов, которые представляют различные датчики в механизме. Сеть возвращает в качестве выходного значения остаточный срок службы двигателя, измеренный в циклах.
В этом примере используется набор данных моделирования деградации турбовентиляторного двигателя, как описано в [1]. Этот набор данных содержит 100 учебных наблюдений и 100 тестовых наблюдений. Учебные данные содержат смоделированные данные временных рядов для 100 двигателей. Каждая последовательность имеет 17 функций, варьируется по длине и соответствует экземпляру полного прогона до отказа (RTF). Данные теста содержат 100 частичные последовательности и соответствующие значения остаточного срока службы в конце каждой последовательности.
В этом примере используется предварительно обученная сеть LSTM. Дополнительные сведения о том, как обучить сеть LSTM, см. в примере Классификация последовательностей с использованием глубокого обучения (Deep Learning Toolbox).
Этот пример демонстрирует два различных подхода к выполнению прогнозирования с использованием сети LSTM:
Первый подход использует стандартную сеть LSTM и выполняет вывод по набору данных временных рядов.
Второй подход использует поведение с учетом состояния той же сети LSTM. В этом методе выполняется одновременная передача одного временного интервала данных и обновление состояния сети на каждом временном шаге.
В этом примере рабочий процесс на основе PIL используется для генерации функции MEX, которая, в свою очередь, вызывает исполняемый файл, сгенерированный в целевом оборудовании из MATLAB.
Примечания:
Строки кода в этом примере комментируются. Раскомментируйте их перед запуском примера.
Версия библиотеки вычислений ARM, используемая в этом примере, может не быть последней версией, поддерживаемой при создании кода. Сведения о поддерживаемых версиях компиляторов и библиотек см. в разделе Аппаратное и программное обеспечение сторонних производителей.
Этот пример не поддерживается в MATLAB Online.
MATLAB ® Coder™
Встроенный кодер ®
Глубокое обучение Toolbox™
Интерфейс кодера MATLAB для библиотек глубокого обучения. Чтобы установить этот пакет поддержки, используйте обозреватель надстроек.
Пакет поддержки MATLAB для оборудования Raspberry Pi. Чтобы установить этот пакет поддержки, используйте обозреватель надстроек.
Аппаратное обеспечение Raspberry Pi
Вычислительная библиотека ARM (на целевом оборудовании ARM)
Переменные среды для компиляторов и библиотек. Сведения о настройке переменных среды см. в разделе Переменные среды.
Чтобы создать функцию PIL MEX для указанной функции точки входа, создайте объект конфигурации кода для статической библиотеки и установите режим проверки «PIL». Установите целевой язык на C++.
% cfg = coder.config('lib', 'ecoder', true); % cfg.VerificationMode = 'PIL'; % cfg.TargetLang = 'C++';
Создать coder.ARMNEONConfig объект. Укажите версию библиотеки вычислений. В этом примере предположим, что вычислительная библиотека ARM в аппаратном обеспечении Raspberry Pi имеет версию 19.05.
% dlcfg = coder.DeepLearningConfig('arm-compute'); % dlcfg.ArmComputeVersion = '19.05';
Установите DeepLearningConfig свойство объекта конфигурации генерации кода для объекта конфигурации глубокого обучения.
% cfg.DeepLearningConfig = dlcfg;Используйте функцию MATLAB Support Package for Raspberry Pi Support Package, raspi, чтобы создать соединение с Raspberry Pi. В следующем коде замените:
raspiname с именем вашего Малинового Пи
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 для генерации функции mex на основе PIL rul_lstmnet_predict_pil на хост-платформе.
% codegen -config cfg rul_lstmnet_predict -args {matrixInput} -reportЗагрузка файла MAT RULTestData. В этом MAT-файле хранятся переменные XTest и YTest которые содержат примеры временных интервалов показаний датчиков, по которым можно протестировать сгенерированный код. Эти тестовые данные взяты из примера Классификация последовательностей с использованием глубокого обучения (Deep Learning Toolbox) после предварительной обработки данных.
load RULTestData; 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}
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;Вместо того, чтобы передавать все данные временных рядов сразу в 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 команда для генерации функции mex на основе PIL 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] Саксена, Абхинав, Кай Гебель, Дон Симон и Нил Эклунд. «Моделирование распространения повреждений для имитации обкатки двигателя самолета». В Prognostics and Health Management, 2008. PHM 2008. Международная конференция, стр. 1-9. IEEE, 2008.
coder.ARMNEONConfig | coder.DeepLearningConfig | coder.hardware | predictAndUpdateState (инструментарий для глубокого обучения)