Изучение набора данных НАСА по ТРДД

MLP с запаздыванием для профилактического обслуживания турбовентиляторных двигателей

Стандартизация на основе условий эксплуатации и настройка гиперпараметров для FD002

‹отказ от ответственности Я стремлюсь продемонстрировать влияние различных методов и вариантов, сделанных во время разработки модели. Эти эффекты часто демонстрируются с помощью набора тестов, что считается (очень) плохой практикой, но помогает в образовательных целях. ›

Добро пожаловать в очередной выпуск серии Изучение набора данных НАСА по турбовентиляторным двигателям. В нашем последнем анализе мы обучили случайный лес и настроили гиперпараметры для FD003.

Сегодня мы разработаем модель для набора данных FD002. Набор данных, в котором двигатели могут работать в шести уникальных рабочих условиях, справиться с которыми оказалось гораздо сложнее, чем я ожидал. Для этой цели я решил написать об этом наборе данных после FD003. Поскольку, на мой взгляд, изменение порядка приводит к более постепенному увеличению сложности. Более сложные наборы данных часто требуют более сложных решений, это будет первая статья в серии, в которой мы будем обучать и настраивать нейронную сеть (NN). К тому же это самая длинная статья, потому что здесь так много всего, что нужно обсудить, так что приступим!

Загрузка данных

Сначала мы импортируем необходимые библиотеки.

Затем мы загрузим данные и проверим первые несколько строк.

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

Исследовательский анализ данных (EDA)

Пора приступить к изучению наших данных. Описательную статистику пока пропущу, здесь особо нечего найти. Однако мы проверим наличие шести уникальных условий эксплуатации.

Как видите, присутствуют шесть уникальных условий эксплуатации. Одно рабочее состояние встречается чаще, но в остальном оно довольно сбалансировано.

Сюжет

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

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

Настройки 1 и 2 выглядят очень похоже, поэтому я оставил график настройки 2. Настройка 3 ведет себя немного иначе (см. Изображение ниже).

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

Базовая модель

Базовая модель будет простой линейной регрессией без какой-либо разработки или выбора признаков. Единственное, что мы сделаем, это обновим наше убеждение или ПРАВИЛО для обучающей выборки, как описано в предыдущем посте [4]. По сути, мы делаем то, что вместо того, чтобы позволить вычисленному RUL линейно снижаться, мы устанавливаем верхний предел вычисленного RUL равным 125. Отсечение RUL - это проверенный метод, который дает гораздо лучшие результаты по сравнению с наивным линейным уменьшением RUL [5].

# returns:
# train set RMSE:21.94192340996904, R2:0.7226666213449306
# test set RMSE:32.64244063056574, R2:0.6315800619887212

В нашей базовой модели RMSE тренировки составляет 21,94, а тестовая RMSE - 32,64, что будет лучшим показателем. Продолжим подготовку первой реализации нашей НС.

Набор для проверки

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

Как и в прошлый раз, мы разделим данные таким образом, чтобы все записи одного механизма были либо назначены для обучения, либо для проверки, чтобы предотвратить «утечку данных». Для этой цели мы будем использовать GroupShuffleSplit sklearns, где наши группы для разделения состоят из номеров единиц.

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

Хотя частота ниже, распределение RUL проверки похоже на RUL обучения.

Масштабирование

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

Обратите внимание, что разделение на поезд-валидацию точно такое же, как и предыдущее. Я принял дополнительные меры предосторожности, чтобы обеспечить воспроизводимость и сопоставимость результатов, о чем вы можете прочитать здесь.

Многослойный персептрон (MLP)

MLP считается «ванильной» сетью, подходящей для изучения нелинейных паттернов и состоящей как минимум из входного, скрытого и выходного уровней [6]. Создать и обучить этот тип НС в керасе относительно просто.

Во-первых, мы определяем входное измерение, которое представляет собой количество функций, которые ожидает NN. Затем мы создаем объект модели, инициируя слой Sequential и добавляя несколько плотных слоев, указывая количество узлов в каждом слое. Входное измерение следует передать первому плотному слою. Последним слоем в модели должен быть плотный слой с одним узлом, поскольку мы ожидаем, что модель вернет одно значение (предсказанное RUL) для одной строки данных.

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

Далее обучаем модель. В функцию подгонки передается еще один аргумент - количество эпох. Количество эпох показывает, как часто данные представляются модели для обучения. В этом случае мы представим набор данных 20 раз.

При проверке результатов обучения важно учитывать сокращение потерь при обучении и валидации. Когда оба убытка уменьшаются, все идет хорошо, и модель изучает закономерности в наборе данных. Когда потери в обучении снижаются, а потери при проверке (неуклонно) растут, модель переобучается, чего мы хотим избежать. Однако есть более простой способ интерпретировать потерю - это построить график.

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

# returns:
# train set RMSE:22.393854937161706, R2:0.7111246569724521
# test set RMSE:34.00842713320483, R2:0.600100397460153

Теперь у нас есть модель, производительность которой приближается к базовой модели. Пора начинать разработку функций.

Одно горячее кодирование

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

Одно горячее кодирование часто используется для кодирования категориальной переменной в двоичные столбцы. В этом случае каждое уникальное рабочее состояние будет «категорией», см. Изображение ниже.

Каждая строка будет иметь только одно уникальное рабочее условие, т.е. только один столбец будет иметь в нем 1, а в других - 0. Добавление этой информации к вашим данным при удалении исходных настроек упрощает для NN определение того, какой используется уникальная комбинация настроек и их отношение к целевой переменной.

Обучение модели с этими новыми функциями дало улучшение (RMSE обучения = 20.80, тест RMSE = 32.01), но с этой реализацией возникают две проблемы:

  1. Улучшение за счет одного горячего кодирования не так велико, как я ожидал.
  2. Эта реализация оставляет мало места для разработки дополнительных функций. Например, мы не можем использовать какие-либо фильтры сигналов, когда сигналы датчиков сильно различаются в зависимости от условий эксплуатации. Кроме того, добавление переменных с запаздыванием нецелесообразно, поскольку необходимо также учитывать запаздывания, чтобы учесть изменяющиеся условия эксплуатации.

Я сохранил код в записной книжке для справки, вы можете найти ссылку внизу этой статьи. Затем мы попробуем другой метод работы с условиями эксплуатации.

Стандартизация на основе условий

Ранее мы пробовали масштабировать по минимуму и максимуму сразу весь набор данных. При стандартизации на основе условий вы группируете все записи одного рабочего состояния вместе и масштабируете их с помощью стандартного масштабатора. Применение этого типа масштабирования приведет к нулевому среднему значению сгруппированных рабочих условий. Поскольку вы применяете эту технику для каждого рабочего состояния отдельно, все сигналы будут иметь нулевое среднее значение, что приведет их в некоторой степени к одной и той же линии и сделает их сопоставимыми [7]. Этот тип стандартизации работает очень хорошо, если сигналы имеют схожее поведение, но сосредоточены вокруг другого среднего значения. Обратите внимание: этот метод можно использовать только в том случае, если условия эксплуатации сами по себе не влияют на неизбежность поломки!

Во-первых, мы добавим уникальное рабочее условие в фрейм данных, аналогично первому шагу одного горячего кодирования.

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

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

Сенсоры 1, 5, 16 и 19 выглядят одинаково и на данном этапе не кажутся очень полезными.

Сенсоры 2, 3, 4, 11, 15 и 17 показывают аналогичную тенденцию к росту и должны быть включены для дальнейшей разработки модели.

Сенсоры 6, 10 и 16 выглядят одинаково и не содержат никакой полезной информации после использования этого метода стандартизации.

Сенсоры 7, 12, 20 и 21 показывают аналогичную тенденцию к снижению и должны быть включены для дальнейшей разработки модели.

Сенсоры 8 и 13 почти выглядят так, будто стандартизация не полностью работала к концу, так как сигнал все еще немного прыгает вверх и вниз. Я думаю, что их тенденции похожи на тенденции датчиков 9 и 14 (см. Ниже), только немного шумнее. Мы их пока оставим.

Сенсоры 9 и 14 похожи на сенсоры 8 и 13, но менее шумны. Я бы также рассмотрел их для дальнейшей разработки модели.

Последним и также наименее значимым (каламбур) является датчик 18, который, как ни странно, не хранит никакой информации после стандартизации на основе условий. Мы должны оставить это без внимания.

Подводя итог, можно сказать, что датчики, которые кажутся пригодными для использования после стандартизации на основе условий:

Теперь мы можем подобрать новую модель и проверить результаты.

Потери при проверке снизились более чем на 100 баллов, что является хорошим знаком. Давайте оценим, чтобы увидеть полный эффект стандартизации на основе условий.

# returns:
# train set RMSE:19.35447487320054, R2:0.7842178390649497
# test set RMSE:29.36496528407863, R2:0.7018485932169383

С тестовым среднеквадратичным значением 29,364 мы уже достигли улучшения на 10,04% по сравнению с нашей базовой моделью. Посмотрим, сможем ли мы улучшить его еще больше.

Отстающие переменные

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

Строка 2 содержит данные двух предшествующих ей строк. Строки, в которых вводятся NA, опускаются, поскольку модель с ними не справляется. Следовательно, добавление большого количества задержек сильно влияет на размер вашего набора данных. Давайте обучим модель с запаздывающими переменными, чтобы увидеть, улучшится ли производительность.

Похоже, потеря валидации уменьшилась еще на 50 пунктов. Давайте оценим, чтобы увидеть полный эффект.

# returns:
# train set RMSE:17.572959256116462, R2:0.8236048587786006
# test set RMSE:29.075227321534157, R2:0.7077031620947969

Мы добились небольшого улучшения. Однако модель, кажется, начинает переоснащаться через несколько эпох, мы постараемся бороться с этим позже.

Несколько слов о стационарности и сглаживании

Изначально я пытался сделать данные стационарными. Как объясняется в моем сообщении о таймсериях, стационарные данные подразумевают, что статистические свойства сигнала не меняются со временем. Благодаря этой стационарности статистические модели смогут надежно предсказывать будущие значения.

Вы можете использовать тест adfuller, чтобы проверить, являются ли ваши данные стационарными. Если это не так, вы можете изменить свои данные один раз, чтобы вывести их из тенденции и снова протестировать. Сравнивая свои данные, вы вводите NA, так как первая строка не может отличаться от какой-либо предыдущей. Строки с NA должны быть отброшены, что в конечном итоге повлияет на то, сколько лагов мы можем добавить, что является первым аргументом против того, чтобы ваши данные оставались стационарными в этом сценарии. Поскольку некоторые механизмы в наборе тестов имеют очень ограниченное количество строк, и мы уже вводим NA, добавляя переменные с запаздыванием.

Теперь давайте проверим стационарность наших данных после стандартизации на основе условий.

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

Представляем сглаживание

Для сглаживания я решил реализовать экспоненциально взвешенное скользящее среднее. Эта функция сглаживания довольно проста, но очень эффективна. По сути, он принимает во внимание текущее значение и предыдущее отфильтрованное значение при вычислении отфильтрованного значения (см. Упрощенную формулу ниже) [7].

~Xt = a*Xt + (1 - a)*~Xt-1

Где ~ Xt - отфильтрованное значение Xt, а α - сила фильтра. Значение альфа находится в диапазоне 0–1. Когда альфа равна 0,8, отфильтрованная точка данных будет состоять из 80% значения в Xt и 20% (уже отфильтрованного) значения в Xt-1. Следовательно, более низкие значения альфа будут иметь более сильный эффект сглаживания.

К счастью, Pandas уже реализовал этот тип фильтра в своей экспоненциально взвешенной функции [8]. Теперь давайте проверим стационарность наших данных после стандартизации и сглаживания на основе условий.

Таким образом, после сглаживания сигнал больше не считается стационарным. В зависимости от значения альфа (помните, более низкие значения указывают на более сильное сглаживание) данные будут считаться все менее и менее стационарными, поскольку общая тенденция станет более очевидной, когда шум в сигнале сглаживается.

Таким образом, для достижения стационарности потребуется все больше и больше различий, что приведет к большему сокращению строк в вашем наборе данных. В попытке достичь стационарности значения альфа ниже 0,69 приведут к тому, что все строки некоторых двигателей в тестовом наборе будут полностью отброшены, чего мы хотим избежать. Однако эффект фильтрации со значениями альфа ›= 0,69 не так силен и, следовательно, не сильно улучшает производительность модели. В конце концов, я решил отказаться от стационарности, поскольку более сильное сглаживание дало лучшую производительность модели.

Давайте добавим сглаживания к нашей подготовке данных и переобучим нашу модель, чтобы увидеть, где мы находимся.

# returns:
# train set RMSE:15.916032412669667, R2:0.85530069539296
# test set RMSE:27.852681524828476, R2:0.731767185824673

Отлично, наш тест RMSE немного снизился до 27,853. Я хочу проверить еще кое-что. Используя ту же модель, мы увеличим количество эпох, чтобы увидеть, как будет вести себя потеря валидации. Если он остается относительно постоянным для большего количества эпох, это означает, что мы можем использовать больше эпох при настройке гиперпараметров.

# returns:
# train set RMSE:19.784558538181454, R2:0.7764114588121707
# test set RMSE:32.17059484378398, R2:0.6421540867400053

Среднеквадратичное значение теста значительно увеличилось, но можно настроить между 10–30 эпохами, учитывая, что мы также добавим отсев для борьбы с переобучением. Теперь у нас есть все компоненты предварительной обработки, чтобы начать настройку гиперпараметров.

Настройка гиперпараметров

Мы потенциально можем настроить множество гиперпараметров, о которых я расскажу ниже. Чтобы уменьшить сложность, я решил не настраивать их все.

  • Альфа: сила нашего экспоненциального сглаживающего среднего фильтра
  • Лаги: предыдущие временные интервалы, которые нужно добавить в строку. Я предпочитаю не настраивать этот параметр.
  • Эпохи: количество раз, когда данные передаются в NN. Больше эпох позволяет лучше учиться, но также дает возможность переобучения.
  • Количество слоев в нашей сети, я предпочитаю не настраивать этот параметр
  • Узлов на слой: количество узлов в каждом слое.
  • Выпадение: доля выходов узлов в слое, которая будет установлена ​​на ноль, выпадение помогает избежать переобучения [9]
  • Оптимизатор и скорость обучения, я предпочитаю не настраивать этот параметр
  • Функция активации, функции активации можно рассматривать как форму постобработки выходных данных слоя. Например, после вычисления выходов известная активация relu установит любой отрицательный выход в ноль.
  • Размер пакета: количество образцов, переданных в сеть до обновления весов [10]

Мы не можем использовать настройку гиперпараметров нашего случайного леса с прошлого раза. Поскольку указанные выше параметры необходимо настраивать в разных местах, например данных, архитектуре и настройке NN, нам нужно будет написать собственный код.

Начнем с определения гиперпараметров, функций для подготовки наших данных и создания модели.

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

Теперь блок кода для настройки гиперпараметров довольно велик. Сначала ознакомьтесь с кодом и прочтите мое объяснение ниже.

Как и в прошлый раз, реализованный здесь тип настройки гиперпараметров можно рассматривать как случайный поиск. 60 итераций должно быть достаточно, чтобы получить 95% лучшего решения [11], большее количество итераций приблизит вас к лучшему решению. Я установил количество итераций на 100. Для каждой итерации мы случайным образом отбираем значения гиперпараметров из наших списков определенных параметров. На основе этих параметров выполняется предварительная обработка набора данных и создание модели. Мы будем использовать представленное ранее групповое разбиение для перекрестной проверки, однако для настройки гиперпараметров мы будем использовать 3 разбиения.

После обучения мы сохраняем использованные параметры, среднее значение и стандартное отклонение потери валидации. Стандартное отклонение потерь при проверке показывает, насколько надежна ваша модель в проверочных разделах набора данных. Давайте посмотрим на результат.

Как видите, общие параметры могут сильно повлиять на производительность модели: лучшая модель имеет среднюю потерю проверки 171,19, а худшая модель - среднюю потерю проверки 3640,33, что в 21 раз хуже!

Финальная модель

Мы тренируем нашу финальную модель на основе лучших параметров.

# returns:
# train set RMSE:12.82085148416833, R2:0.9061075756420954
# test set RMSE:25.352943890689797, R2:0.7777536332595578

С RMSE 25,353 мы улучшились на 22,33% по сравнению с нашей базовой моделью, замечательно! Это можно было бы продвинуть немного дальше, настроив задержки, количество слоев, оптимизатор и скорость обучения.

Полную записную книжку вы можете найти на моей странице на github здесь. Я хотел бы поблагодарить Майкеля Гроббе за его вклад и рецензирование моей статьи. В следующий раз мы углубимся в последний набор данных и LSTM. Есть вопросы или замечания? Позвольте мне знать в комментариях ниже!

Ссылки:
[1] https://keras.io/getting_started/faq/#how-can-i-obtain-reproducible-results-using-keras-during-development
[2] Https://stackoverflow.com/questions/32419510/how-to-get-reproducible-results-in-keras/59076062#59076062
[3] https://www.onlinemathlearning.com/probability -without-replace.html
[4] Важность формирования проблем для решений по контролируемому профилактическому обслуживанию
[5] Ф.О. Хаймс, Рекуррентные нейронные сети для оценки оставшегося срока полезного использования , Международная конференция по прогнозированию и управлению здоровьем, 2008 г., Денвер, Колорадо, 2008 г., стр. 1–6, doi: 10.1109 / PHM.2008.4711422.
[6] https://en.wikipedia.org / wiki / Многослойный_перцептрон
[7] Дуарте Паша, Г., Пайшан де Медейруш, И., и Йонеяма, Т. (2019). Методы прогнозирования на основе нейронных сетей, инвариантных к рабочему состоянию, применяемые на турбовентиляторных авиационных двигателях. Ежегодная конференция общества PHM, 11 (1). Https://doi.org/10.36001/phmconf.2019.v11i1.786
[8] https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame .ewm.html
[9] https://www.tensorflow.org/tutorials/keras/overfit_and_underfit#add_dropout
[10] https://www.tensorflow.org/api_docs / python / tf / keras / Последовательный
[11] Чжэн, Алиса. Оценка моделей машинного обучения. O’Reilly Media, Inc., 2015 г.