Эксперимент 2026-05-26: LightGBM baseline для прогноза урожайности
Постановка
Прогноз урожайности риса по полям Темрюкского района Краснодарского края.
Датасет – 20 строк × 22 колонки (см. data/processed/fields_features.csv).
Из них 18 числовых фичей, 1 синтетический таргет yield_centner_ha, 3 поля метаинфы (field_id, crop_osm, ndvi_date_peak).
Важная оговорка: таргет синтетический, сгенерирован в feature_engineering.py
по правилу yield = 55 + 30*(NDVI_peak - median) + N(0, 2). Реальной пол-уровневой
урожайности риса в открытом доступе нет (Росстат публикует на районном уровне с задержкой).
Это означает: метрики честные относительно pipeline и feature engineering, но не доказывают
качество модели на реальных данных. Для реальной задачи нужен multi-year + multi-region датасет.
Дизайн оценки
- Cross-validation: Leave-One-Out (LOO). Для каждой из 20 строк модель учится на 19, предсказывает 20-ю. Это даёт честные out-of-sample предсказания и метрики.
- Метрики: MAPE, MAE, RMSE, R². MAPE удобен для бизнес-интерпретации (% ошибки относительно факта).
- Сравнение: 1 baseline (mean) + 2 baseline LinearRegression + 2 варианта LightGBM. Цель – понять, оправдан ли gradient boosting на этом датасете.
Результаты LOO-CV
| Модель | Фичи | MAPE % | MAE | RMSE | R² |
|---|---|---|---|---|---|
| baseline_mean | 0 | 4.96 | 2.758 | 3.534 | 0.000 |
| baseline_lr_peak | 1 | 2.95 | 1.613 | 1.932 | 0.701 |
| baseline_lr_ndvi | 9 | 4.48 | 2.459 | 3.291 | 0.132 |
| lightgbm | 18 | 4.39 | 2.412 | 2.915 | 0.319 |
| lightgbm_ndvi_only | 9 | 4.54 | 2.518 | 2.910 | 0.322 |
Победитель: LinearRegression на одной фиче ndvi_peak. MAPE 2.95%, R² 0.70.
Интерпретация
Почему простая линейная модель бьёт LightGBM
- Маленький N. 20 строк – слишком мало для LightGBM. На 19 точках тренировки модель находит сложные паттерны в шуме.
- Структура таргета. Синтетический таргет линеен по
ndvi_peak, остальные фичи – шум, погода вообще константа. Линейная регрессия с одной правильной фичей – идеальная функциональная форма для этой задачи. - LinearRegression на 9 NDVI-фичах хуже, чем на одной (R² 0.13 vs 0.70) – это эффект мультиколлинеарности. Все NDVI-фичи сильно коррелируют между собой, lin regression “размывает” коэффициенты.
- LightGBM добавляет шум на маленьком датасете. Train MAPE 0.03% (идеально), LOO MAPE 4.39% – классический симптом переобучения. 18 фичей × 20 точек = слишком высокая dimensionality.
Что делает LightGBM правильно
- Отсёк все 8 weather-фичей – они константы для 20 полей (variance=0), gain importance ровно 0. Это правильный feature filtering.
- Top-3 по gain: ndvi_peak_anomaly, ndvi_peak, ndvi_growth_rate_max. Физически осмысленные предикторы.
- Permutation importance даёт ту же тройку: ndvi_peak (1.30), ndvi_peak_anomaly (1.27), ndvi_growth_rate_max (0.57).
- area_ha имеет много splits (212), но низкий gain – модель пыталась использовать, но не нашла стабильного сигнала.
Регрессия к среднему
На scatter predicted vs actual видно классический паттерн regression to mean:
- F004 (max yield 63.11) – предсказание 58.21 (занижено на 4.9 ц/га);
- F005 (min yield 47.58) – предсказание 54.44 (завышено на 6.9 ц/га).
Это типично для деревьев на маленьких датасетах: модель «жмётся» к среднему обучающего множества.
Выводы для портфолио
Главный методологический сигнал. Простая линейная регрессия на одной фиче
ndvi_peakпобеждает LightGBM на 18 фичах (MAPE 2.95% vs 4.39%, R² 0.70 vs 0.32). Train MAPE LightGBM = 0.03%, LOO MAPE = 4.39% – классический симптом переобучения. На 20 точках бустинг бесполезен. Это показывает зрелое понимание bias-variance trade-off, а не подход «лишь бы LightGBM запустить». Зрелый ML начинается с baseline и доказывает, что более сложная модель оправдана.
- На 20 точках LightGBM не нужен. Простая линейная регрессия с одной правильной фичей даёт лучший результат. Это важный методологический урок: gradient boosting – инструмент для данных с нелинейностями И большим N. Когда либо одно отсутствует, baseline побеждает.
- Pipeline работает корректно. Модель ловит правильные предикторы, отсекает шум (константы погоды), даёт ожидаемые корреляции. Если подключить реальные данные с дисперсией по погоде (разные годы, разные регионы) – LightGBM покажет свою силу.
- Feature engineering важнее модели. Самая сильная фича (NDVI peak) даёт R² 0.70 в простейшей линейной регрессии. Остальные фичи добавляют шум на текущем датасете – их ценность раскроется при multi-year данных.
- Честность важнее впечатления. В отчёт включён как победный baseline_lr_peak, так и слабый LightGBM. Это даёт нанимателю реальную картину знаний и зрелости анализа.
Что дальше
- Расширить датасет. Multi-year (2020-2024 = 5 лет × 20 полей = 100 строк), плюс multi-region (Калининский, Славянский районы для пшеницы) даст 200-300 строк с реальной дисперсией погоды.
- Реальный таргет. Запросить пол-уровневые урожайности у местных хозяйств или через open data (если будет агрегатор). Альтернатива – использовать районную урожайность Росстата как noisy proxy и moderating prior.
- Time-series модель. Вместо плоских фичей – 1D CNN или Conv-LSTM на сырой NDVI-кривой длиной 45 точек.
- Anomaly detection (день 7). На текущем датасете будет полезным дополнительным сигналом: «поле F005 имеет NDVI ниже исторического коридора».
Артефакты
data/processed/cv_predictions.csv– LOO predictions с residuals и абс. % error;data/processed/feature_importance.csv– gain / split / permutation importance;data/processed/lgb_metrics.csv– сводка метрик 5 моделей;models/lgb_yield.pkl– финальная модель + feature_cols + метаданные;data/preview/cv_scatter.png– predicted vs actual;data/preview/feature_importance.png– три типа importance;data/preview/residuals.png– ошибки по полям;data/preview/model_compare.png– сравнение MAPE и R² пяти моделей.
Параметры LightGBM
{
"n_estimators": 300,
"learning_rate": 0.05,
"num_leaves": 7,
"min_data_in_leaf": 2,
"max_depth": 4,
"feature_fraction": 0.8,
"bagging_fraction": 0.8,
"bagging_freq": 3,
"lambda_l2": 0.1,
"random_state": 42,
}
Tuning гиперпараметров не проводилось: на 20 точках любой grid search будет переобучаться на CV. Использованы консервативные настройки (мало листьев, регуляризация).