Это завершающий проект, завершенный в рамках буткемпа по аналитике данных Fullstack Academy. Excel, Python и Tableau использовались для исследовательского анализа данных, прогнозирования машинного обучения и визуализации данных.
Ресурсы
- Набор данных IBM Cognos: отток клиентов телекоммуникационных компаний 11.3.3+
- Ноутбук 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)?
- Как чрезмерная плата за передачу данных и телефонные звонки влияет на отток клиентов?
- Каковы географические точки оттока клиентов? Можем ли мы надежно прогнозировать отток в этих областях?
- Каков верхний порог ежемесячной оплаты, при котором клиент может уйти?
- Какова идеальная ежемесячная плата для удержания клиента в долгосрочной перспективе?