Вопрос или проблема
У меня есть процесс, который (проще говоря), запускается каждые 5 минут, собирает данные и записывает эти данные в базу данных.
Более подробное объяснение: процесс запускается, собирает данные (что занимает некоторое время) и размещает их в топике kafka (что также занимает некоторое время). Наконец, данные из топика kafka обрабатываются базой данных (что также занимает некоторое время).
Каждая запись в базе данных имеет время вставки, округленное до секунды.
Когда я подсчитываю записи (за 4 часа) по времени вставки, график выглядит так:
Если я подсчитываю записи по интервалам в 5 минут, график выглядит так:
На этом графике видно, что все точки находятся примерно на одном уровне (слегка выше 7000), но точка, отмеченная красной стрелкой, и её сосед слева находятся ниже 7000.
Минимум, среднее и максимум для этих подсчетов за 5 минут:
min 6262
mean 7154
max 7186
Так как точка, отмеченная красной стрелкой, примерно на 12% ниже среднего или максимума, мы можем (возможно) считать её аномалией.
Я знаком с несколькими алгоритмами обнаружения выбросов/аномалий в машинном обучении, но я не уверен, как их использовать, когда новые данные постоянно поступают в базу данных. Что бы я ни делал, я бы хотел избежать использования фиксированных порогов (например, если количество падает на 10% ниже среднего, поднять тревогу).
Например, точка, отмеченная красной стрелкой на графике выше, появилась 2021-01-06 14:30:00, так что через несколько минут я должен был бы поднять тревогу из-за этого.
На данный момент это процедура, которую я придумал в отношении этого процесса сбора данных за 5 минут. Следующее будет выполняться каждые 5 минут:
- взять из базы данных последние несколько часов (временное окно) подсчетов за 5 минут (периоды n)
- отбросить последний период (n), так как он может быть не завершен (записи еще не в базе данных)
- использовать какой-то ML алгоритм (пока не уверен какой) на временном окне (до n-2), чтобы увидеть, является ли подсчет за последний период (n-1) аномалией
- если аномалия, поднять тревогу
- исключить аномальную точку данных из будущих сборов данных на шаге 1.
Я не уверен, что это хороший подход.
Если кто-то делал что-то подобное раньше с потоком данных, пожалуйста, поделитесь своим опытом в этом вопросе.
Если кому-то нужно увидеть набор данных, вы можете найти его на https://pastebin.com/UaXeEjq9 в формате csv.
Попробуйте изучить Алгоритм Надежного Случайного Леса Разрезов (RRCF). Есть реализация на Python, поддерживающая потоковые данные, где вы создаете скользящие окна (называемые “shingles”): https://github.com/kLabUM/rrcf
RRCF строит бинарное дерево решений, случайным образом выбирая число между минимумом и максимумом вашей переменной и разделяя данные там. Если точка оказывается одна после разделения, она становится листом в дереве. Чем больше точка отделена от остальной части данных (то есть чем больше она является выбросом/аномалией), тем вероятнее, что она станет листом выше в дереве. Это хорошо работает с многомерными данными, поскольку алгоритм просто будет случайно разделять все переменные.
Вот видео, которое объясняет RRCF лучше, чем я мог бы в письменном посте: https://youtu.be/yx1vf3uapX8?t=355
Ответ или решение
Обнаружение аномалий в почти постоянном потоке данных — задача, требующая внимательного подхода и грамотного выбора метода. Давайте разберем процесс и предложим возможное решение с использованием алгоритмов машинного обучения для работы с потоковыми данными.
Введение в проблему
У вас есть процесс, который каждые 5 минут собирает данные, помещая их в базу данных через Kafka. Эти данные сохраняются с точностью до секунды, и анализируя их по интервалам в 5 минут, вы заметили аномалии, как, например, в точке, отмеченной красной стрелкой на предоставленном графике.
Основной целью является автоматическое выявление таких аномалий без использования фиксированных порогов, таких как «ниже среднего на 10%», чтобы система могла самой адаптироваться к изменениям в потоке данных.
Предложенное решение
-
Использование маштабируемого алгоритма RRCF: Рассмотрите алгоритм Robust Random Cut Forest (RRCF), который идеально подходит для работы с потоковыми данными. Он использует метод построения бинарного дерева решений, который позволяет автоматически выявлять выбросы, вычисляя высоту листа в дереве. Чем выше лист, тем более вероятно, что это аномалия. RRCF особенно полезен для многомерных данных, что делает его универсальным инструментом.
-
Построение временного окна: Каждые 5 минут извлекайте данные за последние несколько часов, исключая самый последний интервал, так как данные могут быть еще не полными. Это позволит построить более надежную модель без ложных срабатываний на неполных данных.
-
Обработка и обучение модели: Примените RRCF на временное окно данных, игнорируя последние 1-2 интервала, чтобы определить, является ли новый набор данных аномалией. Это позволит адаптировать и обучить модель без необходимости ручной настройки параметров.
-
Обнаружение и сигнализация: Если последнее изменение в потоке данных считается аномалией, сгенерируйте сигнал тревоги. Это может быть реализовано как уведомление или запись в лог.
-
Исключение из будущих анализов: Исключите обнаруженные аномальные точки из будущих обучающих наборов данных, предотвращая искажение модели.
Дополнительные рекомендации
- Тестирование и валидация: Необходимо тщательно протестировать выбранный подход на исторических данных, чтобы убедиться в корректности обнаружения аномалий и предотвратить ложные срабатывания.
- Динамическая адаптация: Регулярно обновляйте модель с учетом новых поступающих данных, чтобы поддерживать актуальность анализа.
- Оптимизация ресурсов: Убедитесь, что построение модели эффективно с точки зрения ресурсов и не создает дополнительных задержек в обработке данных.
Использование данного подхода поможет вам организовать интеллектуальную систему мониторинга и оперативно реагировать на изменения в потоках данных, что очень важно в сценарии, где данные поступают непрерывно и быстро изменяются.
Надеюсь, предложенное решение и объяснение помогут вам эффективно управлять потоковой обработкой данных и обнаружением аномалий.