Завтра будет так же, как вчера?

353d3f1fadbe6209d84430586d8ad6c0.png

Разбиение на обучающую и тестовую выборку без учета времени — распространенная ошибка, про которую все уже знают. Правильное разбиение может привести к неочевидным проблемам, которые мы обнаружим и решим.

Рассмотрим небольшой пример. Нам нужно спрогнозировать выручку по магазинам на следующий месяц, признаки — агрегаты выручки в прошлом, доступны данные за год. Модель специально выберем стандартную, градиентный бустинг над решающими деревьями. Для наглядности оценивать качество будем по средней относительной ошибке 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 различаются по значениям целевой переменной

Train и test различаются по значениям целевой переменной

То же самое. Логично, это тот же показатель, что и на предыдущем графике. Более того, наши признаки подсчитаны из выручки за прошлые месяцы, тренд есть и в них. Причина смещения — тренд, который модель не может учесть. Разберемся, как он влияет на модель:

  • Меняется распределение признаков, посчитанных из истории выручки. Выученные сплиты решающих деревьев начинают работать хуже.

  • Меняется распределение целевой переменной. Решающее дерево не умеет экстраполировать, модель никогда не видела таких больших значений выручки и не может их спрогнозировать.

  • В прошлом тренда не было или он был другим. У нас мало данных с нужными зависимостями.

В реальных задачах все будет сложнее: появляются новые категории объектов, различные акции и промо или меняется методология сбора данных и расчета метрик.

Скрытый текст

Несколько примеров из жизни.

Работая над проектом из нефтяной промышленности, заметили, что с определенного момента данных становится значительно больше и падает качество. Выяснилось, что у месторождения сменился владелец. Бурить начали активнее и по-другому собирать показатели.

Другой случай возник при работе над системой динамического ценообразования. Прямо перед запуском в метриках продукта появился тренд, как в нашем примере. Построенные модели с ним не справлялись, помогло удаление тренда и другие методы.

Устраним смещение

Если коротко, то нам нужно сделать train и test похожими. Несколько простых методов:

  • Удаление наиболее различающихся признаков. Может помочь, но как правило смещение не содержится только в каких-то конкретных признаках, к тому же теряем ценную информацию.

  • Oversampling или undersampling. Насэмплим данные в train, чтобы распределения в train и test были похожими. Помогает в случае label shift.

  • Преобразование признаков и целевой переменной: переход к относительными значениям, масштабирование данных, объединение или разделение категорий, удаление тренда и т.д.

  • Удаление данных. Например, если в test или train есть аномалии и вы уверены, что модель не должна их обрабатывать, можно их удалить.

Также можно воспользоваться техниками из transfer learning или собрать больше данных.

А теперь удалим тренд. Из каждого значения выручки вычтем предыдущее значение, пересчитаем признаки. Модель будет прогнозировать не выручку, а изменение выручки относительно предыдущего месяца.

Для оценки качества обязательно выполним обратное преобразование: прибавим к прогнозу модели выручку за предыдущий месяц. Теперь ошибка 7% и не растет во времени! Мы не только уменьшили MAPE c 24% до 7%, но и сделали нашу модель надежнее. Если тренд продолжится, модель будет работать корректно.

После удаления тренда ошибка не только стала меньше, но и не растет со временем

После удаления тренда ошибка не только стала меньше, но и не растет со временем

На практике полностью удалять смещение не нужно. Как только качество устраивает, заканчиваем. Если есть сомнения, проверьте, что разница в ошибках стат. значимая.

Итог

Разбивая датасет по времени, можно столкнуться со смещением. Обнаружить и устранить смещение непросто, но в результате вы получите надежную и точную модель. Вложенные усилия обязательно окупятся в продакшене.

Что мы узнали:

  1. Важно правильно выбрать стратегию валидации. Качество может отличаться в разы, а узнаете вы об этом только в проде.

  2. Всегда стоит проверить, как данные изменяются во времени. Хотя бы по основным показателям и целевой переменной.

  3. Удаление смещения повышает качество модели и делает ее надежнее.

Расскажите в комментариях о своих случаях смещения, некорректных или необычных способах валидации. Буду рад любым дополнениям и уточнениям.

Полезные ссылки:

© Habrahabr.ru