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

Ресурсы

Утро понедельника. Вы входите в конференц-зал B в Главной телекоммуникационной компании и обнаруживаете, что обычная публика необычайно болтлива, оживлена ​​и нервничает. Их датский никто не трогал. Встреча начинается, и вы слышите новости…

Наша компания потеряла7,75 млн долларов в прошлом месяце из-за оттока клиентов.

Излишне говорить, что это плохо. Время паниковать.

Большое количество клиентов неожиданно ушло в прошлом месяце — наихудший сценарий для бизнес-модели, основанной на подписке.

Глядя на цифры, отток клиентов за последний месяц представляет собой:

  • 35% всех клиентов
  • 25% от всей выручки (пожизненная ценность клиента CLTV)
  • 50% всех новых клиентов, привлеченных за последние 3 квартала

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

Следите за тем, как мы просматриваем данные и решаем эти бизнес-задачи.

Исследовательский анализ данных

Отток клиентов телекоммуникационных компаний 11.3.3+ — это классический набор данных для проектов анализа данных, предоставляемый IBM Cognos Analytics. Всего имеется 6 таблиц, содержащих 7043 строки записей о клиентах и ​​дополнительный контекст по результатам оттока клиентов за последний месяц, контрактным услугам, местонахождению клиентов, демографическим данным и отзывам о выходе из опроса.

После проверки в Excel не обнаружено никаких нулевых значений или обязательной очистки данных (фух!). Я решил сосредоточиться на клиентском опыте и демографических данных, а не на географических данных, затем скомпилировал соответствующие поля из всех листов в один .csv и начал анализировать на Python.

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

Прогнозы машинного обучения

Примечание. Если кодирование на Python вас не интересует, перейдите к следующему разделу.

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

Начнем с импорта всех наших инструментов.

# ------------------
# IMPORT TOOLS
# ------------------
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns


# ------------------
# IMPORT MACHINE LEARNING MODELS
# ------------------
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC
from sklearn.neural_network import MLPClassifier
from sklearn.ensemble import RandomForestClassifier
from xgboost import XGBClassifier
from sklearn.tree import DecisionTreeClassifier


# ------------------
# SET MODEL ALIAS
# ------------------
lr = LogisticRegression()
svm = LinearSVC()
mlp = MLPClassifier()
rf = RandomForestClassifier()
xg = XGBClassifier()
dt = DecisionTreeClassifier()


# ------------------
# IMPORT DATA
# ------------------
telco = pd.read_csv('Telco-churn.csv')

Затем мы устанавливаем разделение обучения/тестирования на 80/20, подбираем модели, оцениваем их и сравниваем результаты.

# ------------------
# TRAIN/TEST SPLIT
# ------------------

# TRAIN / TEST SPLIT
from sklearn.model_selection import train_test_split

# SET TRAIN, TEST GROUPS
train, test = train_test_split(telco, test_size = 0.2)

# IDENTIFY FEATURES / INPUT / HYPOTHESIS / INDEPENDENT VARIABLE
train_feat = train.iloc[:,:23]

# IDENTIFY TARGET / OUTPUT / CONCLUSION / DEPENDENT VARIABLE
train_targ = train['Churn']

# IDENTIFY TEST FEATURES / TARGET
test_feat = test.iloc[:,:23]
test_targ = test['Churn']


# ------------------
# FIT MODELS
# ------------------
lr.fit(train_feat, train_targ)
svm.fit(train_feat, train_targ)
mlp.fit(train_feat, train_targ)
rf.fit(train_feat, train_targ)
xg.fit(train_feat, train_targ)
dt.fit(train_feat, train_targ)


# ------------------
# SCORE MODELS
# ------------------
print('\n____ PREDICTION MODEL ACCURACY ____\n')

print("Logistic Regression Train:",round((lr.score(train_feat, train_targ) * 100),3),"%")
print("Logistic Regression Test:",round((lr.score(test_feat, test_targ) * 100),3),"% \n")

print("LinearSVM Regression Train:",round((svm.score(train_feat, train_targ) * 100),3),"%")
print("Linear SVM Regression Test:",round((svm.score(test_feat, test_targ) * 100),3),"% \n")

print("MLP Classifier Train:",round((mlp.score(train_feat, train_targ) * 100),3),"%")
print("MLP Classifier Test:",round((mlp.score(test_feat, test_targ) * 100),3),"% \n")

print("Random Forest Classifier Train:",round((rf.score(train_feat, train_targ) * 100),3),"%")
print("Random Forest Classifier Test:",round((rf.score(test_feat, test_targ) * 100),3),"% \n")

print("XGBoost Classifier Train:",round((xg.score(train_feat, train_targ) * 100),3),"%")
print("XGBoost Classifier Test:",round((xg.score(test_feat, test_targ) * 100),3),"% \n")


print("Decision Tree Classifier Train:",round((dt.score(train_feat, train_targ) * 100),3),"%")
print("Decision Tree Classifier Test:",round((dt.score(test_feat, test_targ) * 100),3),"% \n")

… результаты:

____ PREDICTION MODEL ACCURACY ____

Logistic Regression Train: 81.7 % 
Logistic Regression Test: 81.405 %

LinearSVM Regression Train: 46.29 % 
Linear SVM Regression Test: 44.074 %

MLP Classifier Train: 77.831 % 
MLP Classifier Test: 77.999 %

Random Forest Classifier Train: 99.982 % 
Random Forest Classifier Test: 81.618 %

XGBoost Classifier Train: 96.752 % 
XGBoost Classifier Test: 81.973 %

Decision Tree Classifier Train: 100.0 % 
Decision Tree Classifier Test: 75.515 %

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

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

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

Двигаясь по часовой стрелке сверху слева:

  • Истинно положительный результат: правильный прогноз оттока.
  • Ошибочное срабатывание: неверно прогнозируется отток.
  • True Negative: правильный прогноз продления.
  • False Negative: неверно предсказано продление.

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

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

Двойной удар.

Давайте сравним результаты матриц путаницы для наших трех лучших моделей: Random Forest, XGBoost и Дерево решений.

# ------------------
# CONFUSION MATRIX RESULTS
# ------------------

from sklearn.metrics import confusion_matrix

cf_rf = confusion_matrix(rf.predict(test_feat),test_targ)
cf_xg = confusion_matrix(xg.predict(test_feat),test_targ)
cf_dt = confusion_matrix(dt.predict(test_feat),test_targ)

print('\n____ CONFUSION MATRIX RESULTS ____\n')
print('\nRandom Forest Classifier Array:\n', cf_rf)
print('\nXGBoost Classifier Array:\n', cf_xg)
print('\nDecision Tree Classifier Array:\n', cf_dt)
____ CONFUSION MATRIX RESULTS ____

Random Forest Classifier Array:
 [[937 166]
 [ 93 213]]

XGBoost Classifier Array:
 [[924 148]
 [106 231]]

Decision Tree Classifier Array:
 [[862 177]
 [168 202]]

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

# CONFUSION MATRIX VIZ //  RANDOM FOREST

group_names = ['True Neg','False Pos','False Neg','True Pos']

group_counts = ['{0:0.0f}'.format(value) for value in
                cf_rf.flatten()]

group_percentages = ['{0:.2%}'.format(value) for value in
                     cf_rf.flatten()/np.sum(cf_rf)]

labels = [f'{v1}\n{v2}\n{v3}' for v1, v2, v3 in
          zip(group_names,group_counts,group_percentages)]

labels = np.asarray(labels).reshape(2,2)

sns.heatmap(cf_rf, annot = labels, fmt = '', cmap = 'Greens')
plt.title('Random Forest Confusion Matrix')
plt.show()

# ------------------
# etc., et al.

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

# ------------------
# FEATURE IMPORTANCE VIZ // RANDOM FOREST // 
# ------------------

importance = rf.feature_importances_
features = train_feat.columns
importance_df = pd.DataFrame({'Feature': features, 'Importance': importance})
importance_df = importance_df.sort_values('Importance', ascending=True)


plt.figure(figsize=(4,4))
plt.barh(importance_df['Feature'], importance_df['Importance'], color = 'Green')
plt.title('Random Forest Feature Importance')
plt.xlabel('Importance Score')
plt.ylabel('Features')
plt.show()


# ------------------
# FEATURE IMPORTANCE //  RANDOM FOREST  //  SUMMARY
# ------------------
print('\n____ FEATURE IMPORTANCE ____\n')
print(importance_df)

____ FEATURE IMPORTANCE ____

                 Feature  Importance
4          Phone Service    0.007547
1                Partner    0.012819
21  Premium Tech Support    0.013043
18     Referred a Friend    0.013093
10          Tech Support    0.014406
12      Streaming Movies    0.016278
11          Streaming TV    0.016674
5         Multiple Lines    0.017132
9      Device Protection    0.018043
22        Unlimited Data    0.018615
8          Online Backup    0.018841
0         Senior Citizen    0.020026
7        Online Security    0.020200
14     Paperless Billing    0.023121
20                 Offer    0.024222
2             Dependents    0.028911
15        Payment Method    0.048659
6       Internet Service    0.050130
19   Number of Referrals    0.081108
13              Contract    0.091829
17                  CLTV    0.135204
16       Monthly Charges    0.150078
3          Tenure Months    0.160020

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

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

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

Таблица Insights

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

«Никто никогда не принимал решение из-за числа. Им нужна история».
— Даниэль Канеман, психолог, поведенческий экономист

Панель управления оттоком клиентов в сфере телекоммуникаций

Нажмите здесь и исследуйте самостоятельно

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

Обзор приборной панели:

  • 1869 оттока клиентов
  • 5 174 новых клиентов
  • Общий доход 31 миллион долларов (CLTV)

Во-первых, давайте сравним клиентов, которые обновились, и тех, кто ушел.

Фильтр: Продления клиентов

Фильтр: Отток клиентов

Теперь мы к чему-то пришли.

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

Фильтр: Домохозяйства с одним родителем

Вопрос.Виновны ли родители-одиночки в оттоке?
Ответ:Конечно, нет.

Домохозяйства с одним родителем составляют только 50 из 1869 ушедших клиентов.

Фильтр: Возраст до 30 лет

Вопрос. Что делать с клиентами младше 30 лет? Они непостоянны?
Ответ: Не совсем.

Молодые люди имеют широкое распределение по сроку пребывания в должности в месяцах и составляют лишь 16% оттока.

Фильтр: Маркетинговое предложение E

Вопрос.Было ли маркетинговое предложение E действительно плохой сделкой?
Ответ:Да, как для клиента, так и для компании.

Предложение E было реализовано за последние 9 месяцев, и 50% привлеченных клиентов ушли.

Фильтр: Месячные контракты

Вопрос:Могут ли ежемесячные контракты быть причиной оттока?
Ответ: Да!(?)

Теперь мы нашли четкую закономерность. На эту группу приходится 88% оттока. Кроме того, срок владения в месяцах сильно смещен в сторону периода в 1 месяц.

Фильтр: Выход из опроса Обратная связь

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

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

Выводы

Давайте завершим это несколькими выводами.

  • За последние 9 месяцев компания Major Telecom приобрела большое количество новых клиентов, которые быстро ушли. Большинство из них подписывали ежемесячные контракты, использовали более рискованные способы оплаты и отказывались приобретать дополнительную техподдержку.
  • Наплыв клиентов перегрузил службу поддержки клиентов. Эта команда не смогла предоставить людям ожидаемый уровень поддержки, пока они настраивали новые устройства и службы.
  • Конкурирующая телекоммуникационная компания воспользовалась возможностью привлечь новых клиентов с помощью предложений, которые обещали более качественные устройства, скорость Интернета и обслуживание клиентов.

Рекомендации

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

  • Привлекайте новых клиентов медленно и неуклонно, чтобы мы не перегружали команду службы поддержки клиентов. В качестве альтернативы инвестируйте в дополнительные ресурсы для этой команды.
  • Маркетинг Предложения A и B — это отличные истории успеха, которые следует тиражировать.
  • Стимулируйте клиентов подписывать контракты на 1–2 года, используяболеебезопасные способы оплаты, такие как банковский перевод и оплата кредитной картой.

Дополнительное исследование

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

  • Если мы знаем стоимость привлечения нового клиента (CAC), как долго их нужно удерживать, чтобы получить приемлемую прибыль в виде ценности жизненного цикла клиента (CLTV)?
  • Как чрезмерная плата за передачу данных и телефонные звонки влияет на отток клиентов?
  • Каковы географические точки оттока клиентов? Можем ли мы надежно прогнозировать отток в этих областях?
  • Каков верхний порог ежемесячной оплаты, при котором клиент может уйти?
  • Какова идеальная ежемесячная плата для удержания клиента в долгосрочной перспективе?