Регрессия от последовательности к последовательности Используя глубокое обучение

В этом примере показано, как предсказать остающийся срок полезного использования (RUL) механизмов при помощи глубокого обучения.

Чтобы обучить глубокую нейронную сеть предсказывать числовые значения от временных рядов или данных о последовательности, можно использовать сеть долгой краткосрочной памяти (LSTM).

Этот пример использует Турбовентиляторный Набор Данных моделирования Ухудшения Engine как описано в [1]. Пример обучает сеть LSTM, чтобы предсказать остающийся срок полезного использования механизма (прогнозирующее обслуживание), измеренный в циклах, учитывая данные временных рядов, представляющие различные датчики в механизме. Обучающие данные содержат симулированные данные временных рядов для 100 механизмов. Каждая последовательность имеет 17 функций, варьируется по длине и соответствует полному экземпляру запуска к отказу (RTF). Тестовые данные содержат 100 частичных последовательностей и соответствующие значения остающегося срока полезного использования в конце каждой последовательности.

Набор данных содержит 100 учебных наблюдений и 100 тестовых наблюдений.

Загрузите данные

Загрузите и разархивируйте Турбовентиляторный Набор Данных моделирования Ухудшения Engine от https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository/[2].

Каждые временные ряды представляют различный механизм. Каждый механизм запускается с неизвестных степеней начального износа и производственного изменения. Механизм действует обычно в начале каждых временных рядов и разрабатывает отказ в какой-то момент во время ряда. В наборе обучающих данных отказ растет в величине до системного отказа.

Данные содержат сжатые до zip текстовые файлы с 26 столбцами чисел, разделенных пробелами. Каждая строка является снимком состояния данных, взятых во время одного рабочего цикла, и каждый столбец является различной переменной. Столбцы соответствуют следующему:

  • Столбец 1: Модульный номер

  • Столбец 2: Время в циклах

  • Столбцы 3-5: Операционные настройки

  • Столбцы 6-26: измерения Датчика 1–17

filename = "CMAPSSData.zip";
dataFolder = "data";
unzip(filename,dataFolder)

Подготовьте обучающие данные

Загрузите данные с помощью функционального preprocessDataTrain показанный в конце этого примера. Функциональный prepareDataTrain извлекает данные из filenamePredictors и возвращает массивы ячеек XTrain и YTrain, которые содержат учебный предиктор и последовательности ответа.

filenamePredictors = fullfile(dataFolder,"train_FD001.txt");
[XTrain,YTrain] = prepareDataTrain(filenamePredictors);

Удалите функции с постоянными значениями

Функции, которые остаются постоянными навсегда, продвигаются, может негативно повлиять на обучение. Найдите строки данных, которые имеют те же минимальные и максимальные значения и удаляют строки.

m = min([XTrain{:}],[],2);
M = max([XTrain{:}],[],2);
idxConstant = M == m;

for i = 1:numel(XTrain)
    XTrain{i}(idxConstant,:) = [];
end

Нормируйте учебные предикторы

Нормируйте учебные предикторы, чтобы иметь нулевое среднее значение и модульное отклонение. Чтобы вычислить среднее и стандартное отклонение по всем наблюдениям, конкатенируйте данные о последовательности горизонтально.

mu = mean([XTrain{:}],2);
sig = std([XTrain{:}],0,2);

for i = 1:numel(XTrain)
    XTrain{i} = (XTrain{i} - mu) ./ sig;
end

Отсеките ответы

Чтобы узнать больше из данных о последовательности, когда механизмы будут близко к сбою, отсеките ответы в пороге 150. Это делает сетевые экземпляры обработки с выше значениями RUL как равные.

thr = 150;
for i = 1:numel(YTrain)
    YTrain{i}(YTrain{i} > thr) = thr;
end

Этот рисунок показывает первое наблюдение и соответствующий отсеченный ответ.

Подготовка данных для дополнения

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

Сортировка обучающих данных длиной последовательности.

for i=1:numel(XTrain)
    sequence = XTrain{i};
    sequenceLengths(i) = size(sequence,2);
end

[sequenceLengths,idx] = sort(sequenceLengths,'descend');
XTrain = XTrain(idx);
YTrain = YTrain(idx);

Просмотрите отсортированные длины последовательности в столбчатой диаграмме.

figure
bar(sequenceLengths)
xlabel("Sequence")
ylabel("Length")
title("Sorted Data")

Выберите мини-пакетный размер, который делит обучающие данные равномерно и уменьшает объем дополнения в мини-пакетах. Задайте мини-пакетный размер 20. Этот рисунок иллюстрирует дополнение, добавленное к неотсортированным и отсортированным последовательностям.

miniBatchSize = 20;

Архитектура сети Define

Определить сетевую архитектуру. Создайте сеть LSTM, которая состоит из слоя LSTM с 200 скрытыми модулями, сопровождаемыми полносвязным слоем размера 50 и слоя уволенного с вероятностью уволенного 0.5.

numResponses = size(YTrain{1},1);
featureDimension = size(XTrain{1},1);
numHiddenUnits = 200;

layers = [ ...
    sequenceInputLayer(featureDimension)
    lstmLayer(numHiddenUnits,'OutputMode','sequence')
    fullyConnectedLayer(50)
    dropoutLayer(0.5)
    fullyConnectedLayer(numResponses)
    regressionLayer];

Задайте опции обучения. Обучите в течение 60 эпох с мини-пакетами размера 20 использований решателя 'adam'. Задайте темп обучения 0.01. Чтобы препятствовать тому, чтобы градиенты взорвались, установите порог градиента к 1. Чтобы сохранить последовательности отсортированными по длине, установите 'Shuffle' к 'never'.

maxEpochs = 60;
miniBatchSize = 20;

options = trainingOptions('adam', ...
    'MaxEpochs',maxEpochs, ...
    'MiniBatchSize',miniBatchSize, ...
    'InitialLearnRate',0.01, ...
    'GradientThreshold',1, ...
    'Shuffle','never', ...
    'Plots','training-progress',...
    'Verbose',0);

Обучите сеть

Обучите сеть с помощью trainNetwork.

net = trainNetwork(XTrain,YTrain,layers,options);

Протестируйте сеть

Подготовьте тестовые данные с помощью функционального prepareDataTest показанный в конце примера. Функциональный prepareDataTest извлекает данные из filenamePredictors и filenameResponses и возвращает массивы ячеек XTest и YTest, которые содержат тестовый предиктор и последовательности ответа, соответственно.

filenamePredictors = fullfile(dataFolder,"test_FD001.txt");
filenameResponses = fullfile(dataFolder,"RUL_FD001.txt");
[XTest,YTest] = prepareDataTest(filenamePredictors,filenameResponses);

Удалите функции с постоянными значениями с помощью idxConstant вычисленный от обучающих данных. Нормируйте тестовые предикторы с помощью тех же параметров в качестве в обучающих данных. Отсеките тестовые ответы в том же пороге, используемом в обучающих данных.

for i = 1:numel(XTest)
    XTest{i}(idxConstant,:) = [];
    XTest{i} = (XTest{i} - mu) ./ sig;
    YTest{i}(YTest{i} > thr) = thr;
end

Сделайте прогнозы на тестовых данных с помощью predict. Чтобы препятствовать тому, чтобы функция добавила дополнение в данные, задайте мини-пакетный размер 1.

YPred = predict(net,XTest,'MiniBatchSize',1);

Сеть LSTM делает прогнозы на частичной последовательности одним временным шагом за один раз. На каждом временном шаге сеть предсказывает использование значения на этом временном шаге и сетевого состояния, вычисленного от предыдущих временных шагов только. Сеть обновляет свое состояние между каждым прогнозом. predict функция возвращает последовательность этих прогнозов. Последний элемент прогноза соответствует предсказанному RUL для частичной последовательности.

В качестве альтернативы можно сделать прогнозы одним временным шагом за один раз при помощи predictAndUpdateState. Это полезно, когда у вас есть значения временных шагов, прибывающих в поток. Обычно, это быстрее, чтобы сделать прогнозы на полных последовательностях когда по сравнению с созданием прогнозов один временной шаг за один раз. Для примера, показывающего, как предсказать будущие временные шаги путем обновления сети между одним прогнозами временного шага, смотрите, что Временные ряды Предсказывают Используя Глубокое обучение.

Визуализируйте некоторые прогнозы в графике.

idx = randperm(numel(YPred),4);
figure
for i = 1:numel(idx)
    subplot(2,2,i)
    
    plot(YTest{idx(i)},'--')
    hold on
    plot(YPred{idx(i)},'.-')
    hold off
    
    ylim([0 thr + 25])
    title("Test Observation " + idx(i))
    xlabel("Time Step")
    ylabel("RUL")
end
legend(["Test Data" "Predicted"],'Location','southeast')

Для данной частичной последовательности предсказанный текущий RUL является последним элементом предсказанных последовательностей. Вычислите среднеквадратичную ошибку (RMSE) прогнозов и визуализируйте ошибку прогноза в гистограмме.

for i = 1:numel(YTest)
    YTestLast(i) = YTest{i}(end);
    YPredLast(i) = YPred{i}(end);
end
figure
rmse = sqrt(mean((YPredLast - YTestLast).^2))
rmse = single
    16.9854
histogram(YPredLast - YTestLast)
title("RMSE = " + rmse)
ylabel("Frequency")
xlabel("Error")

Функции, взятые в качестве примера,

Функциональный prepareDataTrain извлекает данные из filenamePredictors и возвращает массивы ячеек XTrain и YTrain которые содержат учебный предиктор и последовательности ответа, соответственно.

Данные содержат сжатые до zip текстовые файлы с 26 столбцами чисел, разделенных пробелами. Каждая строка является снимком состояния данных, взятых во время одного рабочего цикла, и каждый столбец является различной переменной. Столбцы соответствуют следующему:

  • 1: Модульный номер

  • 2: Время в циклах

  • 3–5: Операционные настройки

  • 6–26: Измерения датчика 1–17

function [XTrain,YTrain] = prepareDataTrain(filenamePredictors)

dataTrain = dlmread(filenamePredictors);

numObservations = max(dataTrain(:,1));

XTrain = cell(numObservations,1);
YTrain = cell(numObservations,1);
for i = 1:numObservations
    idx = dataTrain(:,1) == i;
    
    X = dataTrain(idx,3:end)';
    XTrain{i} = X;
    
    timeSteps = dataTrain(idx,2)';
    Y = fliplr(timeSteps);
    YTrain{i} = Y;
end

end

Функциональный prepareDataTest извлекает данные из filenamePredictors и filenameResponses и возвращает массивы ячеек XTest и YTest, которые содержат тестовый предиктор и последовательности ответа. В filenamePredictors, временные ряды заканчивают некоторое время до системного отказа. Данные в filenameResponses обеспечивает вектор истинных значений RUL для тестовых данных.

function [XTest,YTest] = prepareDataTest(filenamePredictors,filenameResponses)

XTest = prepareDataTrain(filenamePredictors);

RULTest = dlmread(filenameResponses);

numObservations = numel(RULTest);

YTest = cell(numObservations,1);
for i = 1:numObservations
    X = XTest{i};
    sequenceLength = size(X,2);
    
    rul = RULTest(i);
    YTest{i} = rul+sequenceLength-1:-1:rul;
end

end

Смотрите также

| | | |

Ссылки

[1] Saxena, Abhinav, Кай Гоебель, Дон Саймон и Нил Экланд. "Повредите моделирование распространения для симуляции запуска к отказу авиационного двигателя". В Предзнаменованиях и медицинском управлении, 2008. PHM 2008. Международная конференция по вопросам, стр 1-9. IEEE, 2008.

[2] Saxena, Abhinav, Кай Гоебель. "Турбовентиляторный Набор Данных моделирования Ухудшения Engine". НАСА Репозиторий данных Предзнаменований Эймса https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository/, Исследовательский центр Эймса, Поле Moffett, CA

Похожие темы