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

Этот пример показывает, как предсказать остающийся срок полезного использования (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

Похожие темы