Как формировать обучающие данные для классификации на основе истории показов и покупок
Что проверяют
Умеете ли вы собрать выборку так, чтобы модель на проде видела то же, что при обучении: без утечек из будущего, с правильной меткой и честным разбиением. Следом спрашивают про покупки, которые приходят через дни после показа, и про дисбаланс классов.
Как отвечать
- единица наблюдения: пара «пользователь, товар» в момент показа. Метка 1, если товар купили в заранее выбранное окно после показа (например, 7 дней), иначе 0. Повторные показы одного товара склеивают или берут последний перед покупкой;
- признаки на момент показа: всё считается строго по данным до времени показа, через point-in-time join или feature store с историей значений. Счётчики берут по окнам: просмотры за 1, 7 и 30 дней, CTR товара за прошлую неделю, цена на момент показа;
- созревание меток: последние дни истории, где окно атрибуции ещё не закрылось, в обучение не берут, иначе поздние покупки станут ложными нулями;
- разбиение по времени: учим на прошлых неделях, валидируем на следующей, тестируем на ещё более поздней. Случайное разбиение смешивает будущее с прошлым и завышает метрики;
- дисбаланс: покупки обычно составляют доли процента от показов. Негативы прореживают, оставляя долю
w, и возвращают калибровку формулойq = p / (p + (1-p) / w), либо обучают на всех данных с весами классов. Качество смотрят по PR-AUC и logloss, а не по accuracy; - позиционное смещение: верхние позиции покупают чаще просто из-за места. Позицию добавляют признаком и на инференсе фиксируют константой, либо взвешивают примеры по вероятности просмотра.
В данных только показанные товары, то есть решения прошлого ранжировщика; небольшая доля случайных показов помогает измерить это смещение.
Где спотыкаются
Считают признаки по всему периоду сразу, например популярность товара с учётом будущих покупок. Офлайн-метрики отличные, на проде модель проваливается.
Делят выборку случайно, и один и тот же пользовательский сеанс попадает и в обучение, и в тест.
Лечат дисбаланс синтетикой вроде SMOTE и заполняют пропуски медианой не глядя. Для логов показов это портит вероятности, а пропуск признака часто сам несёт сигнал, например что пользователь новый.