Рост, управляемый данными с помощью Python

Модели реакции рынка

Прогнозирование прироста рекламных кампаний

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

Я расскажу обо всех темах в следующих девяти статьях:

1- Знай свои показатели

2- Сегментация клиентов

3- Прогнозирование жизненной ценности клиента

4- Прогнозирование оттока

5- Прогнозирование следующего дня покупки

6- Прогнозирование продаж

7- Модели реакции рынка

8- Моделирование подъемов

9- Дизайн и проведение A / B-тестирования

В статьях будут собственные фрагменты кода, чтобы вы могли их легко применять. Если вы новичок в программировании, вы можете получить хорошее введение в Python и Pandas (известная библиотека, которую мы будем использовать во всем) здесь. Но все же без введения в кодирование вы можете изучить концепции, как использовать свои данные и начать извлекать из них пользу:

Иногда нужно бежать, прежде чем ходить - Тони Старк

В качестве предварительного условия убедитесь, что на вашем компьютере установлены J upyter Notebook и P ython. Фрагменты кода будут работать только в Jupyter Notebook.

Хорошо, приступим.

Часть 7: Модели реакции рынка

Используя модели, которые мы построили в предыдущих статьях, мы можем легко сегментировать клиентов и прогнозировать их жизненную ценность (LTV) для целей таргетинга. Кстати, мы также знаем, какими будут наши показатели продаж. Но как мы можем увеличить наши продажи? Если мы сделаем скидку сегодня, сколько дополнительных транзакций нам следует ожидать?

Сегментирование клиентов и проведение A / B-тестов позволяет нам опробовать множество различных идей для увеличения продаж. Это один из строительных блоков Growth Hacking. Вам нужно постоянно придумывать идеи и экспериментировать, чтобы найти возможности для роста.

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

Давайте посмотрим на пример ниже:

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

1- Повышает ли конверсия предложение оффера?

2- Если да, какое предложение работает лучше всего? Скидка или купите один получить один?

Если предположить, что результаты статистически значимы, скидка (группа A) выглядит лучше всего, так как она увеличила конверсию на 3% по сравнению с контрольной группой и принесла на 1% больше конверсии по сравнению с «Купи один - получи один».

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

Теперь мы знаем, какое предложение показало лучшие результаты по сравнению с другими благодаря эксперименту. Но как насчет того, чтобы его предсказать? Если мы спрогнозируем эффект от предложения, мы легко сможем максимизировать наши транзакции и получить прогноз стоимости. Модели реакции рынка помогают нам построить эту основу. Но есть несколько способов сделать это. Мы можем сгруппировать их в две группы:

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

Чтобы построить такую ​​модель, ваш набор данных должен включать данные о продажах в промо-дни и не-промо-дни, чтобы модель машинного обучения могла рассчитать инкрементность.

2- Если у вас есть контрольная группа, вы можете построить модель ответа на основе сегмента или индивидуального уровня. Для них обоих предположение одно и то же. Предоставление предложения должно увеличить вероятность конверсии. Повышение вероятности конверсии отдельных лиц приведет к постепенному увеличению конверсии.

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

Давайте импортируем нужные нам библиотеки и импортируем наши данные:

Первые 10 строк наших данных:

Наши первые 8 столбцов предоставляют данные на индивидуальном уровне, а столбец конверсии - это наш ярлык для прогнозирования:

  • давность: месяцы с момента последней покупки
  • история: $ стоимость исторических покупок
  • used_discount / used_bogo: указывает, использовал ли покупатель скидку или купил ее раньше
  • zip_code: класс почтового индекса как Пригородный / Городской / Сельский
  • is_referral: указывает, был ли клиент привлечен из реферального канала
  • канал: каналы, которые использует клиент, Телефон / Интернет / Многоканальный
  • предложение: предложения, отправленные покупателям, Скидка / Одно предложение / Нет предложения

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

  • Формула подъема
  • Исследовательский анализ данных (EDA) и разработка функций
  • Оценка вероятностей конверсии
  • Наблюдение за результатами на тестовом наборе

Формула подъема

Во-первых, нам нужно создать функцию, которая вычисляет наш подъем. Для простоты предположим, что каждая конверсия означает 1 заказ, а средняя стоимость заказа составляет 25 $.

Мы собираемся рассчитать три типа подъема:

Повышение конверсии: коэффициент конверсии тестовой группы - коэффициент конверсии контрольной группы.

Увеличение количества заказов: рост конверсии * # покупатель, совершивший конверсию в тестовой группе

Увеличение дохода: увеличение количества заказов * Средняя стоимость заказа в $

Давайте создадим нашу функцию calc_uplift:

def calc_uplift(df):
    #assigning 25$ to the average order value
    avg_order_value = 25
    
    #calculate conversions for each offer type
    base_conv = df[df.offer == 'No Offer']['conversion'].mean()
    disc_conv = df[df.offer == 'Discount']['conversion'].mean()
    bogo_conv = df[df.offer == 'Buy One Get One']['conversion'].mean()
    
    #calculate conversion uplift for discount and bogo
    disc_conv_uplift = disc_conv - base_conv
    bogo_conv_uplift = bogo_conv - base_conv
    
    #calculate order uplift
    disc_order_uplift = disc_conv_uplift * len(df[df.offer == 'Discount']['conversion'])
    bogo_order_uplift = bogo_conv_uplift * len(df[df.offer == 'Buy One Get One']['conversion'])
    
    #calculate revenue uplift
    disc_rev_uplift = disc_order_uplift * avg_order_value
    bogo_rev_uplift = bogo_order_uplift * avg_order_value
    
    
    print('Discount Conversion Uplift: {0}%'.format(np.round(disc_conv_uplift*100,2)))
    print('Discount Order Uplift: {0}'.format(np.round(disc_order_uplift,2)))
    print('Discount Revenue Uplift: ${0}\n'.format(np.round(disc_rev_uplift,2)))
          
    print('-------------- \n')
print('BOGO Conversion Uplift: {0}%'.format(np.round(bogo_conv_uplift*100,2)))
    print('BOGO Order Uplift: {0}'.format(np.round(bogo_order_uplift,2)))
    print('BOGO Revenue Uplift: ${0}'.format(np.round(bogo_rev_uplift,2)))

Если мы применим эту функцию к нашему фрейму данных, мы увидим результаты ниже:

Скидка кажется лучшим вариантом, если мы хотим получить больше конверсии. Это дает прирост 7,6% по сравнению с клиентами, которые не получали никаких предложений. У BOGO («Купи один - получи один») также наблюдается рост на 4,5%.

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

EDA и разработка функций

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

1- Давность

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

df_plot = df_data.groupby('recency').conversion.mean().reset_index()
plot_data = [
    go.Bar(
        x=df_plot['recency'],
        y=df_plot['conversion'],
    )
]
plot_layout = go.Layout(
        xaxis={"type": "category"},
        title='Recency vs Conversion',
        plot_bgcolor  = 'rgb(243,243,243)',
        paper_bgcolor  = 'rgb(243,243,243)',
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

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

2- История

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

kmeans = KMeans(n_clusters=5)
kmeans.fit(df_data[['history']])
df_data['history_cluster'] = kmeans.predict(df_data[['history']])
#order the cluster numbers 
df_data = order_cluster('history_cluster', 'history',df_data,True)
#print how the clusters look like
df_data.groupby('history_cluster').agg({'history':['mean','min','max'], 'conversion':['count', 'mean']})
#plot the conversion by each cluster
df_plot = df_data.groupby('history_cluster').conversion.mean().reset_index()
plot_data = [
    go.Bar(
        x=df_plot['history_cluster'],
        y=df_plot['conversion'],
    )
]
plot_layout = go.Layout(
        xaxis={"type": "category"},
        title='History vs Conversion',
        plot_bgcolor  = 'rgb(243,243,243)',
        paper_bgcolor  = 'rgb(243,243,243)',
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Обзор кластеров и графика против конверсии:

Клиенты с более высокой историей в долларах с большей вероятностью конвертируют.

3- использованная скидка и BOGO

Мы проверим эти две функции вместе со следующей строкой кода:

df_data.groupby(['used_discount','used_bogo','offer']).agg({'conversion':'mean'})

Выход:

Клиенты, которые ранее использовали оба предложения, имеют самый высокий коэффициент конверсии.

4- Почтовый индекс

Сельский район показывает лучшую конверсию по сравнению с другими:

df_plot = df_data.groupby('zip_code').conversion.mean().reset_index()
plot_data = [
    go.Bar(
        x=df_plot['zip_code'],
        y=df_plot['conversion'],
        marker=dict(
        color=['green', 'blue', 'orange'])
    )
]
plot_layout = go.Layout(
        xaxis={"type": "category"},
        title='Zip Code vs Conversion',
        plot_bgcolor  = 'rgb(243,243,243)',
        paper_bgcolor  = 'rgb(243,243,243)',
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

5- Реферал

Как мы видим ниже, у клиентов из реферального канала коэффициент конверсии ниже:

У них конверсия почти на 5% меньше.

6-канальный

Многоканальность показывает более высокий коэффициент конверсии, чем мы и ожидали. Использование более чем одного канала - показатель высокой вовлеченности.

7- Тип предложения

Клиенты, получившие предложения со скидкой, показывают конверсию ~ 18%, тогда как для BOGO это ~ 15%. Если клиенты не получат предложения, их коэффициент конверсии снизится примерно на 4%.

Конструирование функций этих данных будет довольно простым. Мы применим .get_dummies () для преобразования категориальных столбцов в числовые:

df_model = df_data.copy()
df_model = pd.get_dummies(df_model)

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

Оценка вероятностей конверсии

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

Начнем с разделения объектов и метки:

#create feature set and labels
X = df_model.drop(['conversion'],axis=1)
y = df_model.conversion

Создание обучающих и тестовых наборов:

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=56)

Подберем модель и получим вероятности конверсии. Функция predit_proba () нашей модели назначает вероятность для каждой строки:

xgb_model = xgb.XGBClassifier().fit(X_train, y_train)
X_test['proba'] = xgb_model.predict_proba(X_test)[:,1]

Давайте посмотрим, как выглядит наш столбец вероятностей:

Из вышесказанного видно, что наша модель присвоила вероятность конверсии (от 0 до 1) для каждого покупателя.

Наконец, нам нужно понять, работает наша модель или нет.

Результаты на тестовом наборе

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

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

Давайте посчитаем прогнозируемый и реальный рост заказов на скидку:

real_disc_uptick = len(X_test)*(X_test[X_test['offer_Discount'] == 1].conversion.mean() - X_test[X_test['offer_No Offer'] == 1].conversion.mean())
pred_disc_uptick = len(X_test)*(X_test[X_test['offer_Discount'] == 1].proba.mean() - X_test[X_test['offer_No Offer'] == 1].proba.mean())

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

Результаты очень хорошие. Реальный рост числа заказов составил 966, и модель предсказала его как 948 (ошибка 1,8%) .

Сравнение прогнозов роста доходов: 24150 против 23700.

Нам нужно проверить, хороши ли результаты и для BOGO:

real_bogo_uptick = len(X_test)*(X_test[X_test['offer_Buy One Get One'] == 1].conversion.mean() - X_test[X_test['offer_No Offer'] == 1].conversion.mean())
pred_bogo_uptick = len(X_test)*(X_test[X_test['offer_Buy One Get One'] == 1].proba.mean() - X_test[X_test['offer_No Offer'] == 1].proba.mean())

Многообещающие результаты для BOGO:

Рост количества заказов - реальный против прогнозируемого: 563 против 595

Рост дохода - реальный против прогнозируемого: 14075 против 14875

Частота ошибок составляет около 5,6%. Модель может выиграть от улучшения оценок прогноза для типа предложения BOGO.

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

Вы можете найти Jupyter Notebook для этой статьи здесь.

Чтобы обсудить маркетинг роста и науку о данных, забронируйте со мной бесплатную сессию здесь.