Автор статьи: Артем Михайлов

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

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

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

Цель данной статьи – познакомить читателей с процессом анализа данных клиентов и построения модели прогнозирования оттока с использованием языка программирования 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 году и перспективах в будущем. А также о том, как повысить зарплатную вилку на начальном этапе: с какой суммы начинать и к какой сумме стремиться. По итогам вебинара вы сможете понять подходит вам профессия системного аналитика или нет. Регистрируйтесь и приходите, будет интересно.

Комментарии (1)


  1. AVAF
    27.07.2023 17:40
    +2

    Даже не потрудились "Основные статистики о клиентах" от экспоненты очистить.