Сегодня мы продолжим погружение в тему оптимизации CRM маркетинга при рассылке промо-предложений и рассмотрим опыт применения RFM-сегментации для решения этой задачи в рамках сервиса доставки еды и продуктов притания Delivery Club, ныне присоединившегося к группе компаний крупного e-com сервиса.

Основной вопрос менеджера CRM аналитику
Основной вопрос менеджера CRM аналитику

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

Иллюстрации взяты из открытых источников и также созданы самим автором данной статьи.

Содержание

I. RFM-анализ для оптимизации промо-акций:

  1. Общее описание задачи и целей оптимизации промо;

  2. Общий алгоритм RFM-сегментации;

  3. Формирование стратегии коммуникаций;

  4. Post-hoc анализ.

II. Методы формирования RFM-сегментов. 
Общее описание:

  1. Статистический анализ;

  2. Кластеризация методами машинного обучения.

III. Последующие шаги развития системы: куда и как двигаться?

Заключение

Acknowledgments

RFM-анализ для промо-акций

1. Общее описание задачи и целей оптимизации промо

Популярной механикой работы с клиентской базой в рамках CRM маркетинга в e-commerce сервисах является рассылка промо-кодов определенным группам пользователей. 

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

Обозначенные задачи можно формализовать в ряд метрик, с которыми можно работать в процессе оптимизации. Среди них, к примеру, могут быть: Retention Rate или RR, Stickiness, AOV или средний чек, RPO, RPU, Revenue кумулятивный, GMV или оборот, Churn Rate, кумулятивные затраты на повышение RR, LTV, CPO, CPU и др.

Метрики, оптимизируемые в процессе работы с промо-акциями в CRM маркетинге
Метрики, оптимизируемые в процессе работы с промо-акциями в CRM маркетинге

Одним из наиболее простых и эффективных способов оптимизации стоимости компаний по рассылке промо-кодов и повышения Retention является сегментирование аудитории покупателей-клиентов в приложении.

2. Общий алгоритм RFM-сегментации

RFM-анализ — метод исследования особенностей поведения пользователей в процессе покупки, применяемый при сегментации пользователей, основанный на оценке метрик давности (recency или R), частоты (Frequency или F) и суммы затрат на покупки (Monetory или M), призванный помочь определить клиентов, приносящих больший оборот продукции, GMV, и своевременно выявить клиентов, которые потенциально могут уйти в отток.

Recency, Frequency, Monetory
Recency, Frequency, Monetory

Исходя из исходной постановки целей оптимизации, RFM-анализ может применяться для нескольких задач:

  1. Формирование стратегии коммуникаций;

  2. Post-hoc анализ.

Примеры использования результатов:

  1. Витрина сегментов аудитории, tracking перетекания и оттока;

  2. Формирование стратегий коммуникации для различных сегментов: передача id кластера в качестве дополнительной метки пользователя в CRM-систему.

3. Формирование стратегии коммуникаций

Проведя сегментацию клиентов, мы сможем увидеть ярко выраженные паттерны поведения групп пользователей в отдельных кластерах по R, F и M метрикам, например:

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

  • Давность захода R: 
    - 1 — недавние клиенты в рамках рассматриваемого периода,
    - 2 — клиенты со средней и чуть ниже средней давностью захода в рамках периода;
    - 3 — клиенты со средней и чуть выше средней давностью захода в рамках периода;
    - 4 — клиенты с давним последним заходом, относящимся к началу рассматриваемого периода и не заходившие давно;

  • Частота F:
    - 1 — высокочастотные клиенты в рамках рассматриваемого периода, с большим количеством покупок,
    - 2 — клиенты со средней частотой и чуть выше, чем средней частотой покупок в рамках периода;
    - 3 — клиенты со средней частотой и чуть ниже, чем средней частотой покупок в рамках периода,
    - 4 — низкочастотные клиенты с наименьшим числом покупок в рамках рассматриваемого периода;

  • Сумма покупок M:
    - 1 — клиенты с наибольшей суммой покупок в рамках рассматриваемого периода,
    - 2 — клиенты со средней и чуть выше средней суммой покупок в рамках периода;
    - 3 — клиенты со средней и чуть ниже, чем средней суммой покупок в рамках периода ,
    - 4 — клиенты с наименьшей суммой покупок в рамках рассматриваемого периода;

Исходя из значений RFM показателей в кластерах можно выделить определенные группы и особенности поведения пользователей этих кластеров, описав каждый кластер или набор из нескольких кластеров по показателям метрик в этом кластере или наборе:

Сегменты клиентов по кластерам RF
Сегменты клиентов по кластерам RF

Исходя из особенностей группы формируются и стратегии коммуникации с нею:

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

  • отточников нужно возвращать уже при помощи более настойчивых стратегий и, возможно, прибавляя к CRM-механикам, включающим пуши, SMS, ещё и performance-рекламные компании — предлагайте им альтернативные товары и категории, не скупитесь на скидки, рассказывайте о нововведениях, особых возможностях, новостях об улучшении интерфейсов и функциональности приложения, актуальных предложениях, специальных персональных скидках и снижении цен, улучшении состава товаров в каталогах и их качественных усовершенствованиях,

  • лояльных можно сделать VIP-группой, которой предлагают продукты из premium-категорий, более дорогие по цене, наблюдая за реакцией, их нужно не трогать большую часть времени, однако подкреплять их интерес периодически пушами с благодарностью и, возможно, предлагая anniversary codes на какие-то особые даты, или редкими пушами с потенциально интересными категориями товаров, которые клиенты ещё не приобретали, но по схожести их интересов могут быть заинтересованы;

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

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

Важно отметить новичков, c которыми нужно продумать отдельные стратегии коммуникации: новые клиенты, зарегистрировавшиеся в рамках периода недавно, пока сложны для проведения анализов и составления выводов — о них у нас не так много данных и, следовательно, о них сложно сделать выводы в моменте. Кроме того, возможно им нужен онбординг больше, чем скидочные предложения.

4. Post-hoc анализ

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

Изменение доли сегментов с течением времени
Изменение доли сегментов с течением времени

Это позволяет делать выводы о “здоровье” сервиса, например, если растет доля пользователей в оттоке, но при этом достаточно высока доля новых пользователей, это сигнал, что пользователи не задерживаются на сервисе и время проводить исследование причин — плохой сервис и недовольство пользователей, неправильные таргетинги с привлечением нерелевантной аудитории, изменение коньюнктуры рынка и в особенности спроса под воздействием внешних обстоятельств или какие-то другие причины, и найдя их, начать “лечить”.

Изменения доли сегментов на протяжении месяца до и месяца после рассылки
Изменения доли сегментов на протяжении месяца до и месяца после рассылки

После проведения очередного цикла промо-акций, можно провести повторную сегментацию пользователей и посмотреть на изменения соотношений в сегментах. Кроме того, можно посмотреть распределение долей сегментов на тех же пользователях, которые участвовали в предыдущем цикле рассылок, без учета новых регистраций и покупателей, привлеченных уже после старта предыдущего цикла рассылок — это позволит понять влияние именно на retention core-аудитории, не фокусируясь на результатах работы acquisition стратегий, которые непосредственно влияют на долю новых.

Изменения доли сегментов на протяжении месяца до и месяца после рассылки
Изменения доли сегментов на протяжении месяца до и месяца после рассылки

Таким образом RFM-сегментацию можно использовать также и для проведения Post-hoc анализа проводимых промо-акций и больших промо-компаний.

Методы формирования RFM-сегментов. Общее описание

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

1. Статистический анализ

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

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.cluster import KMeans
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
import warnings
warnings.filterwarnings("ignore")

data = pd.read_csv('/data/rfm_data.csv')

data.describe()

Визуализируем распредение наших данных:

plt.figure(figsize=(12,12))
plt.subplot(311)
data['Recency'].hist(bins=40, alpha=0.8, label='Value', 
                     edgecolor='white', linewidth=2)
plt.ylabel('Recency')
plt.subplot(312)
data['Frequency'].hist(bins=40, color = 'green', alpha=0.8, label='Value', 
                       edgecolor='white', linewidth=2)
plt.ylabel('Frequency')
plt.subplot(313)
data['Monetory'].hist(bins=40, color = 'yellow', alpha=0.8, label='Value', 
                      edgecolor='white', linewidth=2)
plt.ylabel('Monetory')
plt.show()

Первый простой метод, которым мы воспользуемся, это квантильный RFM:

### 1. Квантильный RFM:
def rfm_quantile(rfm_data: pd.DataFrame() = None, metrics: list() = None, q: int = 4):
    if rfm_data is None:
        return None
    if metrics is None:
        metrics = rfm_data.columns[1:]
    Recency, Frequency, Monetary = metrics
    rfm_data[metrics] = rfm_data[metrics].dropna().astype('int64')

    labels = range(q, 0, -1)
    rfm_data['R'] = pd.qcut(rfm_data[Recency], q=q, labels=labels[::-1]).values
    rfm_data['F'] = pd.qcut(rfm_data[Frequency], q=q, labels=labels).values
    rfm_data['M'] = pd.qcut(rfm_data[Monetary], q=q, labels=labels).values
    rfm_data['RFM_Segment'] = rfm_data.apply(lambda x: str(x['R']) +
                                                       str(x['F']) +
                                                       str(x['M']), axis=1)
    rfm_data['RF_Segment'] = rfm_data.apply(lambda x: str(x['R']) +
                                                       str(x['F']), axis=1)
    rfm_data['FM_Segment'] = rfm_data.apply(lambda x: str(x['F']) +
                                                       str(x['M']), axis=1)
    rfm_data['RFM_Score'] = rfm_data[['R', 'F', 'M']].sum(axis=1)
    return rfm_data

Суть метода очень проста: в качестве кластеров принимаются границы квартилей [0..25), [25..50), [50..75), [75..100]. Проведем моделирование и посмотрим на результаты:

rfm_result = rfm_quantile(data, metrics = ['Recency', 'Frequency', 'Monetory'], q = 4)

Посмотрим на тепловую карту получившихся кластеров:

rfm_aggr = rfm_result[['user_id', 'R', 'F']].groupby(['R', 'F']).user_id.nunique().reset_index()
rfm_pivot = rfm_aggr.pivot(values = 'user_id', index='R', columns='F')
sns.heatmap(rfm_pivot, annot=True, fmt=".0f")
Количество пользователей в кластерах, построенных методом квартилей
Количество пользователей в кластерах, построенных методом квартилей

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

rfm_aggr['users_share'] = rfm_aggr['user_id']*1.0/\
                          rfm_aggr['user_id'].sum()*100.0
sns.heatmap(rfm_aggr.pivot(values = 'users_share', 
                           index='R', columns='F'), annot=True, fmt=".3g")
Доля пользователей в кластерах, построенных методом квартилей
Доля пользователей в кластерах, построенных методом квартилей

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

2. Кластеризация методами машинного обучения

В качестве метода кластеризации мы воспользуемся простым алгоритмом k-средних, который заключается в определении элементов множества, точек, ближайшим образом расположенных к предварительно случайным образом выбранным центроидам кластеров. При этом реализуем как кластеризацию по каждому отдельному параметру из множества R, F, M, так и по всем 3-м параметрам вместе. Ниже представлена разработанная на основе этого требования функция кластеризации:

def rfm_kmeans(rfm_data: pd.DataFrame() = None, metrics: list() = None, name: str = '', n_clusters: int = 4):
    if rfm_data is None:
        return None
    if metrics is None:
        metrics = rfm_data.columns[1:]
    # Сlustering
    Recency, Frequency, Monetary = metrics

    kmeans_clusters = KMeans(n_clusters=n_clusters, init='k-means++', 
                             max_iter=300, random_state=0)
    kmeans_clusters.fit(rfm_data[[Recency]].dropna().astype('int64'))
    rfm_data['R_Cluster'] = 4-kmeans_clusters.labels_

    kmeans_clusters = KMeans(n_clusters=n_clusters, init='k-means++', 
                             max_iter=300, random_state=0)
    kmeans_clusters.fit(rfm_data[[Frequency]].dropna().astype('int64'))
    rfm_data['F_Cluster'] = kmeans_clusters.labels_+1

    kmeans_clusters = KMeans(n_clusters=n_clusters, init='k-means++', 
                             max_iter=300, random_state=0)
    kmeans_clusters.fit(rfm_data[[Monetary]].dropna().astype('int64'))
    rfm_data['M_Cluster'] = kmeans_clusters.labels_+1

    kmeans_clusters = KMeans(n_clusters=n_clusters, init='k-means++', 
                             max_iter=300, random_state=0)
    kmeans_clusters.fit(rfm_data[metrics].dropna().astype('int64'))
    # Assign the clusters to datamart
    rfm_data['K_Cluster'] = kmeans_clusters.labels_+1
    return rfm_data

Для запуска алгоритма кластеризации k-средних необходимо предварительно определить количество кластеров, поможет в этом нам метод “локтя”, то есть моделирования метрики внутри-кластерной суммы квадратов расстояний между точками кластера и центроидами кластера, иначе называемой инерцией, и выбора точки, после которой при увеличении количества кластеров инерция перестает снижаться и выходит фактически на плато:

def wcss(rfm_data: pd.DataFrame() = None, metrics: list() = None):
    if rfm_data is None:
        return None
    if metrics is None:
        metrics = rfm_data.columns

    wcss = {}
    for k in range(1, 11):
        kmeans = KMeans(n_clusters=k, init='k-means++', max_iter=300)
        kmeans.fit(rfm_data)
        wcss[k] = kmeans.inertia_
    # plot the WCSS values
    sns.pointplot(x=list(wcss.keys()), y=list(wcss.values()))
    plt.xlabel('K Numbers')
    plt.ylabel('WCSS')
    plt.show()
    return

wcss(data[['Recency', 'Frequency', 'Monetory']])
Инерция в зависимости от количества кластеров, ручной метод
Инерция в зависимости от количества кластеров, ручной метод

Как можно видеть, не смотря на хорошую сходимость метода иногде определить на графике “локоть”, точку перегиба — из графика не очевидно, это точка с количеством кластеров 3 или 4 или какая-то другая.

Воспользуемся библиотекой YelloBrick для более точного определения количества кластеров. YelloBrick — это удобная библиотека для автоматизации и визуализации подобных расчетов и исследований в машинном обучении, упрощающая многие операции предварительного анализа для последующего моделирования методами ML. Определение количества кластеров при помощи билиотеки YellowBrick очень простое и наглядное:

from yellowbrick.cluster import KElbowVisualizer
# Instantiate the clustering model and visualizer
model = KMeans()
visualizer = KElbowVisualizer(model, k=(1,12))
visualizer.fit(data[['Recency', 'Frequency', 'Monetory']]) # Fit the data to the visualizer
visualizer.show() # Finalize and render the figure
Инерция в зависимости от количества кластеров — библиотека YellowBricks
Инерция в зависимости от количества кластеров — библиотека YellowBricks

Теперь мы видим, что нам подходит использование разбивки на 4 кластера.

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

Проведем моделирование алгоритмом k-средних и визуализируем результаты:

result = rfm_kmeans(data[['user_id', 'Recency', 'Frequency', 'Monetory']], 
                    n_clusters=4)
rfm_aggr = result[['user_id', 'R_Cluster', 'F_Cluster']].\
                    groupby(['R_Cluster', 'F_Cluster']).user_id.nunique().reset_index()
rfm_pivot = rfm_aggr.pivot(values = 'user_id', index='R_Cluster', columns='F_Cluster')
Количество пользователей в кластерах, построенных методом k-means
Количество пользователей в кластерах, построенных методом k-means

Как можно видеть, кластера распределены уже не так равномерно и красиво, как при моделировании при помощи квантильного подхода. В процентном соотношении также наблюдается смещение внутри определенных кластеров:

rfm_aggr['users_share'] = rfm_aggr['user_id']*1.0/rfm_aggr['user_id'].sum()*100.0
sns.heatmap(rfm_aggr.pivot(values = 'users_share', index='R_Cluster', 
                           columns='F_Cluster'), annot=True, fmt=".3g")
Доля пользователей в кластерах, построенных методом k-means
Доля пользователей в кластерах, построенных методом k-means

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

Последующие шаги развития системы: куда и как двигаться?

Как мы и проговорили изначально выше, RFM-сегментация — это довольно простой алгоритм, основные достоинства которого — простота реализации и довольно высокая для такого базового алгоритма эффективность, однако существуют и более эффективные модели, которые применяются на практике для повышения точности и полноты результатов:

Модели оттока
Модели оттока
  1. Класс моделей оттока:
    Уточнение сегментации vможно проверсти путем создания модели оттока — в ней мы предсказываем вероятность покупки или её отсутствия через N дней и отправляем сообщение пользователям с наименьшей вероятностью покупки;

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

Сложная красота математики uplift-модели
Сложная красота математики uplift-модели

Заключение

Все мы в рамках e-commerce сервисов стремимся к оптимизации cost’ов и повышению лояльности пользователей, применяя при этом затратные стратегии, к примеру, рассылки промо-кодов, и хотим делать это наиболее эффективно. Рассмотренные нами выше простые методики могут в этом и не займут много времени для реализации в качественной инфраструктуре. Пробуйте, экспериментируйте и добивайтесь более эффективных результатов.

Данный метод ранее освещался в виде доклада на ряде конференций (EpicGrowth Meetup-2021, Нетология, митапы в рамках программы VK Study и Worki@Mail.Ru) и образовательных курсов и получил высокие оценки от участников в рамках программы повышения квалификации в VK Company (former Mail.Ru Group) и программ обучения студентов VK Образования в МГТУ им. Н.Э.Баумана, МГУ им. М.В.Ломоносова и других ВУЗов, поэтому надеемся, что он будет полезен и интересен более широкой аудитории.

Acknowledgments

Former Delivery Club Tech Presents…
Former Delivery Club Tech Presents…

Задумка и вдохновение на написание статьи появились достаточно давно, и вот, наконец, появилась возможность реализовать задуманное и передать опыт решения интересной и полезной задачи.
За крутые задачи хочу особенно отметить команду ???? Деливери Клаб:
своего потрясающего team-lead'а в Деливери Клаб Лёшу Пыжика,
своих непосредственных заказчиков
CMO, директора по маркетингу, директора по развитию крутейшего Олега Хаустова,
директора по CRM крутейшего Андрея Ленеца
и всех наших потрясающих маркетологов и CRM-менеджеров,
продактов и всех, всех, всех сопричастных коллег.
Всем добра и Big Data :)

Комментарии (0)