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

В этой статье я хотел бы поделиться подходом к использованию потоковых данных путем настройки панели мониторинга путем регистрации статистических профилей потоковых данных. Для этого я буду использовать подводный аппарат с дистанционным управлением (ROV) в качестве варианта использования. В частности, мы будем отслеживать неисправности OpenROV v2.8 последнего OpenROV (ныне Sofar), недорогого телероботического подводного дрона. Чтобы расширить наши возможности по обнаружению неисправностей, мы будем использовать регрессионную модель, обученную на платформе SKLearn, для моделирования поведения нашего автомобиля. Таким образом, наша панель мониторинга будет служить двум целям: отслеживать проблемы с производительностью и качеством регрессионной модели, но также (и в основном) отслеживать состояние самого транспортного средства. Поскольку намеренное взлом ROV было бы проблематичным, мы вручную добавим некоторые неисправности датчиков в наши данные и, будем надеяться, сможем обнаружить эти неисправности с помощью нашей приборной панели.

В качестве платформы для регистрации данных мы будем использовать whylogs, библиотеку с открытым исходным кодом от WhyLabs, предназначенную для мониторинга данных из приложений ML / AI. Whylogs рассчитывает приблизительную статистику для зарегистрированных записей, что означает, что это подходящий выбор для конвейеров с большими объемами данных. Несмотря на то, что в этом примере используется минимальный объем информации, приятно знать, что выбранные инструменты допускают возможное расширение в будущем.

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

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

Оглавление

  1. Обзор
  2. Что у нас получается
  3. Внедрение неисправностей
  4. Разработка приложения
    Настройка Kafka
    Создание клиентов Kafka
    Производитель телеметрии
    Производитель прогнозов
    Регистратор телеметрии
    Регистратор прогнозов
    Регистратор сеансов
  5. Панель мониторинга
    Сеанс 0 - Ошибка постоянного усиления
    Сессия 1 - Застрял в (ноль)
    Сессия 2 - Зависание (максимум)
    Сессия 3 - Дрейф и потеря
  6. Заключение

Обзор

Давайте подробнее рассмотрим наш эксперимент.

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

Следующим компонентом является производитель прогнозов, который использует тему телеметрии для создания прогнозов с помощью обученной регрессионной модели и передает результаты в отдельную тему прогнозирования. В этом случае регрессионная модель использует телеметрическую информацию для прогнозирования следующего временного шага для одной конкретной функции - GYROZ, которая представляет собой угловую скорость ROV в направлении рыскания ( как быстро поворачивает автомобиль). Модель регрессии представляет собой модель линейной регрессии методом наименьших квадратов с регуляризацией L2 и полиномиальными базисными функциями, которая была обучена примерно за 24 часа работы ROV с использованием библиотеки SKLearn.

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

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

Что мы в итоге получаем

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

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

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

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

Инъекция неисправностей

В этом эксперименте мы будем использовать данные 4 отдельных рабочих сеансов, каждый из которых имеет продолжительность от 4 до 9 минут. В каждом сеансе примерно в половину времени вводится сообщение о неисправности датчика GYROZ длительностью 5 с. Вы можете просмотреть файлы JSON с уже введенными ошибками в репозитории проекта в папке rov_data.

На рисунке ниже типы инжектированных неисправностей показаны оранжевым цветом в виде образца синусоидального сигнала. В сеансе 0 вводится ошибка постоянного усиления, в которой реальное значение искажается путем умножения постоянного коэффициента, как показано в a). Ошибка застревания моделируется в обоих сеансах 1 и 2, и отличается значением, на котором он «застревает» - в то время как в сеансе 1 значение GYROZ застревает на значении 0, как показано на b) в сеансе 2 зафиксировано значение 5,56, что соответствует максимальному диапазону датчика гироскопа ROV. Наконец, в сеансе 3 вводится ошибка датчика дрейфа, как показано в c). Эта неисправность имитирует состояние, при котором реальное значение искажается добавлением значения, которое увеличивается во времени по отношению к началу неисправности.

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

Разработка приложения

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

Настройка Kafka

Прежде чем продолжить, нам нужно настроить нашу потоковую платформу с Kafka. Мы имеем дело с низкой пропускной способностью производителей, поэтому для этого проекта будет достаточно настроить локальную Kafka с Docker. Для этого вы можете следовать этому руководству. Пошаговые инструкции очень хорошо объяснены в статье, но для очень короткой версии вы можете просто скопировать файл docker-compose.yml в нужную папку, а затем запустить docker-compose up. . Естественно, для этого шага вам потребуется установить Docker.

Когда контейнеры будут готовы, вы можете войти в kafka-tools интерфейс командной строки с помощью:

docker exec -it kafka /bin/sh

И проверьте доступные темы, чтобы убедиться, что они работают:

kafka-topics --list --bootstrap-server localhost:9092

Создание клиентов Kafka

В следующих скриптах Python нам придется много создавать потребителей и производителей Kafka. Давайте определим две простые функции для создания клиентов, чтобы мы могли повторно использовать их в будущем:

В обоих случаях клиентам сообщается адрес, с которым они должны связаться, чтобы загрузить начальные метаданные кластера. Кроме того, поскольку мы производим / используем значения в формате JSON, нам необходимо указать правильную обработку для него с помощью аргументов vaue_serializer / value_deserializer.

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

Для получения дополнительной информации об интеграции журналов почему с Kafka вы можете обратиться к этой записной книжке и этой записи блога на сайте WhyLabs.

Производитель телеметрии

Теперь, когда у нас работает Kafka, мы можем начать с отправки данных ROV в нашу тему телеметрии. Во-первых, нам нужно создать Kafka Producer Client, который будет публиковать записи в нашем кластере и читать файлы с кодировкой JSON в папке rov_data, чтобы создать список словарей:

Как мы видим, наши точки отбора проб состоят из ряда функций:

  • mtarg1, mtarg2, mtarg3: вводить команды, отправленные каждому из трех пропеллеров.
  • крен, тангаж, рыскание: угловое положение автомобиля относительно осей X, Y, Z.
  • LACCX, LACCY, LACCZ: угловое ускорение автомобиля вокруг осей X, Y, Z.
  • GYROX, GYROY, GYROZ: угловая скорость транспортного средства вокруг осей X, Y, Z.
  • SC1I, SC2I, SC3I: показания электрического тока от каждого гребного винта.
  • BT1I, BT2I: показания электрического тока от каждого из аккумуляторных блоков.
  • vout, iout и cpuUsage: напряжение, ток и загрузка ЦП микрокомпьютера BeagleBone ROV.

Теперь мы можем публиковать наши данные в нашей теме:

Если вы хотите, перед отправкой информации рекомендуется создать тему Kafka с соответствующими разделами / репликацией, введя atkafka-tools:

kafka-topics --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic telemetry-rov

Но в этом нет необходимости, поскольку он автоматически создает тему, если она еще не существует.

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

Продюсер прогнозов

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

Как и раньше, мы создаем клиент Consumer (для чтения из раздела телеметрии) и клиента Producer (для публикации в разделе прогнозов). Нам также необходимо загрузить нашу модель SKLearn, сохраненную с помощью joblib:

В нашей функции main скрипт будет непрерывно извлекать данные из темы и вычислять наши остатки для каждого прочитанного временного шага. Если прошло 10 секунд, а новые записи не поступили, мы выводим предупреждение, чтобы проинформировать пользователя.

Как только у нас есть данные для текущего и предыдущего временных шагов, вычисляется остаток:

Чтобы делать прогнозы, нам также необходимо загрузить скейлеры Min-Max, установленные в процессе обучения модели (BL_x.pickle и BL_y.pickle), чтобы мы могли преобразовать функции для прогнозирования и обратного преобразования для вывода немасштабированных остаточный.

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

Регистратор телеметрии

После того, как оба производителя Kafka настроены должным образом, мы можем начать регистрировать наши профили сеанса с помощью журналов whylogs. Записи опрашиваются из темы телеметрии и разделяются на отдельные сеансы. Если следующая точка отбора проб отделяется от последней более чем на 5 минут, текущий сеанс завершается и регистрируется перед началом следующего сеанса. Когда прошло более 10 секунд без новой информации, мы также считаем, что текущий сеанс завершен, и записываем результаты.

Регистратор прогнозов

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

Даже при номинальных условиях транспортного средства у нас могут быть скачки остаточной стоимости, что приводит к высокому уровню ложных срабатываний. Чтобы уменьшить это, мы вычисляем скользящее среднее остатка по разным временным рамкам. В этом примере мы будем регистрировать, помимо неизменного остатка, скользящее среднее для последних 5, 10 и 15 временных шагов. (1, 2 и 3 секунд):

Если для данного скользящего окна у нас есть nan значений или у нас просто недостаточно записей для расчета скользящего среднего, nan регистрируется для данной временной метки.

Регистратор сессий

Каждый раз, когда регистраторы завершают сеанс, вызывается функция log_session(), которая отвечает за инициализацию сеанса регистрации и протоколирование каждой записи данного сеанса.

Для этого давайте организуем наши данные в Pandas Dataframe, преобразуем наш столбец timestamp в объекты datetime, а затем разделим DataFrame на пакеты по 1 минуте каждый, используя df.groupby. Таким образом, каждый рабочий сеанс будет регистрироваться со статистическими профилями для каждой минуты активности ROV. Параметры key и freq сообщают нам столбец для группировки и частоту группировки соответственно.

Теперь, когда данные должным образом разделены на пакеты, мы можем вызвать session.logger() для каждого пакета данных, передавая dataset_timestamp, чтобы отметить начало каждого окна, и продолжить регистрацию каждого пакета.

Панель мониторинга

На этом этапе наши потребители слушают любые новые отправленные записи и записывают их в нашу папку вывода whylogs, которая, согласно конфигурационному файлу .whylogs.yaml, является whylogs-output папка. Остается использовать сгенерированные статистические профили для проверки рабочих сессий в поисках признаков введенных неисправностей.

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

Несмотря на то, что основной отслеживаемой функцией телеметрии является GYROZ, было бы полезно иметь простой способ проверки графиков для всех оставшихся функций. Что касается остаточных характеристик, мы могли бы проверить графики на наличие различных скользящих средних. Учитывая, что для любого из этих вариантов у нас есть 3 или 4 типа графиков, которые могут представлять интерес, было бы интересно централизовать все эти параметры на интерактивной панели мониторинга, где пользователь может выбрать конкретные графики, которые ему интересны. в этом проекте это было сделано в форме виджета iPython.

В этой статье я покажу только результаты работы виджета, но вы можете проверить полный код и подробное объяснение его в прилагаемом блокноте jupyter. В репозитории проекта вы найдете предварительно зарегистрированную информацию, так что вы можете сразу перейти к разделу панели инструментов. Только не забудьте установить ipywidgets:

python -m pip install ipywidgets

И включите расширение виджетов:

jupyter nbextension enable --py widgetsnbextension

Сессия 0 - Ошибка постоянного усиления

Теперь давайте посмотрим на несколько примеров вывода. Выбрав первый сеанс, нам будут представлены дата и время работы ROV, а также различные варианты телеметрии и графиков остатков:

В этом сеансе произошел сбой датчика постоянного усиления. Из рисунка выше сложно оценить только распределение GYROZ, поскольку разные шаблоны пилотирования приведут к разным распределениям, что является нормальным. Неизменная остаточная стоимость также не очень ясна. Но, применяя скользящую среднюю 3s, мы определенно начинаем замечать некоторые признаки необычного поведения. Это тот случай, когда только мониторинга сенсорной информации транспортного средства недостаточно для обнаружения неисправности.

Сессия 1 - Застрял в (ноль)

Давайте продолжим наш второй пример, сеанс 1:

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

Сессия 2 - Застрял (максимум)

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

Это довольно легко обнаружить, поскольку максимальное значение действительно выше обычного распределения. Графики телеметрии и остаточного распределения согласны с тем, что около 21:13 произошло что-то ненормальное.

Сессия 3 - Дрейф и потеря

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

Остатки регистрируются с nan значениями всякий раз, когда у нас нет действительного предыдущего временного шага. Следовательно, для точек выборки первого сеанса ожидаются недостающие значения. Однако, когда они появляются в середине цикла, это признак того, что между двумя точками выборки прошел длительный период (›0,5 с), что указывает на ошибку потерь. Несмотря на то, что мы напрямую не отслеживаем ошибки потерь, мы можем увидеть их присутствие ближе к концу выполнения, примерно в 09:14.

Заключение

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

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

Что касается самого приложения, здесь тоже есть много возможностей для расширения. В этом примере мы использовали Kafka локально в демонстрационных целях, но я уверен, что в производственной среде все может быть сложнее. Может быть, в будущем у нас может быть целый парк ROV, который будет автоматически отслеживаться на предмет неисправностей!

На этом пока все! Спасибо за чтение, и если у вас есть какие-либо вопросы или предложения, не стесняйтесь обращаться к нам!