Skip to the content.

Эксперимент 2026-05-26: anomaly detection по NDVI-кривым

Постановка

Найти поля-выбросы среди 20 рисовых чеков Темрюкского района по их сезонным NDVI-кривым. Использовать сразу несколько независимых методов и проверить согласованность – это даёт устойчивость к выбору алгоритма.

Дизайн

Три метода, на одних и тех же данных:

Метод 1: Pointwise z-score

Для каждой даты считаем медиану и MAD (median absolute deviation) NDVI по 20 полям. Для каждого поля считаем z = (ndvi_f - median_все_поля) / MAD. Пиксельный порог |z| > 2. По полю агрегируем:

Сильная сторона: показывает не только «насколько», но и «когда» происходила аномалия. Слабость: чувствителен к шуму единичных дат.

Метод 2: IsolationForest

На тех же 18 фичах, что у LightGBM в дне 6. contamination=0.15 (3 аномалии из 20 ожидаемых). n_estimators=200, random_state=42. Чем ниже decision_function – тем аномальнее. Инвертируем знак для интерпретации «высокий score = аномалия».

Сильная сторона: учитывает многомерную структуру (форма кривой через 10 NDVI-фичей сразу). Слабость: чёрный ящик, объяснение через permutation тяжёлое.

Метод 3: L2-distance от медианной кривой

Сглаженная NDVI-кривая поля (rolling 21d, daily grid 361 точка) сравнивается с медианной кривой по 20 полям через L2-норму. Одно число – общее «расстояние от стаи».

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

Объединение

Каждое поле получает 3 ранга (1 = самый аномальный). Финальная метрика mean_rank = mean(rank_z, rank_iso, rank_l2). Top-K=3 по этому рангу – финальный список выбросов.

Результаты

Top-3 аномалий

field_id mean_rank rank_z rank_iso rank_l2   z count iso_score L2
F004 1.00 1 1 1 164 0.066 2.88    
F005 2.33 2 2 3 197 0.056 2.51    
F017 3.33 3 5 2 207 -0.022 2.59    

F004 – абсолютный лидер во всех трёх методах. F005 и F017 уверенно входят в top-3 у двух методов из трёх.

Согласованность методов (Spearman ρ по 20 рангам)

  Z-total IsoForest L2
anomaly_z_total 1.00 0.70 0.96
isoforest_score 0.70 1.00 0.79
l2_from_median 0.96 0.79 1.00

Высокая корреляция Z ↔ L2 (0.96) – ожидаемо: оба строятся над одним сглаженным сигналом. IsolationForest даёт ρ=0.70-0.79 – независимый сигнал, но направление то же. Top-3 по объединённому рангу согласуется со всеми тремя методами – это и есть устойчивый сигнал.

Интерпретация выбросов

field_id NDVI peak doy_peak yield (синтетический) Природа аномалии
F004 0.77 187 (05 июля) 63.11 ц/га Максимум по всем метрикам. Высокая биомасса, ранний и устойчивый пик. Это «лучшее» поле.
F005 0.45 141 (20 мая) 47.58 ц/га Минимум урожая. Низкая биомасса, рано «упал» в воду. Подозрение на пересев или другую культуру в ротации.
F017 0.61 134 (13 мая) 57.09 ц/га Сдвинутый сезон. Самый ранний пик из всех 20 полей. На heatmap виден зимний минимум вместе со всеми, но весной пик опережает остальных на 2-3 недели. Скорее всего раннее затопление чека.

Anomaly-детектор находит и положительные, и отрицательные выбросы – это важно для агро-страхования: «вот поле, которое существенно отличается от соседей в любую сторону, посмотрите внимательнее».

Важное ограничение (для портфолио)

В индустриальной задаче «исторический коридор» строится из multi-year данных по тому же полю: 5 лет NDVI 2020-2024 даёт коридор p10-p90 на каждый календарный день. Поле сравнивается со своей же историей.

В нашем pet-проекте данные за один год, поэтому коридор построен по соседним полям того же года – это слабый proxy. Соседние поля могут отличаться сортом, датой затопления, фазой ротации (рис → пшеница → пар). Этот выбор зафиксирован честно в коде и в этом отчёте.

При расширении датасета на 5 лет (data/processed/ndvi_series.csv структурно к этому готов – только нужны больше запросов к STAC API) пересчитать тривиально: то же pointwise_z, но median и MAD строятся по 5 годам на каждый календарный день, а не по 20 полям одного года.

Что доказано

  1. Три независимых метода сходятся. Spearman ρ от 0.70 до 0.96 между парами. Top-3 одинаков для всех. Это признак устойчивого сигнала, а не артефакта одного алгоритма.
  2. Heatmap z-score читается как агрономический документ. Видны не только «какие поля», но и «когда» отклонялись от группы.
  3. Anomaly score интегрируется с моделью прогноза. Если поле в top-K по anomaly, его прогноз LightGBM (или линейной модели) нужно сопровождать предупреждением «out-of-distribution» – это валидный downstream-сигнал для UI Дня 8.
  4. Подход осознанно прост. Использован минимум алгоритмов, всё интерпретируется. На реальных multi-year данных можно добавить более сложные методы (DTW, autoencoder, prophet-residuals) – но они доказывают себя только когда у baseline-подходов кончается воздух.

Что дальше

Артефакты