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

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

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

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

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

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

  • Класс 1: клиенты, которые приобрели продукт в рамках маркетинговой кампании (1/1).
  • Класс 2 – клиенты, которые не откликнулись на маркетинговую кампанию (1/0).
  • Класс 3: клиенты, которые приобрели продукт без маркетинговой кампании (0/1).
  • Класс 4: клиенты, которые не подвергались маркетинговой кампании и не покупали продукт (0/0).

В конце этапа моделирования клиенты, помеченные моделью как класс 1 (1/1), станут целью маркетинговой кампании.

Примечание. Результаты модели, упомянутой в этой статье, в режиме реального времени не только позволили добиться в 3 раза более высокой скорости отклика кампании, чем обычная кампания, но также свели к минимуму затраты на SMS и значительно затраченное время за счет сокращения количества клиентов, которым нужно отправить SMS. /Push-уведомления примерно 100 раз.

Этап подготовки данных

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

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

С помощью этих классов мы будем устранять;

  • Класс 2. Клиенты, которые не отвечают/не покупают, даже если к ним относятся с помощью кампании (Не беспокоить)
  • Класс 3: клиенты, которые отвечают/покупают, даже если к ним не относятся с кампанией (Sure Things).
  • Класс 4 : Упущенные причины

Таким образом, мы сосредоточимся только на классе 1 (Persuadables).

Этап предварительной обработки данных

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

Во-первых, проверяется соотношение нулевого значения каждой функции.

df_na = (df.isnull().sum() / len(df)) * 100
df_na = df_na.drop(df_na[df_na == 0].index).sort_values(ascending=False)[:100]
missing_data = pd.DataFrame({'Missing Ratio' :df_na})
missing_data.head(50)

Мы можем построить отношения пропущенных значений в порядке возрастания

missingdataplot=pd.DataFrame(missing_data)
missingdataplot.plot(kind='barh', figsize=(12, 14),  zorder=2, width=0.85)
plt.suptitle('Missing Value Ratio',fontsize=20)
txt="Figure 3 - Missing Value Ratio of Features after dropping"
plt.figtext(0.5, 0.05, txt, wrap=True, horizontalalignment='center', fontsize=12)

Обработка пропущенных значений будет различаться в зависимости от

  • MCAR — отсутствует полностью случайным образом
  • MAR — Случайно пропавшие без вести
  • MNAR — Пропал без вести не случайно

Существуют также методы обработки пропущенных значений;

  • Удаление — Удаление
  • Заполнение константой, средним значением или модой
  • Назад — вперед Заполнение
  • Вменение (KNN, итеративное и т. д.)

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

mask = df.isna().sum() / len(df) < 0.4
reduced_df = df.loc[:, mask]
print(df.shape)
print(reduced_df.shape)

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

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

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

plt.figure(figsize=(16, 6))
mask = np.triu(np.ones_like(df.corr(), dtype=np.bool))
heatmap = sns.heatmap(df.corr(), mask=mask, vmin=-1, vmax=1, annot=True, cmap='BrBG')
heatmap.set_title('Triangle Correlation Heatmap', fontdict={'fontsize':18}, pad=16);

Мы можем установить значение корреляции (в данном случае %70) и отбросить объекты с корреляцией более 70%.

corr_matrix = reduced_df.corr().abs()
mask = np.triu(np.ones_like(corr_matrix, dtype=bool))
tri_df = corr_matrix.mask(mask)
#Correlation Value(r > 0.70)
to_drop = [c for c in tri_df.columns if any(tri_df[c] > 0.70)]
# Drop
reduced_df1 = reduced_df.drop(to_drop, axis=1)
print("The reduced_df dataframe has {} columns".format(reduced_df.shape[1]))
print("The reduced_df1 dataframe has {} columns".format(reduced_df1.shape[1]))

Этап моделирования

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

  • y — цель нашей модели, которая состоит из 4 разных значений класса.
  • X — Набор функций после исключения нулевых и высококоррелированных функций.
from sklearn.model_selection import train_test_split
y = reduced_df['TARGET']
X=reduced_df.drop('MODELTARGET',axis=1)

Фитинг LightGBM Classifier:

import lightgbm as lgb
X_train, X_test, y_train, y_test = train_test_split(X, y,stratify=y, test_size=0.20, random_state=0)
lgb=lgb.LGBMClassifier()
lgb.fit(X_train, y_train)


Результаты и оценка

Обратите внимание, что разница в точности обучения и теста не должна превышать 5 единиц.

from sklearn.metrics import classification_report
report = classification_report(y_test, predicted)
print(report)

Построение важности функций

importances = lgb.feature_importances_
# Sort importances
sorted_index = np.argsort(importances)
# Create labels
labels = X.columns[sorted_index]
# Clear current plot
plt.clf()
# Create plot
plt.figure(figsize=(25,25))
plt.barh(range(X.shape[1]), importances[sorted_index], tick_label=labels)
plt.suptitle('Predictor Importance',fontsize=20)
txt="Figure 9 - Feature Importance for Light GBM Model"
plt.figtext(0.5, 0.05, txt, wrap=True, horizontalalignment='center', fontsize=12)
plt.show()

ОСНОВНЫЕ ВЫВОДЫ

  • Подготовьте данные для моделирования с функциями, которые кажутся важными в соответствии с потребностями бизнеса/кампании, и пометьте клиентов, как описано выше.
  • Тщательно проверяйте данные, визуализируйте (Исследовательский анализ данных)
  • Предварительно обработайте данные (нулевые значения, сильно коррелированные признаки, пороговое значение дисперсии и т. д.)
  • Выберите алгоритм (в данном случае классификатор), подберите и предскажите модель
  • Проверить матрицу путаницы и отчет о классификации
  • Сопоставьте новые данные, которые модель никогда не видела, и отправьте кампанию клиентам, помеченным как класс 1. Мы не отправляем кампанию клиентам, помеченным как класс 2, 3 и 4.
  • Проверяйте результаты в режиме реального времени

Следующие статьи будут о;

  • Обработка пропущенных значений
  • Подробный выбор функций (RFE, Boruta и т. д.)
  • Обработка несбалансированных классов (SMOTE, Tomek Links и т. д.)
  • Сравнение алгоритмов классификатора