Разбиение на обучающую и тестовую выборку без учета времени — распространенная ошибка, про которую все уже знают. Правильное разбиение может привести к неочевидным проблемам, которые мы обнаружим и решим.
Рассмотрим небольшой пример. Нам нужно спрогнозировать выручку по магазинам на следующий месяц, признаки — агрегаты выручки в прошлом, доступны данные за год. Модель специально выберем стандартную, градиентный бустинг над решающими деревьями. Для наглядности оценивать качество будем по средней относительной ошибке MAPE.
Разобьем данные на обучающую(train) и тестовую(test) выборки случайно, обучим модель и оценим результат. Кросс-валидацию и валидационную выборку упускаем для простоты.
Подход со случайным разбиением дает ошибку на test в 12%. Возможно этого хватит, но в продакшене модель обученная на прошлом будет прогнозировать будущую выручку. В случайном разбиении это не учтено.
Сделаем разбиение по времени, теперь в test последние 3 месяца. Всегда стоит разобраться, как будет использоваться модель и выбрать стратегию валидации, повторяющую продакшн.
Обучаем новую модель, MAPE выросла с 12% до 24%! Более того, ошибка растет с каждым месяцем.
В отчетах или на демо 12% выглядят лучше, чем 24%, но в проде модель будет работать с ошибкой в 24%. Оценивая модель некорректно, вы можете неприятно удивиться результатам АБ-теста или приемки.
Что произошло?
Мы столкнулись со смещением данных или dataset shift. Мир со временем меняется, и эти изменения отражаются в данных. Обученная на прошлом модель ничего о них не знает. Пытаясь обучиться на train, модель начинает все сильнее ошибаться test.
Скрытый текст
Смещение можно принять за переобучение. В нашем примере ошибка на test 24%, а на train 6%. Предотвращение переобучения повысит метрики, но не решит проблему.
Что это значит для нас:
-
Большая ошибка прогноза. 24% Может быть достаточно, но можно меньше.
-
Быстрая деградация модели. Без регулярного переобучения 19% в первый месяц быстро превратятся в 30%.
-
Сложно обучить модель. Изменение гиперпараметров и работа с данными слабо влияют на метрики качества.
Обнаружим смещение
Есть 3 причины смещения и все они могут возникнуть одновременно:
-
Covariate shift: Разное распределение признаков в train и test.
-
Prior probability shift или label shift: Разное распределение целевой переменной.
-
Concept drift: Изменилась зависимость между признаками и целевой переменной.
Несколько методов обнаружения смещения, пойдем от простого к сложному:
-
Проверить изменение целевой переменной и признаков во времени глазами. Иногда можно заметить очевидные аномалии и тренды.
-
Сравнить распределения признаков и целевой переменной в train и test, лучше с помощью стат. тестов. Этот метод обнаруживает смещение в отдельных признаках, но не учитывает их взаимодействие.
-
Построить классификатор отличающий train и test. Объединяем train и test выборки, признаки из исходного датасета, а целевая переменная - принадлежность к train или test. Чем выше качество классификатора, тем сильнее смещение. Взаимодействие признаков уже учитывается, по feature importance можно определить смещенные признаки.
Теперь разберемся что происходит у нас. Не обязательно сразу бросаться в подготовленные датасеты, общую картину можно быстро понять по уже готовым отчетам и дэшбордам, особенно это выручает когда ваши данные еще не готовы. Откроем отчет с показателями по нашей компании и посмотрим на выручку.
Благодаря общим усилиям, выручка в магазинах растет и продолжает расти, есть тренд. Посмотрим на целевую переменную в наших данных.
То же самое. Логично, это тот же показатель, что и на предыдущем графике. Более того, наши признаки подсчитаны из выручки за прошлые месяцы, тренд есть и в них. Причина смещения — тренд, который модель не может учесть. Разберемся, как он влияет на модель:
-
Меняется распределение признаков, посчитанных из истории выручки. Выученные сплиты решающих деревьев начинают работать хуже.
-
Меняется распределение целевой переменной. Решающее дерево не умеет экстраполировать, модель никогда не видела таких больших значений выручки и не может их спрогнозировать.
-
В прошлом тренда не было или он был другим. У нас мало данных с нужными зависимостями.
В реальных задачах все будет сложнее: появляются новые категории объектов, различные акции и промо или меняется методология сбора данных и расчета метрик.
Скрытый текст
Несколько примеров из жизни.
Работая над проектом из нефтяной промышленности, заметили, что с определенного момента данных становится значительно больше и падает качество. Выяснилось, что у месторождения сменился владелец. Бурить начали активнее и по-другому собирать показатели.
Другой случай возник при работе над системой динамического ценообразования. Прямо перед запуском в метриках продукта появился тренд, как в нашем примере. Построенные модели с ним не справлялись, помогло удаление тренда и другие методы.
Устраним смещение
Если коротко, то нам нужно сделать train и test похожими. Несколько простых методов:
-
Удаление наиболее различающихся признаков. Может помочь, но как правило смещение не содержится только в каких-то конкретных признаках, к тому же теряем ценную информацию.
-
Oversampling или undersampling. Насэмплим данные в train, чтобы распределения в train и test были похожими. Помогает в случае label shift.
-
Преобразование признаков и целевой переменной: переход к относительными значениям, масштабирование данных, объединение или разделение категорий, удаление тренда и т.д.
-
Удаление данных. Например, если в test или train есть аномалии и вы уверены, что модель не должна их обрабатывать, можно их удалить.
Также можно воспользоваться техниками из transfer learning или собрать больше данных.
А теперь удалим тренд. Из каждого значения выручки вычтем предыдущее значение, пересчитаем признаки. Модель будет прогнозировать не выручку, а изменение выручки относительно предыдущего месяца.
Для оценки качества обязательно выполним обратное преобразование: прибавим к прогнозу модели выручку за предыдущий месяц. Теперь ошибка 7% и не растет во времени! Мы не только уменьшили MAPE c 24% до 7%, но и сделали нашу модель надежнее. Если тренд продолжится, модель будет работать корректно.
На практике полностью удалять смещение не нужно. Как только качество устраивает, заканчиваем. Если есть сомнения, проверьте, что разница в ошибках стат. значимая.
Итог
Разбивая датасет по времени, можно столкнуться со смещением. Обнаружить и устранить смещение непросто, но в результате вы получите надежную и точную модель. Вложенные усилия обязательно окупятся в продакшене.
Что мы узнали:
-
Важно правильно выбрать стратегию валидации. Качество может отличаться в разы, а узнаете вы об этом только в проде.
-
Всегда стоит проверить, как данные изменяются во времени. Хотя бы по основным показателям и целевой переменной.
-
Удаление смещения повышает качество модели и делает ее надежнее.
Расскажите в комментариях о своих случаях смещения, некорректных или необычных способах валидации. Буду рад любым дополнениям и уточнениям.
Полезные ссылки:
-
Подробнее о смещении можно прочесть в книге Shimodaira, H. Dataset Shift in Machine Learning. Neural Information Processing Series, Yale University Press, CAMBRIDGE 2009
Автор: Ev_V