ML for Value / Ваня Максимов – Telegram
ML for Value / Ваня Максимов
5.59K subscribers
191 photos
1 video
1 file
119 links
Путь от ML-модели до Value для компании | RecSys, Search, LLM, Pricing и CLTV

Ваня Максимов, @Ivan_maksimov
Head of AI | Recsys, search, llm @Y.Market, ex-WB, ex-Delivery Club

Консультирую компании, Веду курсы
Публикую релевантную рекламу
Download Telegram
Out-of-stock в реальной жизни
Грабли #3: Прогноз продаж все еще меньше факта.. Или человеческий фактор 👩‍🔧

Но мы же вроде решили проблему out-of-stock. Модель работает хорошо: на валидации с метриками все в порядке. Где же может быть загвоздка?

Типичный флоу ML-продукта:
Данные -->
Модель + прогноз --> Рекомендации (какое промо проводить) -->
Реализация рекомендаций

Чтобы ваш ML-проект реально принес value для бизнеса, нужно убедиться, что в реальной жизни ваши рекомендации / прогнозы / что угодно реально используются. Мне очень нравится фраза одного моего друга-разработчика:

"Поменял цвет кнопки - зайди на сайт и проверь, что он изменился"

Так и в ML-проектах. Если вы что-то сделали - возьмите и физически проверьте, что это работает. Зайдите в магазин и проверьте, идет ли акция, которую порекомендовала завести ML-модель

Зашли в магазин - акции нет. Идем к менеджеру, который заводит промо:

"Ваша модель рекомендует слишком низкие скидки. Мой личный KPI - выручка, а не прибыль. Если я буду пользоваться вашей моделью, то стану меньше зарабатывать"

Упс. Вот это уже серьезная проблема. Не то что ваши лоссы и ml-метрики. Чтобы модель заработала, вероятно, нужно будет поменять KPI менеджеру - через директора(?) - иначе все, что вы делали - зря

Вывод
Проверяйте, как в реальности работает ваша модель / рекомендации. Обычно все проблемы в implementation details. Менеджер с другим KPI - лишь одна из возможных проблем
2
При работе с некоторыми менеджерами (особенно, если вы автоматизируете их работу через ML) этот мем уже не кажется смешным
👍1
Грабли #4: локально оптимальное решение.. или каннибализация

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

Часть 1: Договорённости ДО начала проекта: https://news.1rj.ru/str/ml4value/8
Часть 2: Выбор ML-метрик и Loss: https://news.1rj.ru/str/ml4value/18
Часть 3: ML-это не только модели (сечас вы читаете пост №4 в этой части): https://news.1rj.ru/str/ml4value/24


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

Мы прогнозируем прирост прибыли для конкретного товара в зависимости от параметров акции. И выбираем argmax (profit) по параметрам акции. На самом деле, наше решение оптимально лишь для 1 конкретного товара

Но есть проблема: Каннибализация - рост продаж этого товара снижает продажи всех остальных товаров в категории

Простой пример: сделайте скидку 20% на кока-колу - продажи всех остальных газировок резко упадут. Может быть, 20% - оптимально для прибыли кока-колы в вакууме. Но мы же хотим повысить совокупные продажи магазина (или хотя бы продажи всех газировок). Поэтому, оптимизируя прибыль колы, мы находим лишь локально оптимальное решение

Подробно про решение проблемы каннибализации я рассказывал на конференции Х5:
https://www.youtube.com/watch?v=2djYDhQG_BM

TL;DR
Продажи категории товаров (газ. напитки) - функция от промо продаж в этой категории. Поэтому можно делать так:

Шаг 1. Прогнозируем продажи всех товаров на промо
Шаг 2. Суммируем их --> прогноз промо продаж в категории
Шаг 3. Обучаем простую модель, где таргет = все продажи в категории, а одна из фичей - промо продажи в категории. Зависимость, очевидно, нелинейная (см. рисунок ниже)
Шаг 4. Вуаля, мы получили, что прирост промо продаж с 1000 до 1200 (+200) увеличивает продажи категории лишь на +150. Каннибализация = 150 - 200 = -50. И ее нужно учитвывать при выборе параметров промо каждого товара

Вывод:
Помните, что ML-решения зачастую оптимальны лишь локально. И пытайтесь их приблизить к глобальному оптимуму
👌2
Как вам блок про "ML - это не только модели"?
Оптимизация промо акций
Часть 4
Как померить бизнес-эффект? 💰💰

- Очевидно, А/В тестом!
- Да, но не все так просто. Опять мои любимые implementation details:)


Грабли #1: Выбор корректного теста

Классические А/В из учебников применяются не так часто, т.к. столкновение теории с реальностью разбивает первую вдребезги

Что же не так с А/В из учебника? Вспомним, что там пишут:

Шаг 1. Разбиваем юзеров на А и В группы.. Но стоп. Мы же делаем акции на товары в магазине, как же мы побьем юзеров? Правильно - никак. Нужно сплитить магазины

Шаг 2. Провести А/А тест. Обычно в лекциях это упоминается вскользь. Предполагают, что А/А тест всегда успешен. Но в кейсе со сплитом по магазинам зачастую это не так 🙅‍♀ Хьюстон, у нас проблемы

Причин может быть 2:
>> Магазинов мало (даже у Х5 и Магнита их ~20к по всей России) + А/В на полстраны вам запустить никто не даст. В итоге, дай бог, дадут 1-2к магазинов для теста
>> Магазины очень сильно отличаются (разные города, районы города, уровень зп,...)

Что же делать?
1. Можно стратифицированно сэмплировать магазины для А и В групп. Не рекомендую, т к очень сложно подобрать хорошие фичи, по которым вы будете стратифицировать (город? з/п? Население? Все сразу?)

2. Switch back тесты. Рекомендую.
Хорошая статья от DoorDash на эту тему:
https://www.google.com/amp/s/doordash.engineering/2019/02/20/experiment-rigor-for-switchback-experiment-analysis/amp/

TL;DR;
Раз в неделю (в идеале день, но у нас оффлайн ритейл) вы делаете сплитование заново. Если тест идёт 3 недели, то один и тот же магазин может на одной неделе быть в А группе, а на другой - в В. Это позволяет нивелировать различия между средними в А и В группах, и даже снизить дисперсию метрик (ускорить тест)

Вывод
Внимательно следите за тем, какую технику А/В вы используете

#pricing #timeseries
👌1
Грабли #2: А/В тест длиною в жизнь

Допустим, мы выбрали относительно хороший дизайн А/В:
-- Метрика - прибыль на 1 магазин за 1 день
-- Switch back тест
-- Нам разрешили взять максимум 2к магазинов в тестовую группу

Всё, запускаем? Вообще, нужно бы посчитать, сколько недель нам нужно держать А/В. Считаем и получаем.. 2 года 😱

И тут мы приходим к необходимости ускорить А/В тест. Ускорить А/В = снизить дисперсию вашей метрики. Я оставлю ссылки на варианты решения этой проблемы и напишу TL; DR
Когда ждёшь, пока прокрасится метрика в А/В, а не ускоряешь его
Ускорение А/В
Способ 1. Стратификация и CUPED
https://youtu.be/pZpUM08mv-E

Стратификация = Сначала посчитать средние в каждой группе (город/страна/сегмент юзеров по доходу/..), а потом взвещенно по кол-во наблюдений в группе усреднить

Тогда итоговое среднее останется таким же как и в классическом подходе, а дисперсия упадёт - - > тест нужно будет держать меньше

CUPED
В видео объяснение довольно сложное, но по сути вы просто строите линейную регрессию вашей целевой метрики на фичи

Важно (!): значение фичей должно быть известно ДО начала эксперимента

Пример фичей:
-- Целевая метрика магазина N недель назад
-- Город, в котором находится магазин
--...

Потом, вы из целевой метрики вычитание её прогноз. И считаете А/В на уже получившейся величине. Это сильно ускоряет тест, но снижает его интерпретируемость

P.S. Для любителей строгой мат.статистики - выше я описал лишь концепцию. Если вдаваться в детали, то текст выше в чем-то не совсем корректен. Но суть идеи передаёт отлично:)
1
Будьте осторожны с интерпретацией CUPED (под его капотом линейная регрессия)
Ускорение А/В
Способ 2. Выбрать другую метрику 😅

Да-да, вы не ослышались. Можно и иногда даже нужно выбирать другие метрики в А/В, чтобы ждать результатов не 2 года, а 2-3 недели

Прибыль = кол-во заказов * средняя прибыль с одного заказа

Невероятно, но факт (ну, почти всегда факт 😜): дисперсия этих множителей сильно меньше дисперсии прибыли

А значит, А/В успешен, если
хотя бы одна из метрик растёт, а другая - не падает

P.S. Но не забывайте про поправки (например, Бонферонни) для множественного тестирования гипотез
Ускорение А/В
Способ 3: Байесовская статистика
https://youtu.be/Wxw1lseUXVU
(про Байеса - в конце видео)

Одно из немногих успешних применений байеса - А/В тесты и многорукие бандиты

Тут TL;DR не получится, так как много теории. Если интересно, то лучше прочитайте об этом в годных статьях:

Байесовские А/В:
https://link.medium.com/9b4ukKvHK9

Байесовские многорукие бандиты:
https://lilianweng.github.io/lil-log/2018/01/23/the-multi-armed-bandit-problem-and-its-solutions.html
Как вам посты про дизайн и ускорение А/В?

P.S. А ещё: стратификация, линеаризация, байес и т д - просто частные случаи CUPED
Грабли универсальные: Тесты ds-кода

Сразу оговорюсь, что я ни разу не ML Engineer / Devops. Бакалавриат я закончил вообще по мат.методам в экономике. И до начала работы почти ничего не слышал о юнит- и других тестах

Но как только мои модели начали использоваться, даже мне стало очевидно, что без тестов - никуда. Без них пайплайны падают, их починка отнимает кучу времени, а бизнес-заказчики недоумевают где их 300кк/сек от внедрения ML

А если ваши пайплайны падают слишком часто - не за горами тот момент, когда и вы будете недоумевать про свои 300кк/сек 🙂

Так что начнем мое небольшое введение в тестирование ML-пайплайнов!

ML-тесты очень специфичны. В продакшене каждый день мы обучаемся на немного разных данных. При этом даже на одних и тех же inputs можно получать разные outputs. Мы в общем случае не знаем, какой должен быть ответ на одном или другом примере

Поэтому я предлагаю покрывать отдельными тестами:
— входные данные (да-да, и для нейронок тоже)
— каждый этап трансформации данных
— predict

В моем идеальном мире, код может выглядеть примерно так:

df = read_data()
test_on_inputs(df)

df = first_transform(df)
test_on_transform(type='first')

df = second_transform(df)
test_on_transform(type='second')

model = MyFavoriteModel()
model.fit(df)
test_on_predict(model, df)


Далее опишу тесты, которые я использую каждый день стараюсь использовать. А чтобы убедить вас, что тесты нужны, добавлю мои самые эпичные фейлы
На мой взгляд 90% ошибок - в самых элементарных вещах. Перепутали типы данных, сделали left join вместо inner и т.п. И если вы думаете, что это происходит "с любым, но точно не со мной" - скорее всего вы заблуждаетесь:) Для таких кейсов представляю вам:

Капитанский набор тестов для DS
.. и мои эпичнейшие фейлы:

1. Проверка типов входных данных
Прочитать pandas dataframe без указания типов данных и получить out of memory error - это уже стало классикой

2. Проверка кол-во строк в датафрейме
Вы обучили модель и она показала 99% AUC? Запускаете регулярный джоб на обучение и вдруг видите совершенно неадекватные предсказания и AUC около 50%? Поздравляю, еще одна классика: джоб автоматически обучил вашу SOTA модель на не собранной до конца базе (например, там оказалось 10к строк вместо 10кк)

3. Проверяйте долю NaN-ов и уникальных значений в каждом столбце
Я однажды сджойнил датафрейм с поминутными событиями и датафрейм "дата-праздник". Угадайте, для каких минут были не NaN-ы (для ХХ-ХХ-ХХ:00:00). Поэтому мои юзеры праздновали не только НГ исключительно 1 минуту в полночь, но и все остальные праздники

4. Проверяйте распределение фичей
- min/max значения (особенно актуально для дат)
- Среднее

Я встречал отрицательные цены, возраст в 5000+ лет, отрицательный прогноз продаж (хотя в трейне только положительные продажи, но бустингу все равно), даты после сегодняшнего дня в трейне и еще много артефактов. И да, замечаете вы их далеко не сразу. В свою защиту скажу, что и появляются такие артефакты тоже не всегда сразу

5. Тесты на логику
- Статистики по категориям (условно через df.groupby(store_id)['item_id'].nunique() посчитать, что в каждом магазине > 1000 товаров
- Продажи любого товара не больше 10к шт в день

Если в ваш магазин заехал оптовик и закупил 5 Камазов картошки по акции, то это легко сломает вам все модели

6. Тесты на логику predict
Вы же ожидаете, что прогноз продаж вырастет, если увеличить скидку на товар? Так напишите на это тест

Кстати, почти все эти тесты можно очень удобно закодить с помощью достаточно новой либы great-expectations:
https://docs.greatexpectations.io/en/latest/
*На самом деле тесты вам помогут найти баги в пайплайне и даже улучшить качество модели!

Но это не точно
Все то, что я описал выше, касается картинок и текстов тоже

Нет ничего более обидного, чем когда обучил Sota сетку с огромным входным размером изображения, а на вход в проде подаёшь микро картинку (условно, 256х256) и автоматически pad-ишь ее нулями.. Всё работает, но качество - так себе
Вам понравился пост про ML-тесты?

Если интересно услышать еще больше true sad stories про фейлы из-за отсутствия тестов (или рассказать свою историю) - добро пожаловать в комментарии
Рекомендательные системы
Всё, чему нас учили - неправда

Следующая серия постов будет посвящена получению Business Value от рекомендательных систем (RecSys). А пока поделюсь с вами довольно значимым научным открытием в 2020 году:

Оказалось, что некорректно использовать наши любимые NDCG, precision@k, recall@k для сравнения моделей, если эти метрики посчитаны на сэмпле данных. Вместо этого корректно использовать AUC@k 😱

А сэмплирование используется почти во всех продакшн-системах, так как товаров сотни тысяч, а то и миллионы (метрики считают обычно на сэмпле из 100-1000 товаров)

Видео с KDD-2020 на эту тему (всего 15 мин)


Для тех, кто не очень близок к сфере recsys: в 99% курсах на первом же уроке говорят, что использовать AUC для оценки качества ранжирования нельзя, т.к он плохо учитывает порядок рекомендаций

На очень годных курсах добавляют, что AUC@k чуть получше, но тоже не айс 🥶

И настоятельно советуют использовать те самые NDCG, precision@k, ...

Вот так и переворачиваются в момент все представления о задаче ранжирования

P.S. Сколько же раз, получается, я выбирал модель на основе некорректных метрик..

#recsys