Инструменты и прототип ML-системы предиктивной аналитики для карьерных самосвалов (подход универсален для экскаваторов и самосвалов). Проект объединяет данные телеметрии, результаты лабораторного анализа масла и логи простоя техники, чтобы обнаруживать аномалии и предсказывать возможные аварии задолго до их появления.
Цель работы: раннее выявление деградации и нештатного поведения, а не фиксация аварийных событий.
- Задача НЕ:
- поиск выбросов
- поиск редких значений
- Правильная формулировка задачи:
- Поиск устойчивых отклонений телеметрии экскаватора от нормального поведения при сопоставимых режимах работы
- Это автоматически требует:
- режимной нормализации
- оконных признаков
- обучения на «норме»
- Нельзя обучаться на смешанных данных всех экскаваторов , тк у каждого экскаватора:
- своя кинематика
- свой ноль датчиков
- свой «здоровый профиль»
- Разделить пайплайн по excavator_id
- Все шаги ниже выполнять внутри одной машины
- Агрегировать результат на уровне парка только в конце
Что видно из describe
- -1e6
- 0 как возможный placeholder
- огромные плато нулей по углам
Kaggle best practice
Проблемы с качеством данных ≠ аномалии
Перед обучением любой модели необходимо:
- выделить технические аномалии:
- -1e6
- физически невозможные углы
- резкие скачки → 0 → нормальные
- либо:
- выкинуть
- либо пометить отдельным флагом
📌 Это НЕ аномалии эксплуатации, их нельзя давать в Модель.
Модель видит:
- стоянку
- маневр
- движение
- поворот стрелы
как один и тот же режим → отсюда ложные аномалии
Поэтому правильно: Аномалия = необычно для ЭТОГО режима
Необходимо определить режимы (квазистационарные состояния машины):
- стоянка (gps_speed_kmh ≈ 0)
- движение
- поворот платформы
- активная работа стрелы / рукояти
Далее:
- либо отдельная модель на режим
- либо режим как входной признак
📌 Без этого твой IF всегда будет шуметь.
Промышленные аномалии носят протяжённый во времени характер, а не мгновенный характер
Поэтому необходимо ввести оконные признаки:
- окна: 30с / 60с / 120с
- внутри окна:
- mean
- std
- min / max
- slope (тренд)
- diff
📌 После этого понизится размерность, повысится стабильность данных, понизится шум
Обучать детектор аномалий только на здоровых данных
Поэтому надо:
- Определить proxy «нормы»:
- первые N дней месяца
- или периоды без резких изменений
- или кластеры с низкой дисперсией
- Обучать модель только на этих данных
- Применять — на всём периоде
Важное уточнение Isolation Forest:
- не детектор временных аномалий
- детектор странных состояний
- contamination — технический параметр
- реальный порог считается постфактум
Нужно использовать Isolation Forest как один из скорингов, а не финальное решение
План**:
- Isolation Forest → anomaly_score_if
- Robust stats → anomaly_score_stat
- (позже) Autoencoder → anomaly_score_ae
- Финальный score = ансамбль
- Получить anomaly_score на train-норме: (взять q99.5 / q99.9)
- Применить к тесту отдельно по режимам
Одноточечные аномалии почти всегда являются шумом.
Необходимо:
- Считать плотность аномалий в окне (например, 5–10 минут)
- Аномалия = если:
- anomaly_score высокий
- и держится во времени
📌 Это резко снижает false positive.
Не просто «красная точка» , а:
- какие признаки
- в каком режиме
- как долго
Необходимо:
- сохранять contribution признаков (IF feature importance proxy)
- показывать:
- «аномальный тренд угла + нулевая скорость»
- «несоответствие кинематики»
For each excavator we perform regime-aware sliding-window feature extraction, train anomaly detectors on healthy data only, use an ensemble of Isolation Forest and robust statistical detectors, apply quantile-based adaptive thresholds and aggregate anomaly scores over time to reduce noise.
Для каждого экскаватора мы выполняем извлечение признаков с помощью скользящего окна с учетом режима работы, обучаем детекторы аномалий только на здоровых данных, используем ансамбль детекторов Isolation Forest и надежных статистических детекторов, применяем адаптивные пороговые значения на основе квантилей и агрегируем оценки аномалий во времени для снижения шума.
outputs/
└── anomalies/
└── <excavator_id>/
├── anomaly_report.txt
├── gps_speed_kmh.html
├── heading_angle_deg.html
└── ...