Какие проблемы возникают при добавлении номера месяца как признака
Что проверяют
Понимаете ли вы, что способ кодирования признака задаёт модели форму зависимости. Номер месяца выглядит безобидно, но несёт ложный порядок и ложное расстояние. Следом обычно просят закодировать его правильно и объяснить, как проверить пользу на валидации.
Как отвечать
Проблемы и что с ними делать:
- ложная линейность: для линейной модели месяц 1..12 означает монотонно растущий или падающий эффект, а у сезонности форма волны. Декабрь и январь соседи по времени, но в числах между ними 11;
- циклическое кодирование: пара
sin(2π·m/12)иcos(2π·m/12)ставит декабрь рядом с январём. Нужны оба признака: по одному синусу февраль и апрель неразличимы; - one-hot: 11 бинарных колонок (одну убирают, если в модели есть свободный член) дают каждому месяцу свой эффект без предположений о форме, но требуют данных по каждому месяцу;
- деревья: бустинг сам разрежет номер месяца на интервалы, но для «зимы» ему понадобятся два разреза. CatBoost и LightGBM умеют брать месяц как категорию, и это часто проще синусов;
- короткая история: если данных меньше пары лет, месяц сливается с событиями конкретного года, и модель запоминает случай, а не сезонность;
- смешение с трендом: при растущем бизнесе поздние месяцы выборки ещё и позже по времени, модель путает сезон с ростом.
Проверка: валидация по времени (TimeSeriesSplit, окно не короче полного сезона), сравнение с моделью без признака и с сезонной наивной моделью. Часто полезнее не месяц, а флаги праздников, число рабочих дней и расстояние до ключевой даты.
Где спотыкаются
Делают случайный сплит вместо временного. Месяцы перемешиваются, и признак выглядит сильнее, чем окажется в проде.
Добавляют только синус без косинуса. Два разных месяца получают одинаковое значение, и цикл не восстанавливается.
Считают синус и косинус универсально лучшим вариантом. Деревьям эта пара неудобна: делить её приходится по каждому признаку отдельно, и категория или обычный номер там работают не хуже.