Автор статьи: Артем Михайлов
В современном мире, где конкуренция между компаниями становится все более жесткой, понимание поведения клиентов и их удержание становятся ключевыми факторами для успешного бизнеса. Одним из важных инструментов в достижении этой цели является анализ данных клиентов и прогнозирование оттока пользователей.
Анализ данных клиентов – это процесс извлечения, очистки, исследования и визуализации данных о клиентах компании с целью выявления интересных закономерностей и паттернов в их поведении. Такой анализ позволяет компаниям понять, что делает их клиентов довольными, что их раздражает и, самое главное, предсказать вероятность того, что клиент может уйти к конкуренту, что называется оттоком пользователей.
Прогнозирование оттока – это процесс разработки моделей машинного обучения, которые позволяют предсказать, сколько и какие клиенты вероятно покинут компанию в определенный период времени. Предупреждение о возможном оттоке дает компаниям возможность принять меры по удержанию клиентов, что может существенно снизить потери и повысить общую прибыль.
Цель данной статьи – познакомить читателей с процессом анализа данных клиентов и построения модели прогнозирования оттока с использованием языка программирования Python. Мы рассмотрим ключевые этапы работы с данными, включая подготовку, исследовательский анализ, построение моделей машинного обучения и интерпретацию результатов.
Подготовка данных
Подготовим наши данные.
# A. Загрузка данных клиентов
data = {
'CustomerID': [1, 2, 3, 4, 5],
'Age': [32, 45, 29, 56, 38],
'Gender': ['Male', 'Female', 'Female', 'Male', 'Male'],
'TotalSpend': [1000, 1500, 500, 2000, 800],
'NumOfPurchases': [5, 3, 7, 2, 4],
'Churn': [0, 1, 0, 1, 0] # 0 - остается, 1 - ушел
}
# B. Импорт необходимых библиотек
import pandas as pd
from sklearn.preprocessing import LabelEncoder, StandardScaler
# Преобразуем данные в DataFrame
df = pd.DataFrame(data)
# C. Очистка данных: обработка пропущенных значений и дубликатов
# Проверим наличие пропущенных значений
print("Количество пропущенных значений:")
print(df.isnull().sum())
# В данном примере предположим, что у нас нет пропущенных значений, поэтому нет необходимости в дополнительной обработке.
# Однако, если бы в данных были пропуски, то мы могли бы обработать их с помощью метода fillna() для заполнения пропусков
# определенными значениями, либо удалить строки с пропущенными значениями с помощью dropna().
# Проверим и удалим дубликаты, если они есть
df.drop_duplicates(inplace=True)
# D. Преобразование данных: кодирование категориальных признаков и масштабирование числовых признаков
# Кодируем категориальный признак "Gender" в числовой формат, чтобы модель машинного обучения могла работать с ним.
le = LabelEncoder()
df['Gender'] = le.fit_transform(df['Gender'])
# Масштабируем числовые признаки для их нормализации и уменьшения влияния различных единиц измерения.
# В данном примере мы используем StandardScaler для приведения признаков к стандартному нормальному распределению
# со средним значением 0 и стандартным отклонением 1.
scaler = StandardScaler()
df[['Age', 'TotalSpend', 'NumOfPurchases']] = scaler.fit_transform(df[['Age', 'TotalSpend', 'NumOfPurchases']])
# Выведем окончательный результат
print("\nПодготовленные данные:")
print(df)
В данном примере мы предположили, что данные не содержат пропущенных значений. Однако, в реальных данных может быть необходимость в более сложной обработке пропусков. Также, при работе с реальными данными, предполагается, что данные загружаются из файлов, баз данных или других источников, и их обработка может потребовать дополнительных этапов, которые не были учтены в данном примере. Важно всегда проверять и анализировать данные для выбора оптимального подхода к их обработке и подготовке перед построением моделей машинного обучения.
Исследовательский анализ данных
Основные статистики о клиентах
Для начала, давайте рассмотрим основные статистики о клиентах, чтобы получить общее представление о нашем наборе данных.
# Посмотрим на первые несколько строк данных
print("Первые 5 строк данных:")
print(df.head())
# Получим основные статистические показатели о клиентах
print("\nОсновные статистики о клиентах:")
print(df.describe())
Получаем следующее(на картинке):
Данные о клиентах выглядят нормализованными, так как средние значения близки к 0, а стандартные отклонения приближаются к 1. Представленные статистические показатели помогают нам лучше понять характеристики клиентов и их распределения в наборе данных.
Визуализация данных для лучшего понимания распределений
Для визуализации данных и получения более глубокого понимания распределения признаков, давайте построим графики и диаграммы.
import matplotlib.pyplot as plt
import seaborn as sns
# Построим гистограмму возраста клиентов
plt.figure(figsize=(8, 5))
sns.histplot(df['Age'], bins=10, kde=True, color='skyblue')
plt.xlabel('Возраст')
plt.ylabel('Частота')
plt.title('Распределение возраста клиентов')
plt.show()
# Построим гистограмму общего объема расходов
plt.figure(figsize=(8, 5))
sns.histplot(df['TotalSpend'], bins=10, kde=True, color='salmon')
plt.xlabel('Общий объем расходов')
plt.ylabel('Частота')
plt.title('Распределение общего объема расходов клиентов')
plt.show()
# Построим гистограмму количества покупок
plt.figure(figsize=(8, 5))
sns.histplot(df['NumOfPurchases'], bins=10, kde=True, color='orange')
plt.xlabel('Количество покупок')
plt.ylabel('Частота')
plt.title('Распределение количества покупок клиентов')
plt.show()
# Построим диаграмму рассеяния для визуализации связи между признаками Age и TotalSpend
plt.figure(figsize=(8, 5))
sns.scatterplot(x='Age', y='TotalSpend', data=df, hue='Churn', palette='viridis', s=100)
plt.xlabel('Возраст')
plt.ylabel('Общий объем расходов')
plt.title('Диаграмма рассеяния: Возраст vs. Общий объем расходов')
plt.legend(title='Churn', labels=['Остается', 'Ушел'])
plt.show()
Мы получаем следующие результаты:
В итоге получили визуализации, которые помогают нам лучше понять распределение признаков. Гистограммы позволяют нам увидеть, какие значения признаков чаще всего встречаются, а диаграмма рассеяния показывает возможные связи между признаками «Возраст» и «Общий объем расходов», а также как фактор оттока (Churn) может влиять на эти связи.
Исследование корреляции между признаками
Корреляция между признаками позволяет нам определить, какие признаки сильно связаны друг с другом, что помогает в идентификации важных факторов.
# Построим матрицу корреляции между признаками
correlation_matrix = df.corr()
# Визуализируем матрицу корреляции с помощью тепловой карты
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f', linewidths=0.5)
plt.title('Матрица корреляции')
plt.show()
Результат:
Матрица корреляции позволяет нам оценить силу и направление связи между признаками. Самая яркая точка на диагонали (значение 1) представляет собой корреляцию признака с самим собой (что логично, так как корреляция признака с самим собой всегда равна 1). Важным для анализа является взаимосвязь между оттоком (Churn) и другими признаками. Значения корреляции близкие к 1 или -1 указывают на сильную связь, в то время как значения близкие к 0 указывают на отсутствие линейной зависимости.
Построение модели прогнозирования оттока
Выбор алгоритма машинного обучения
Для прогнозирования оттока клиентов, мы выберем три алгоритма машинного обучения: логистическую регрессию, случайный лес и градиентный бустинг. Эти алгоритмы широко используются для задач классификации, таких как прогнозирование оттока, и позволяют получить хорошие результаты при правильной настройке гиперпараметров.
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
# Инициализируем модели
logreg_model = LogisticRegression(random_state=42)
rf_model = RandomForestClassifier(random_state=42)
gb_model = GradientBoostingClassifier(random_state=42)
# Обучение моделей будет произведено в следующей части, когда данные разделены на обучающую и тестовую выборки.
Разделение данных на обучающую и тестовую выборки
Перед обучением модели необходимо разделить данные на обучающую и тестовую выборки. Обучающая выборка будет использоваться для обучения модели, а тестовая выборка для оценки ее производительности.
from sklearn.model_selection import train_test_split
# Разделяем данные на обучающую (80%) и тестовую (20%) выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
Обучение модели на обучающей выборке
Теперь обучим выбранные модели на обучающей выборке.
# Обучение моделей на обучающей выборке
logreg_model.fit(X_train, y_train)
rf_model.fit(X_train, y_train)
gb_model.fit(X_train, y_train)
Оценка производительности модели на тестовой выборке
После обучения моделей на обучающей выборке, необходимо оценить их производительность на тестовой выборке.
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
# Функция для оценки производительности модели
def evaluate_model(model, X_test, y_test):
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
roc_auc = roc_auc_score(y_test, y_pred)
return accuracy, precision, recall, f1, roc_auc
# Оценка производительности моделей
logreg_accuracy, logreg_precision, logreg_recall, logreg_f1, logreg_roc_auc = evaluate_model(logreg_model, X_test, y_test)
rf_accuracy, rf_precision, rf_recall, rf_f1, rf_roc_auc = evaluate_model(rf_model, X_test, y_test)
gb_accuracy, gb_precision, gb_recall, gb_f1, gb_roc_auc = evaluate_model(gb_model, X_test, y_test)
# Вывод результатов
print("Результаты оценки производительности моделей на тестовой выборке:")
print("Логистическая регрессия:")
print(f"Точность: {logreg_accuracy:.4f}, Полнота: {logreg_recall:.4f}, F1-мера: {logreg_f1:.4f}, ROC-AUC: {logreg_roc_auc:.4f}")
print("Случайный лес:")
print(f"Точность: {rf_accuracy:.4f}, Полнота: {rf_recall:.4f}, F1-мера: {rf_f1:.4f}, ROC-AUC: {rf_roc_auc:.4f}")
print("Градиентный бустинг:")
print(f"Точность: {gb_accuracy:.4f}, Полнота: {gb_recall:.4f}, F1-мера: {gb_f1:.4f}, ROC-AUC: {gb_roc_auc:.4f}")
Мы обучили три различные модели машинного обучения (логистическую регрессию, случайный лес и градиентный бустинг) на обучающей выборке и оценили их производительность на тестовой выборке. Результаты оценки включают значения точности, полноты, F1-меры и ROC-AUC для каждой модели. При оценке производительности моделей, мы можем определить, какая модель лучше всего справляется с задачей прогнозирования оттока пользователей.
Заключение
Анализ данных клиентов и прогнозирование оттока играют важную роль для компаний, позволяя предпринимать меры по удержанию клиентов и оптимизации бизнес-процессов. Результаты данного исследования помогут компании лучше понять своих клиентов, выделить ключевые факторы, влияющие на отток.
Кстати, о том, чем занимается системный аналитик и о профессии в целом мои друзья из OTUS расскажут на бесплатном вебинаре. Вы узнаете о востребованности профессии в 2023 году и перспективах в будущем. А также о том, как повысить зарплатную вилку на начальном этапе: с какой суммы начинать и к какой сумме стремиться. По итогам вебинара вы сможете понять подходит вам профессия системного аналитика или нет. Регистрируйтесь и приходите, будет интересно.