Pull to refresh

Динамическое ценообразование на основе LSTM — ANN в ретейле товаров для дома

Reading time10 min
Views12K
Не секрет, что методы машинного обучения стали повсеместно проникать в различные сферы бизнеса, оптимизируя, совершенствуя и даже создавая новые бизнес процессы. Одна из важных областей — это вопрос установления цены на товар и здесь, при достаточном количестве данных, МО помогает сделать то, что раньше было трудно достижимо – восстановить многофакторную кривую спроса из данных. Благодаря восстановленной кривой спроса стало возможным построить динамические системы ценообразования, которые позволяют провести оптимизацию цены в зависимости от цели ценообразования – увеличить выручку или прибыль. Данная статья представляет собой компиляцию моей диссертационной работы, в которой была разработана и опробована на практике в течении 4 недель модель динамического ценообразования LSTM-ANN для одного из товаров ретейлера товаров для дома.

Хочу сразу же отметить, что в данной статье я не стану раскрывать наименование компании, в которой проводилось исследование (тем не менее, это одна из компаний, из представленного списка в предпосылках), вместо этого я буду назвать ее просто – Ретейлер.

Предпосылки


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

Выручка и прибыль основных ретейлеров в Санкт-Петербурге по состоянию на 31.12.2017

image

В связи с этим, в Ретейлере используется другой подход к ценообразованию:

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

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

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

Данные


Для исследования компанией были предоставлены данные с января 2015 по июль 2017 (920 дней / 131 неделя). Эти данные включали в себя:

  • Дневные продажи, включая выходные дни, по 470 товарам (16 номенклатурных групп);
  • Дни проведения рекламных акций в магазине;
  • Дни в которых предоставлялись скидки на товар;
  • Цены на каждый из 470 товаров;
  • Дневные данные по количеству чеков по всей сети в Санкт-Петербурге;
  • Цены основных конкурентов на большинство из 470 товаров (данные снимались раз в неделю).

Дополнительно к этим данным я также добавил календарные дамми переменные:

  • Сезон года (осень/зима/лето/весна);
  • Месяц;
  • Квартал;
  • День недели;
  • Праздничные дни;

А также, погодные переменные:

  • Осадки – дамми;
  • Температура;
  • Отклонение температуры от средней в сезоне.

Непосредственно проанализировав дневные продажи товаров, я обнаружил, что:
Только около 30% товаров продавались все время, все остальные товары либо вводились в продажу позже, чем 2015, либо снимались с продажи раньше, чем 2017, что привело к существенному ограничению на выбор товара для исследования и ценового эксперимента. Это также приводит нас к тому, что за счет постоянной смены товаров в линейке магазина становится трудно создать комплексную потоварную систему ценообразования, однако, есть некоторые способы обойти эту проблему, о которых будет сказано позже.

Система рекомендации цены


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

image

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

То, что не получилось
После выбора одного из товаров для исследования, я использовал XGBoost, перед тем как непосредственно перейти к LSTM модели.

Сделал я это в расчете на то, что XGBoost поможет мне отбросить множество ненужных факторов (это происходит автоматически), и уже оставшиеся использовать для LSTM модели. Такой подход я использовал осознанно, поскольку, во избежание лишних вопросов на защите диссертации я хотел получить сильное и, при этом, простое обоснование выбора факторов для модели с одной стороны, а с другой – упрощение разработки. К тому же, я получал готовую, черновую, модель, на которой можно было быстро опробовать разные идеи в исследовании. И после этого, выйдя на конечное понимание того, что будет работать, а что нет, делать итоговую LSTM модель.

Для понимания задачи прогнозирования, приведу график дневных продаж первого выбранного товара:

image

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

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

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

Первоначальный список факторов, которые, предположительно, влияют на продажи:

  • Данные по дневным продажам других товаров из данной группы, общих продаж в группе в штуках и количестве чеков по всем магазинам сети в Санкт-Петербурге с лагами 1, 2, 3, 7, 14, 21, 28;
  • Данные по ценам других товаров из группы;
  • Соотношение цены на исследуемый товар с ценами других товаров из группы;
  • Наименьшая цена среди всех конкурентов (данные снимались раз в неделю, и я сделал допущение, что такие цены будут действовать и на следующую неделю);
  • Соотношение цены на исследуемый товар с наименьшей ценой у конкурентов;
  • Лаги продаж по группе (в штуках);
  • Простое среднее и RSI на основе лагов продаж товаров группы, общих продаж в группе и количестве чеков.

В общей сложности получилось 380 факторов. (2,42 наблюдения на фактор). Таким образом, проблема отсечения не значимых факторов действительно была высока, однако XGBoost помог справиться с этим, значительно обрезав количество факторов до 23 (40 наблюдений на фактор).

Наилучший результат, которого я смог добиться, используя greed search выглядит следующим образом:

image
R^2-adj = 0.4 на тестовой выборке

Данные делились на тренировочную и тестовую выборки без смешивания (поскольку это временной ряд). В качестве метрики я использовал показатель R^2 скорректированный сознательно, поскольку презентация итоговых результатов работы должна была проводиться перед комиссией, в т.ч. состоящей из представителей бизнеса, поэтому, он был использован, как наиболее известный и простой для понимания.

Итоговые результаты поубавили мою веру в успех, потому что результат R^2-adj 0.4 означал только то, что система предсказания не сможет предсказывать спрос на следующий день достаточно хорошо, а рекомендация на цену будет мало отличаться от системы «пальцем в небо».

Дополнительно я решил проверить, на сколько применение XGBoost будет эффективно для предсказания дневных продаж по группе товаров (в шутках) и предсказании количества чеков в целом по сети.

Продажи по группе товаров:

image
R^2-adj = 0.71

Чеки:

image
R^2-adj = 0.86

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

Для того, чтобы окончательно убедиться в тои, что предсказывать спрос на один день вперед бессмысленное занятие, я использовал модель SARIMAX (пакет statsmodels для python) для дневных продаж:

image

image

Фактически результаты никак не отличаются от полученных с помощью XGBoost, что наводит на мысль о том, что применение сложной модели в данном случае не оправдано.

При этом, хочу также отметить, что ни для XGBoost ни для SARIMAX погодные факторы оказались не значимы.

Построение итоговой модели


Решение проблемы качества предсказания заключалось в агрегировании данных на недельный уровень. Это позволило сократить влияние случайных факторов, однако, существенно сократило количество наблюдаемых данных: если дневных данных было 920, то недельных только 131. Ситуация ухудшилась тем, что количество факторов осталось практически неизменным (исключались дамми на дни недели), а вот количество наблюдений целевой переменной сократилось сильно.

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

Смена товара произошла на товар с ярко выраженной сезонностью:

image

Из-за перехода на недельные продажи встал логичный вопрос: адекватно ли вообще использовать LSTM модель на таком малом количестве данных? Я решил выяснить это на практике и, в первую очередь, сократить количество факторов (пусть даже это несло в себе потенциальный ущерб в сокращении значимой информации). Я выкинул все факторы, являющиеся расчетными на основе лагов продаж (средние, RSI), погодные факторы (на дневных данных погода не играла значения, а перевод на недельный уровень, тем более, терял какой-то смысл). После этого я, уже традиционно, использовал XGBoost, чтобы отсечь прочие не значимые факторы. В последствии я дополнительно отсек еще несколько факторов, на основе LSTM модели, просто поочередно исключая факторы, обучая модель заново и сравнивая результаты.

Конечный список факторов выглядит следующим образом:

  • Соотношение цены за килограмм исследуемого товара и грунтовки CERESIT СТ 17 10 л.;
  • Соотношение цены исследуемого товара и товара и грунтовки CERESIT СТ 17 10 л;
  • Соотношение цены исследуемого товара и грунтовки EURO PRIMER 3 л;
  • Соотношение цены на исследуемый товар и минимальной цены у конкурентов;
  • Дамми переменные на три рекламные акции на уровне сети;
  • Дамми переменные весеннего, летнего, осеннего сезонов;
  • Лаги 1 – 5 недельных продаж исследуемого товара.

Всего 15 факторов (по 9 наблюдений на фактор).

Итоговая LSTM модель была написана с использованием Keras, включала в себя 2 скрытых слоя (25 и 20 нейронов соответственно), и активатор – сигмоиду.

Код конечной LSTM модели с использованием Keras:

model = Sequential()
model.add(LSTM(25, return_sequences=True, input_shape=(1, trainX.shape[2])))
model.add(LSTM(20))
model.add(Dense(1, activation=’sigmoid’))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, epochs=40, batch_size=1, verbose=2)
model.save('LSTM_W.h5')

Результат:

image

image

Качество предсказания на тестовой выборке выглядело достаточно убедительно по метрике, однако, на мой взгляд, все-таки, до идеала не дотягивало, поскольку, не смотря на достаточно точное определение среднего уровня продаж, всплески в отдельно взятые недели могли быть довольно сильно отклоняться от «среднего» уровня продаж, что давало сильно отклонение прогноза продаж от реальности в отдельные дни (вплоть до 50%). Тем не менее, я использовал эту модель уже непосредственно для эксперимента на практике.

Интересно также увидеть, как выглядит восстановленная кривая спроса по цене. Для этого я прогнал модель по диапазону цен и, на основе предсказанных продаж, построил кривую спроса:

image

Эксперимент


Каждую неделю, сеть предоставляла данные о продажах за предыдущую неделю по Санкт-Петербургу, а также цены у конкурентов. На основе этих данных, я проводил оптимизацию цены для максимизации ожидаемой прибыли, говорил цену, которую сеть должна выставить на следующую неделю, что она и делала. Так продолжалось на протяжении 4 недель (срок был оговорен с ретейлером).

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

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

Предсказание объема продаж:

image

Предсказание прибыли:

image

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

Сводные результаты за 4 недели:

image

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

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

Но не стоит также и забывать, что 4 недели – это краткосрочный период и эксперимент был проведен только на одном товаре. На долгосрочном периоде, завышение цены на товары в магазине приводит, как правило, к падению продаж в целом по магазину. Чтобы подтвердить свою догадку на этот счет, я решил, используя XGBoost проверить, есть ли у потребителей «память» на цены за предыдущие периоды (если в прошлом было дороже «в целом» чем у конкурентов, потребитель уходит к конкурентам). Т.е. будет ли оказывать на продажи по группам товаров средний уровень цен по группе за последние 1, 3 и 6 месяцев.

image

Действительно, догадка подтвердилась: так или иначе, средний уровень цен за предыдущие периоды влияет на продажи в текущем периоде. Это значит, что проводить оптимизацию цены в текущем периоде по отдельно взятому товару мало – необходимо учитывать также общий уровень цен в долгосрочном периоде. Что, в целом, приводит к ситуации, когда тактика (максимизация прибыли сейчас) противоречит стратегии (выживание в конкурентной борьбе). Это, однако, уже лучше отдать на откуп маркетологам.

Учитывая полученные результаты и опыт на мой взгляд, наиболее оптимально, система ценообразования на основе прогноза продаж могла бы выглядеть следующим образом:

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

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

→ На основе проделанной работы, я подготовил проект в моем репозитории

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

Надеюсь мой опыт поможет в том, чтобы определить границы использования методов МО и покажет, что терпение и упорство позволяют достигнуть результатов, даже если вы не являетесь профессионалом в какой то области.
Tags:
Hubs:
+4
Comments6

Articles

Change theme settings