В статье описываются основные функции службы динамического ценообразования Otto, которая в настоящее время используется для установления цен на большинство товаров на otto.de. Далее в нем описывается, как мы успешно создали службу как надежное и масштабируемое облачное приложение, способное ежедневно предоставлять цены для миллионов статей. В нем также объясняется, какую пользу мы получили от работы над нашим приложением в многофункциональной команде, и как мы намерены обеспечить постоянное улучшение нашего сервиса.

Использование ИИ для определения лучших цен на товары

Представим, что сейчас начало июня. У нас осталось 230 штук красивого летнего платья в цветочек на складе. Все они должны быть реализованы до конца июля, потому что эти складские мощности потребуются для предстоящего осенне-зимнего ассортимента. Итак, вопрос теперь в том, какая цена гарантирует, что у нас не закончатся запасы слишком рано и не останутся непроданные запасы в конце июля? Услуги ценообразования по уценке решают именно этот вопрос.

Мы используем модели машинного обучения, такие как регрессия OLS, XGBoost и LightGBM, для прогнозирования количества статей, которые можно продать за оставшийся промежуток времени по разным ценам. Мы кормим эти модели историческими данными о ценах и объемах заказов. Поскольку другие факторы, такие как цены конкурентов или маркетинговые кампании, также могут в значительной степени влиять на объем заказа, мы также вводим эту информацию в модели. Включение этих функций помогает нам лучше прогнозировать спрос и более точно определять те изменения спроса, которые могут произойти исключительно в результате изменений цен. Имея под рукой точную модель прогнозирования, легко определить оптимальную цену на оставшиеся летние платья.

Помимо ценообразования по уценке, у нас есть еще одно приложение для динамического ценообразования: оптимизация портфеля. Допустим, мы продаем 200 различных типов холодильников. Для обеспечения прибыльности общая маржа холодильников должна составлять не менее 15 процентов. Если он упадет ниже этого значения, на столе не останется денег для покрытия расходов OTTO, поэтому наша цель — максимизировать объем продаж, не опускаясь ниже критического значения маржи.

Здесь снова пригодятся модели прогнозирования спроса: они помогают нам различать товары, которые сильно реагируют на изменение цены (эластичные товары) и те, которые не реагируют (неэластичные товары). Таким образом, мы можем снизить цены на эластичные изделия, потому что это вызовет значительный рост спроса. Это помогает нам максимизировать общий объем продаж, предлагая нашим клиентам привлекательные цены. С другой стороны, мы не должны корректировать цены на неэластичные товары, потому что снижение цены без увеличения объема заказа означает потерю денег, а ритейлер этого не ценит.

На рис. 2 показана оптимизация портфеля в действии. После развертывания цены были снижены, чтобы максимизировать объем продаж. В результате общая маржа ассортимента падает — именно до целевого уровня, но в среднем не ниже. Отлично! Наши клиенты довольны, потому что они получают выгоду от более привлекательных цен на otto.de, в то время как OTTO счастлив, потому что объем продаж значительно растет, а размер прибыли все еще выше критического порога. К сожалению, наша оптимизация портфеля, распространяющая счастье, требует очень больших вычислительных ресурсов. Вытекающие из этого технические проблемы обсуждаются в следующем разделе.

Построение надежного и масштабируемого конвейера

В 2019 году наши услуги по уценке и оптимизации портфеля охватывали три ассортимента. Мы доставляли около 200 000 цен в неделю. В то время OTTO управляла одним из крупнейших кластеров Hadoop в Европе. Тем не менее машины скрипели под натиском оптимизации цен. Во время «счастливых часов кластера», когда наш сервис делил пул машин с множеством других требовательных к производительности приложений, доступные рабочие узлы были сожраны в кратчайшие сроки. В то время в общем журнале было написано: «Приложение запущено… Оптимизация почти завершена… Извините, вы были вытеснены… Перезапуск приложения». Другими словами, опора на общие ресурсы означала, что наш конвейер не был ни надежным, ни масштабируемым.

Зная, что в настоящее время мы сообщаем цены только на три ассортимента, а десять других все еще ждут загрузки, у нас было два варианта: перенести вычислительно затратную часть нашего приложения в облако или попытаться отпугнуть наших клиентов. коллег из общих ресурсов. Поскольку мы были небольшой командой довольно слабых разработчиков, которые не хотели и не могли никого отпугнуть, мы выбрали первый вариант. При первоначальной поддержке со стороны команды опытных разработчиков облачных вычислений мы начали программировать нашу облачную инфраструктуру в Terraform. Примерно через 6 месяцев весь облачный конвейер был готов к запуску.

Мы по-прежнему собирали входные данные из локальных систем, но вычислительная тяжелая работа теперь выполнялась в облаке. Мы используем Dataproc для обучения наших моделей машинного обучения и оптимизации цен распределенным способом. Одновременно до 2500 ядер заняты обучением моделей машинного обучения тому, как предсказывать продажи на основе цен или определять лучшие цены примерно для миллиона товаров каждый день. Помимо обучения моделей и оптимизации цен, все основные компоненты нашего приложения (например, сервисы, передающие результаты ценообразования в базы данных или предоставляющие данные о ценах для otto.de) построены как контейнерные микросервисы Docker. Процессы ETL, обучение модели, оптимизация цен, загрузка цен и все другие микросервисы управляются сервером Jenkins, который находится в контейнере Docker на самой облачной виртуальной машине. Таким образом, наше приложение в основном состоит из Jenkins Docker, на котором запущены докеризованные микросервисы, и заданий Dataproc для обучения моделей и оптимизации цен между ними.

Сегодня наш сервис предоставляет до 4,7 миллиона цен в неделю. Это примерно в 24 раза больше, чем мы поставили, когда достигли предела наших локальных ресурсов. И теперь служба работает без сбоев. Ну, не всегда. Но довольно часто. Мы продолжаем над этим работать…

Объединяем все это в кросс-функциональную установку

Вы когда-нибудь слышали, как специалисты по обработке и анализу данных из команд задаются вопросом, почему «парням, работающим с ETL, нужна целая НЕДЕЛЯ, чтобы добавить на рынок две крошечные новые колонки»? Что ж, специалисты по данным, вероятно, никогда не были на месте своих коллег. В противном случае они бы знали, что (в зависимости от качества и документации источника) добавление этих новых столбцов вполне может быть болезненной и длительной процедурой. В кросс-функциональной команде, где специалисты по данным надевают свои рабочие перчатки и сами занимаются обработкой данных, этого не произойдет. Не произойдет и того, что инженеры ETL почувствуют себя в затруднительном положении, когда конвейер сломается, пока специалисты DevOps находятся в отпуске, поскольку они смогут исправить это в одиночку или, возможно, вместе с специалистом по данным.

Мы считаем, что хорошая и эффективная командная работа сильно поддерживается кросс-функциональной настройкой. Каждый в нашей команде понимает и ценит работу другого, потому что мы знаем о тонкостях и проблемах, связанных с каждой ролью в команде. И все в команде могут — по крайней мере, в какой-то степени — заменять друг друга. Data Scientist не работает, заболел? Не беспокойтесь, DevOps может построить модель прогнозирования. Это оказывает расслабляющее действие на обоих.

Улучшение нашего продукта

Мы считаем, что лучший способ повысить эффективность нашей службы динамического ценообразования — постоянно оценивать идеи команды о том, как усилить влияние алгоритма на ключевые показатели эффективности бизнеса. Мы делаем это с помощью экспериментальных исследований. Наше приложение легко позволяет нам запускать различные версии алгоритма для двух или более однородных подгрупп товаров в производственной среде на otto.de: в то время как товары в группе A получают цены, рассчитанные по алгоритму X, группа B получает цены по алгоритму Y. Таким образом, мы можем сравнить ключевые показатели эффективности, такие как продажи или прибыль, между группами и решить, выиграет ли Otto от пересмотренного алгоритма. Если это так, мы запускаем его в производство… и запускаем следующий тест. Тест -> выучить -> повторить. Осталось исследовать множество гипотез!

Ищите эту и множество других интересных статей в нашем Техблоге.

Написано Кристофером Блейком