Увеличиваем выручку с помощью математики: как учитывать бизнес-контекст в оптимизационных задачах

от автора

Привет! Я Эдуард, в ecom.tech руковожу группой прогноза спроса для Мегамаркета. В этой статье хочу рассказать, что меняется в работе с алгоритмами машинного обучения, когда начинаешь учитывать ограничения и нюансы бизнес-задачи. Расскажу на примере одного исследования – как мы искали способы увеличить выручку маркетплейса.

В статье будет математика, псевдокод, но главное – постараюсь рассказать, как вся эта техническая часть опирается на бизнес-контекст. Поехали!

Описание бизнес-процесса: карточка товара

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

В примере мы видим описание товара, его цену, сроки доставки, кешбэк, а также кнопку «Купить». Справа внизу есть кнопка «Еще n предложений от m рублей», нажав на которую мы увидим все товарные предложения и условия по данному товару от различных продавцов.

Товарные предложения

Товарные предложения

Напротив каждого товарного предложения есть своя кнопка «Купить». Видно, что товарные предложения отсортированы определенным образом и на их позицию влияет ряд факторов. Назовем их факторами «привлекательности». Чем выше по нашим расчётам «привлекательность» предложения для клиента, тем выше оно в списке.

А ещё обратите внимание, что верхнее предложение идентично тому, что отображается у фиолетовой кнопки «Купить». Это не совпадение. Товарное предложение на верхнем месте становится выбором по умолчанию при нажатии вышеупомянутой кнопки. Эти товарные предложения мы называем «избранными».

Постановка задачи: увеличить выручку 

Факторы, которые могут влиять на привлекательность товарного предложения, могут быть разными – навскидку, это цена или кешбэк, сроки доставки или ее стоимость.

Управляя этими факторами, можно влиять на сортировку товарных предложений.

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

Выручка формируется из двух ключевых составляющих:

  • цена проданного товара;

  • количество проданных товаров.

С одной стороны, если предложение с самой высокой ценой попадает в «избранные», оборот от каждой продажи будет большим. Однако, вероятно, такой товар будет покупаться реже из-за своей высокой стоимости. 

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

В постановке задачи нам необходимо было учитывать пожелания бизнеса — полученная модель должна быть хорошо интерпретируемой.

Правила сортировки товарных предложений были разработаны специалистами, с учётом их опыта и глубокого понимания рынка. Любые изменения в логике сортировки, опирающиеся на математику, эксперименты или что бы то ни было – должны быть прозрачными для бизнеса.

Поскольку важна интерпретируемость, то модели типа Black-Box отпадают автоматически. Так получаем оптимизационную задачу, где целью является поиск наилучших коэффициентов для увеличения выручки.

Давайте расскажу, как мы исследовали эту задачу. 

Формализация задачи

Требуется найти вектор параметров x, x∊ R^{k=4}каждый из которых лежит в интервале[0, 1]и используется в функции

ϕ(x)= -с_{ij}+\sum_{k=1}^{4}B_{ij}^{k}  x_{k}

Эта функция определяет продавца товара.

Все продавцы маркетплейса индексированы i, все товары индексированы j; c_{ij}- стоимость товара j у продавца i. Параметр для цены не подбирается, а назначается равным единице (максимальное значение интервала для остальных параметров);B_{ij}^{(k)} четыре численных характеристики продавца i товара j.

Если продавец i не продает товар j, то полагаем c_{ij}=0, а B_{ij}^{(k)}= -∞

Положимϕ_{ij}(x)— значение функции для пары (i, j).

Пусть параметры вектораxзаданы, а товар j зафиксирован (то есть определено значение его индекса j^{*}). Тогда для товараj^{*} основным является тот продавец, для которого значение функции достигает максимума. Если максимум достигается в нескольких точках, то основного продавца выбираем случайным образом.

Параметры вектора x должны быть определены таким образом, чтобы максимизировать выручку маркетплейса.

Матрица разметки

Рассмотрим матрицуL, в которой по осям продавец-товар однозначно показано, какой продавец для какого товара является оптимальным.

Пусть параметры x=(x_1,...,x_4)известны, тогда определена\{0, 1\}матрица L(x)=(l_{ij}(x)), где l_{ij}(x)=1, если для товара j при заданном x основной продавец — i, в противном случае l_{ij}(x)=0.

В таком случае для произвольной пары продавец-товар (i^{*}, j^{*})

 l_{i^*j^*}(x):= \begin{cases} 1, &\text{если}~ ϕ_{i^*j^*}(x)= max_i\{ϕ_{{ij^*}}(x)\}, \\ 0, ~&\text{в противном случае.} \end{cases}

Отметим, что должно выполняться равенство\sum_{i} l_{ij}=1для любого товара j. Поэтому если для некоторогоj^*существуют несколько значений i_{1}, i_{2}, ... таких, что l_{i_1j^*}=1, ~l_{i_2j^*}=1, ..., то случайным образом отбираем только один из таких кандидатов, а для остальных индексов значение функции l для этого j^*зануляем.

Матрица объемов продаж R

Для каждого товара j по историческим данным определяем объем продаж (в количественном эквиваленте) этого товара за единицу времени (за предыдущий день) каждым продавцом i. Если продавец i не реализует товар j, то полагаем, что r_{ij}=0.

Матрица цен C

Для каждого товара j определяем цену у продавца i.Берется последняя известная цена (за предыдущий день).

Функция ожидаемой выручки

По определению эта функция равна

F(x)=\sum_{i,j} l_{ij}(x)⋅r_{ij}⋅c_{ij}→max,

0≤x_k≤1,для всех k=1,2,3,4.

Функция \sum_{i,j} l_{ij}(x)⋅r_{ij}⋅c_{ij} не является непрерывной в рассматриваемом гиперкубе. Поэтому оптимизационные методы, основанные на дифференциальном исчислении, могут давать неудовлетворительный результат. Вероятно, для решения предпочтительней будет использовать какой-либо derivative-free optimization solver.

Псевдокод описанной модели:

import numpy as np import pandas as pd     def construct_model(x: list[float], features: list[str], df: pd.DataFrame) -> float:    """Модель оптимизации выручки      :param x: список оптимизируемых параметров (инициализация)    :param features: список с названиями факторов привлекательности (price,    cashback, delivery_time, delivery_price)    :param df: датафрейм с данными о факторах привлекательности и объемах продаж    (quantity с индексом (продавец, товар)      :return: ожидаемая выручка при заданных значениях x"""    dims = размер тензора (i, j, k)    missed_vals = вектор длиной k заполненной - Inf и 0 (для цены)    coords = сохраняем индексы ненулевых элементов из датафрейм df     B = создаем тензор размерностью dims и заполняем missed_vals    B[coords] = заменяем missed_vals на значения (где они имеются)    R = создаем матрицу из нулей размером (i, j)    R[coords] = по аналогии, заменяем нулевые значения на фактические    C = матрица цен размером (i, j)    phi = считаем привлекательность как скалярное произведение B и x    max_phi = выбираем индекс самого привлекательного продавца    L = матрицу max_phi пребразумем {0, 1} матрицу    LRC = L * R * C поэлементно перемножаем матрицы     f = - sum(LRC) суммируем по i, j      return f

Ограничения и допущения

Наша оптимизационная модель практически готова, но существует одно концептуальное ограничение, препятствующее прямому решению задачи. Оно связано с матрицей объемов продаж R. Как я упоминал выше, особенностью маркетплейса является то, что внутри карточки товара есть разные товарные предложения.

Избранное товарное предложение будет иметь больший объем продаж по сравнению с остальными из-за его заметного местоположения — прямо под главной фиолетовой кнопкой «Купить». Этот высокий объем продаж может зависеть от UX-дизайна карточки товара.

Действительно, если где-то внизу, на 20-м месте, будет размещено более привлекательное товарное предложение, его объем продаж, вероятно, будет ниже, чем у избранного. А выручка избранных предложений будет выше по сравнению с остальными. Если учитывать, что:

а) объем продаж напрямую влияет на выручку;
б) мы базируемся на сырых данных, полученных из исторической статистики за день.

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

Так, если в матрице R будут представлены реальные значения, то множество товарных предложений, максимизирующих выручку, совпадет с текущим множеством избранных предложений. Оптимальные параметры x будут такими, при которых сохраняется первоначальная сортировка в карточке товара, и, следовательно, оптимизации не произойдет.

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

Перед корректировкой отметим два момента:

  • объемы продаж избранных товарных предложений не зависят от сортировки, поэтому их значения не требуют корректировки;

  • главный фактор, от которого зависит объем продаж, будем считать цену.

Поэтому, для каждого товара (не товарного предложения, а товара), по историческим данным о продажах за последний месяц, строится линейная модель зависимости объема продаж от цены (точнее от Δ_{цены}), которая имеет вид:

Quantity=Level+Trend⋅(Price - Price_{favorite})

  • Price-цена, по которой был куплен товар;

  • Price_{favorite}-цена избранного товарного предложения в момент покупки товара;

  • Quantity-объем продаж при разнице цены покупки товара и цены избранного предложения.

Цель построения данных моделей – получение для каждого товара значения коэффициента Trend, характеризующего степень зависимости объемов продаж от цен. Его, с определенными допущениями, можно интерпретировать как эластичность спроса по цене.

В результате построения были получены следующие взаимосвязи (пример для нескольких товаров).

В качестве моделей использовалась робастная линейная модель с Huber Loss функцией.

В случае, если данных для конкретного товара недостаточно (товар редко покупают), в качестве коэффициента бралось среднее значение Trend по товарной категории, которой принадлежит данный товар.

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

Следующим шагом является использование коэффициентов Trend для корректировки объемов продаж товарных предложений матрицы R.

\hat{r}_{ij}=r_{i_{max}j}+Trend_j⋅(c_{ij}-c_{i_{max}j})

  • \hat{r}_{ij}-скорректированный объем продаж товараj у продавцаi;

  • r_{i_{max}j}-объем продаж избранного товарного предложения товараjза единицу времени (за предыдущий день);

  • Trend_{j}-коэффициент эластичности для товараj(всегда меньше нуля)

  • c_{ij}-цена товара j у продавца i;

  • c_{i_{max}j}— цена избранного товарного предложения товараj.

Данная формула является хорошо интерпретируемой и имеет концептуальный смысл. Если

 r_{ij}:= \begin{cases} r_{i_{max}j}, &c_{ij}=c_{i_{max}j}, \\ >r_{i_{max}j}, ~&c_{ij}<c_{i_{max}j}\\<r_{i_{max}j}, ~&c_{ij}>c_{i_{max}j} \end{cases}

В итоге модель имеет следующий вид

F(x)=\sum_{i,j} l_{ij}(x)⋅\hat{r}_{ij}⋅c_{ij}→max

Оптимизация: имитация отжига 

Из-за негладкости функции применение градиентных оптимизационных методов ограничено (хоть и не полностью). Учитывая это, в качестве оптимизационного алгоритма предлагается использовать simulated annealing (имитация отжига). Используем его реализацию Dual Annealing из пакета scipy.optimize.

Первым аргументом передадим приведенную выше функцию construct\_model. В аргументе bounds зададим границы [0, 1] для каждого коэффициента.

Анализ результатов

Анализ результатов начался с проверки на исторических данных. Мы сравнивали ожидаемую выручку двух множеств: исторически избранных товарных предложений и предложений, которые стали избранными в результате новой сортировки, выполненной с использованием коэффициентов, определенных при оптимизации.

  • ожидаемая выручка увеличилась на 2.7%;

  • средняя цена уменьшилась на 1.3%;

  • средний кэшбэк увеличился на 1.7%;

  • средние сроки доставки уменьшились на 4.4%;

  • средняя стоимость доставки увеличилась на 2.7%;

Следующим шагом мы хотели убедиться, что ситуация будет аналогичной не только на исторических данных, но и в реальности. Для этого был проведен А/B-тест.

A/B-тест

В эксперименте участвовали товары из 1 категории и 3 городов.

В остальном все по классике:

  • выбираем правило разделения на пилотную и контрольную группы;

  • выбираем ключевую и контрольные метрики;

  • проводим А/А-тесты для проверки ключевой метрики;

  • выбираем величину минимального детектируемого эффекта;

  • считаем необходимый размер выборки;

  • проводим A/B-тест.

Сплитование – по клиентам. Одной группе будет показан новый функционал, другой — старый. В качестве ключевой метрики берем среднюю выручку. В качестве контрольных метрик используем: количество клиентов в группах, среднее количество купленных товаров в корзине, средний размер примененного кешбэка. После этого проведем А/А-тест для ключевой метрики с целью проверки равномерности p-value.

Следующим шагом является выбор минимального детектируемого эффекта. В качестве отправной точки будем использовать значение ожидаемой выручки в 2.7 %. Исходя из этого, рассчитаем необходимый размер выборки, который даст статистически значимый результат, принимая уровни ошибок 1 и 2 рода равными 0.05 и 0.2 соответственно.

Таким образом, с помощью этого эксперимента мы получили подтверждение о наличии эффекта с заданной статистической значимостью.

Как найти оптимальное решение

Впереди – много всего интересного.

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

Также мы планируем провести исследования для других категорий товаров.

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

Это исследование дало нам не только математические и экспериментальные результаты. Помимо потенциальных точек роста для бизнеса, подтвержденных статистически, ещё мы получили опыт. Лишний раз увидели на практике, в какой области могут лежать ответы на вопрос “Как найти оптимальное решение прикладной оптимизационной задачи?”. 

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

Нужно помнить, что задача в первую очередь прикладная и только потом оптимизационная. Остальное – дело техники. 


ссылка на оригинал статьи https://habr.com/ru/articles/851296/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *