Маркетинговая кампания по электронной почте

Недавно я прошел «вызов машинного обучения» для крупной компании из ОАЭ.

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

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

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

email_table — информация о каждом отправленном электронном письме

электронный идентификатор

email_text (короткий и длинный тест)

электронная почта_версия

Час

будний день

страна_пользователя

user_past_purchases

email_opened_table — идентификатор писем, которые были открыты хотя бы один раз.

электронный идентификатор

link_clicked_table — идентификаторы писем, ссылка внутри которых была нажата хотя бы один раз.

электронный идентификатор

Описание задачи:

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

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

• Какой процент пользователей открыл электронное письмо и какой процент нажал на ссылку

внутри письма?

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

переход по ссылке внутри письма?

  • Насколько, по вашему мнению, ваша модель улучшит рейтинг кликов (определяемый как количество пользователей, которые нажимают на ссылку/общее количество пользователей, получивших электронное письмо). Как бы вы это проверили?
  • Нашли ли вы какую-нибудь интересную закономерность в том, как кампания по электронной почте работала для разных сегментов пользователей? Объяснять.
  • Насколько, по вашему мнению, ваша модель улучшит рейтинг кликов (определяемый как количество пользователей, которые нажимают на ссылку/общее количество пользователей, получивших электронное письмо). Как бы вы это проверили?
  • Нашли ли вы какую-нибудь интересную закономерность в том, как кампания по электронной почте работала для разных сегментов пользователей? Объяснять.

Начнем СЕЙЧАС:

Импортируйте правильные библиотеки

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
from sklearn.metrics import accuracy_score, precision_recall_fscore_support
import warnings
warnings.filterwarnings('ignore')

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

"emails {}, opened {}, clicked {}, email opened {:.2f}, link clicked {:.2f}".format(
    emails.shape[0],
    email_opened.shape[0],
    link_clicked.shape[0],
    100 * email_opened.shape[0]/emails.shape[0],
    100 * link_clicked.shape[0]/emails.shape[0]
)

исследование данных: эффективность кампании по электронной почте для разных сегментов пользователей **

click_vals = link_clicked['email_id'].values
def clicks_encoder(x):
    if x in click_vals:
        return 1
    else:
        return 0
emails['click'] = emails['email_id'].apply(lambda x:clicks_encoder(x))
sns.countplot(x='email_text',hue='click',data=emails);

sns.countplot(x='email_version',hue='click',data=emails);

sns.countplot(x='hour',hue='click',data=emails);

sns.countplot(x='weekday',hue='click',data=emails);

sns.countplot(x='user_country',hue='click',data=emails);

sns.countplot(x='user_past_purchases',hue='click',data=emails);

› Информация о том, как эффективна кампания по электронной почте для разных сегментов пользователей:

* Анализ не внушает оптимизма, так как только 10% отправленных писем открываются и только 2% переходят по ссылке внутри письма
* В глобальном масштабе количество ненажатий очень велико по сравнению с кликами: 10% против 2% : это доказывает, что случайная выборка не является хорошей идеей, поскольку нам нужно ориентироваться на заинтересованных клиентов

Из анализа данных видно, что:

* Короткое персонализированное электронное письмо привлекло больше кликов
* Больше кликов было получено с 5:00 до 13:00
* Понедельник, вторник, четверг среда кажутся благоприятными днями для кликов
* Клиенты из США больше интересуются электронные письма → больше кликов
* В разделе «Далее» вы можете найти показатели разговоров: они подтверждают эти выводы.

**Создание плотной последовательности модели для прогнозирования электронных писем с высокой вероятностью перехода по ссылке **

#adding new features to the email table
link_clicked['clicked']=1
email_opened['opened']=1
emails_joined = emails.set_index('email_id').join(
    email_opened.set_index('email_id'), 
    lsuffix='_caller', 
    rsuffix='_other'
).join(
    link_clicked.set_index('email_id'), 
    lsuffix='_caller', 
    rsuffix='_other'
)
emails_joined = emails_joined.fillna(0)
emails_joined.tail()

### *Кодировка метки*

#this is the helper file
#the helper is attached if MAF team is used to call helpers
from sklearn.preprocessing import LabelEncoder
def encode_label(values):
    encoder = LabelEncoder()
    encoder.fit(values)
return encoder.transform(values), encoder
#coding features as one can only feed numbers to the neural nets
emails_joined["email_text"], email_text_encoder = encode_label(emails_joined["email_text"].values)
emails_joined["email_version"], email_version_encoder = encode_label(emails_joined["email_version"].values)
emails_joined["weekday"], weekday_encoder = encode_label(emails_joined["weekday"].values)
emails_joined["user_country"], user_country_encoder = encode_label(emails_joined["user_country"].values)

Поезд и тест пролиты

from sklearn.model_selection import train_test_split
x_cols = ["email_text", "email_version", "weekday", "user_country", "hour"]
y_cols = ["opened", "clicked"]
x_data = emails_joined[x_cols]
y_data = emails_joined[y_cols]
X_train, X_test, y_train, y_test = train_test_split(x_data, y_data, test_size=0.10, random_state=42)
X_train.shape, X_test.shape, y_train.shape, y_test.shape

### Масштабирование данных

#data normalizing method
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(X_train)
X_train_standard = ss.transform(X_train)

*### Реализация модели*

from keras.models import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Dense(12, input_dim=5, activation='relu'))
model.add(Dense(12, activation='relu'))
model.add(Dense(2, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()

model.fit(X_train_standard, y_train, epochs=10, batch_size=32)

Проверка

X_test_standard = ss.transform(X_test)
model.evaluate(X_test_standard, y_test)

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

БОНУУУУССС

#testing on one instance by calling the trained model
def get_label(confidence):
    return "yes" if confidence >= 0.5 else "no"
result = model.predict(X_test_standard[:1])
predicted_clicked = []
actual_clicked = []
predicted_opened = []
actual_opened = []
for y_hat, y_true in zip(result, y_test[:1].values):
    for y_h, y_t, y_col in zip(y_hat, y_true, y_cols):
        if y_col == "clicked":
            predicted_clicked.append(get_label(y_h))
            actual_clicked.append(get_label(y_t))
        else:
            predicted_opened.append(get_label(y_h))
            actual_opened.append(get_label(y_t))
result = pd.DataFrame()
result["actual_clicked"] = actual_clicked
result["actual_opened"] = actual_opened
result["predicted_clicked"] = predicted_clicked
result["predicted_opened"] = predicted_opened
print(result)

**Сравнение с классификатором случайного леса**

from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier()
rf.fit(X_train_standard, y_train)
y_pred = rf.predict(X_test_standard)
print("Accuracy Metric")
print(accuracy_score(y_test, y_pred))

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

Спасибо за поощрение этой работы. Я надеюсь, что это поможет сообществу!!!