От временных рядов к изображениям… Спрашивая CNN, «когда произойдет следующая ошибка?»

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

В этом посте я разработал решение для машинного обучения, позволяющее прогнозировать оставшийся полезный срок службы (RUL) конкретного компонента двигателя. Этот вид проблемы играет ключевую роль в области профилактического обслуживания, где цель состоит в том, чтобы сказать: «Сколько времени осталось до следующей неисправности? '. Для достижения этой цели я разработал сверточную сетевую сеть в Keras, которая работает с временными рядами в форме изображений.

НАБОР ДАННЫХ

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

Набор данных для моделирования деградации турбовентиляторных двигателей, предоставленный НАСА, становится важным эталоном при оценке оставшегося срока службы (RUL) для парка двигателей одного типа ( Всего 100). Данные доступны в виде временных рядов: 3 рабочих режима, 21 измерение датчика и цикл, то есть наблюдения с точки зрения времени на срок службы.

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

Чтобы лучше понять это объяснение, мы попытаемся взглянуть на данные:

train_df.id.value_counts().plot.bar()

У двигателей разный срок службы. Среднее время работы с данными поезда составляет 206 циклов, минимум 128 и максимум 362 цикла.

Рабочие настройки и измерения датчиков в составе комплекта для отдельного двигателя показаны ниже:

engine_id = train_df[train_df['id'] == 1]
engine_id[train_df.columns[2:]].plot(subplots=True, sharex=True, figsize=(20,30))

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

ПОДГОТОВЬТЕ ДАННЫЕ

Чтобы предсказать RUL для каждого двигателя, мы применили подход к классификации, создав ярлык самостоятельно следующим образом:

От 0 (неисправность) до 15 оставшихся циклов мы обозначили как 2; от 16 до 45 циклов мы обозначили как 1, а остальные (›46) как 0. Очевидно, что в реалистичном сценарии категория, обозначенная как 2, является наиболее экономически ценной. Прогнозирование этого класса с хорошими характеристиками позволит нам выполнять адекватную программу технического обслуживания, избегая ошибок в будущем и экономя деньги.

Чтобы иметь в нашем распоряжении максимальное количество данных для поезда, мы разбиваем ряды с фиксированным окном и скользящим шагом в 1 шаг. Например, двигатель 1 имеет 192 цикла в последовательности, при длине окна, равной 50, мы извлекаем 142 временных ряда длиной 50:
window1 - ›от cycle0 до цикла50, window2 -› от цикла1 до цикла51,… , window142 - ›from cycle141 to cycle50, window191. Каждое окно помечено соответствующей меткой последнего цикла, учитываемого окном.

sequence_length = 50
def gen_sequence(id_df, seq_len, seq_cols):
data_matrix = id_df[seq_cols].values
    n_elem = data_matrix.shape[0]
    for a,b in zip(range(0,n_elem-seq_len), range(seq_len,n_elem)):
        yield data_matrix[a:b,:]
        
def gen_labels(id_df, seq_len, lab):
    
    data_matrix = id_df[lab].values
    n_elem= data_matrix.shape[0]
    return data_matrix[seq_len:n_elem,:]

ОТ ВРЕМЕННЫХ СЕРИЙ К ИЗОБРАЖЕНИЯМ

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

Я создал изображения по этому удивительному ресурсу. Идея проста ... когда мы пытаемся преобразовать временные ряды в изображения, мы всегда используем спектрограмму. Это разумный выбор, но не всегда лучший (как можно прочитать здесь). В этом посте автор объясняет свое обоснованное недоумение по поводу работы с аудиорядом с представлением спектрограммы. Он говорит о звуке, но смысл можно передать в нашем сценарии. Спектрограммы мощные, но их использование может привести к потере информации, особенно если мы попытаемся подойти к проблеме с точки зрения компьютерного зрения. Чтобы быть эффективной, 2D CNN требует пространственной инвариантности; это основано на предположении, что элементы классического изображения (например, фотографии) несут одно и то же значение независимо от их местоположения. С другой стороны, спектрограмма подразумевает двухмерное представление, состоящее из двух разных единиц (частоты и времени).

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

from scipy.spatial.distance import pdist, squareform
def rec_plot(s, eps=0.10, steps=10):
d = pdist(s[:,None])
    d = np.floor(d/eps)
    d[d>steps] = steps
    Z = squareform(d)
    return Z

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

МОДЕЛЬ

На этом этапе мы готовы построить нашу модель. Я принял классическую архитектуру 2D CNN:

model = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(50, 50, 17)))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(3, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

Я поместил его всего на 10 эпох и получил ТОЧНОСТЬ 0,832%.

Из матрицы неточностей мы видим, что наша модель может хорошо различать, когда двигатель близок к отказу (2 метки: ‹осталось 16 циклов) или когда он работает нормально (0 метка:› 45 циклов). В промежуточном классе присутствует немного шума (›15,‹ 46 циклов). Мы довольны тем, что достигли отличного и четкого результата для предсказания класса 2 - то есть близкого к отказу.

РЕЗЮМЕ

В этом посте мы пытаемся решить проблему профилактического обслуживания. Оценивая RUL двигателей, мы стараемся иметь дело с редкими событиями из-за сложности сбора таких данных. Мы предлагаем интересное решение преобразования временных рядов в изображения с использованием графиков повторяемости. Таким образом, мы можем различать скважинные двигатели, срок службы которых подошел к концу.

ПРОВЕРИТЬ РЕПО НА GITHUB

Оставайтесь на связи: Linkedin