Общий обзор:

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

Описание входных данных:

В основе проекта лежит рабочее пространство проекта Sparkify от Udacity, предоставляющее курируемую среду для разработки нашей модели прогнозирования оттока. Набор данных, являющийся подмножеством полного набора данных размером 12 ГБ (128 МБ), содержит данные о событиях в формате JSON, фиксирующие взаимодействие пользователя со службой потоковой передачи музыки Sparkify. Переменные включают атрибуты пользователя, временные метки, информацию о сеансе и события активности.

Стратегия решения проблемы:

Чтобы справиться с огромным объемом данных и обеспечить масштабируемость, мы не будем использовать pandas и scikit Learning для разработки этой модели, вместо этого мы будем использовать Spark и его библиотеку машинного обучения. Выбранный подход включает очистку данных, EDA и разработку функций для преобразования необработанных данных в значимую информацию. Модели — классификатор дерева решений, классификатор случайного леса и классификатор дерева с градиентным усилением — проходят обучение и оценку с использованием показателя F1, что идеально подходит для несбалансированных наборов данных.

Обсуждение ожидаемого решения:

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

Обоснованные показатели:

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

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

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

Приведенные данные показывают, что из общей клиентской базы примерно 16,12% (44 864 из 278 154) ушли, а остальные 83,8% (233 290 из 278 154) не ушли. Это показывает, что набор данных содержит метку оттока дисбаланса.

Затем мы начнем изучать потенциальные возможности прогнозирования оттока клиентов.

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

Предварительная обработка данных:

Предварительная обработка данных включает в себя этот этап.

  1. FilterInvalidUser:
    Удаляет записи со значениями аутентификации «Вышел из системы» или «Гость».
  2. CalculateDate:
    Преобразует метки времени и регистрации в соответствующие форматы.
    Подсчитывает часы и дни с момента регистрации.
  3. GenerateAggregatedFeatures:
    Создает функции скользящего окна: количество сеансов и затраченное время.
  4. get_churn_flag:
    Помечает пользователей как уволенных на основе «Подтверждения отмены».
    Включает метки оттока в основной DataFrame.
class FilterInvalidUser(Transformer):
    ...
    def _transform(self, df: DataFrame) -> DataFrame:
        return df.where(~f.col("auth").isin(["Logged Out","Guest"]))
    ...
    
class CalculateDate(Transformer):
    ...

    def _fit(self, df: DataFrame) -> DataFrame:
        df = (
            df
            .withColumn('activity_timestamp', f.from_unixtime(f.col('ts').cast(LongType())/1000).cast(TimestampType()))
            .withColumn('activity_date', f.from_unixtime(f.col('ts')/1000).cast(DateType()))
            .withColumn('registration_timestamp', f.from_unixtime(f.col('registration').cast(LongType())/1000).cast(TimestampType()))
            .withColumn('registration_date', f.from_unixtime(f.col('ts')/1000).cast(DateType()))
            .withColumn("los_hour",(f.col("activity_timestamp").cast("long") - f.col("registration_timestamp").cast("long"))/(3600))
            .withColumn("los_day",(f.col("activity_timestamp").cast("long") - f.col("registration_timestamp").cast("long"))/(3600*24))
        )
        return df
    ...

class GenerateAggregatedFeatures(Transformer):
    ...
    
    def _fit(self, df: DataFrame) -> DataFrame:
        i = self.aggregate_window_in_days
        days = lambda i: i * 86400
        w = Window.orderBy(f.col("activity_timestamp").cast('long')).rangeBetween(-days(1), 0)
        
        df = (
            df
            .withColumn(f'count_activity_{i}d', f.size(f.collect_set("sessionId").over(w)))
            .withColumn(f'time_spent_{i}d', f.sum("length").over(w))
        )
        return df
    ...
    
def get_churn_flag(df):
    is_churn_label = (
        df
        .withColumn("is_churn",
                    f.when(f.col("page")=='Cancellation Confirmation',f.lit(1))
                    .otherwise(f.lit(0)))
        .groupby("userId")
        .agg(f.max("is_churn").alias("is_churn"))
    )
    ...

Моделирование:

Перед обучением мы разделяем 70% записей активности на обучение, а оставшуюся часть выделяем на тестирование. Мы используем три модели машинного обучения:

  1. Классификатор дерева решений
    Классификатор дерева решений — это широко используемый алгоритм классификации, который работает путем рекурсивного разделения набора данных на подмножества на основе наиболее значимого атрибута в каждом узле.
  2. Классификатор случайного леса
    Классификатор случайного леса — это метод ансамблевого обучения, который объединяет несколько деревьев решений для повышения точности прогнозирования и уменьшения переобучения.
  3. Классификатор дерева с градиентным усилением (GBT)
    Классификатор дерева с градиентным усилением последовательно строит ансамбль деревьев решений, при этом каждое дерево исправляет ошибки своего предшественника.

Настройка гиперпараметров:

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

models_and_params = {
    "GBTClassifier": (GBTClassifier(), ParamGridBuilder()
                      .addGrid(GBTClassifier.maxDepth, [5,10,20])
                      .addGrid(GBTClassifier.maxBins, [5,10,20,30])
                      .build()),
    "RandomForestClassifier": (RandomForestClassifier(), ParamGridBuilder()
                               .addGrid(RandomForestClassifier.maxDepth, [5,10,20])
                               .addGrid(RandomForestClassifier.numTrees, [10,30,50,100])
                               .build()),
    "DecisionTreeClassifier": (DecisionTreeClassifier(), ParamGridBuilder()
                               .addGrid(DecisionTreeClassifier.maxDepth, [5,10,20])
                               .addGrid(DecisionTreeClassifier.maxBins, [5,10,20,30])
                               .build())
}

Затем мы проверяем лучший параметр для каждой модели в тестовом наборе данных.

Результаты:

Оценка модели выполнена на оставшейся 30% выборке (тестовые данные) с использованием наилучшего параметра из предыдущего шага. Результаты показывают, что классификатор деревьев с градиентным усилением является наиболее эффективным и имеет показатель F1 0,794.

Сравнение производительности моделей:

Заключение:

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

  1. Объем данных и масштабируемость
    Проблема: набор данных, предоставленный для этого проекта, является подмножеством гораздо большего набора данных. Работа с полным набором данных создавала проблемы с масштабируемостью, а использование традиционных библиотек обработки данных, таких как pandas и scikit-learn, было невозможным.
    Решение: Чтобы решить эту проблему, мы обратились к PySpark, среде распределенной обработки данных. Возможности параллельной обработки PySpark позволили нам эффективно обрабатывать большой набор данных, распределяя задачи по кластеру компьютеров. Этот выбор не только обеспечил масштабируемость, но и позволил нам использовать всю мощь наших вычислительных ресурсов.
  2. Несбалансированный набор данных
    Проблема: прогнозирование оттока клиентов часто включает в себя несбалансированные наборы данных, где число пользователей, которые отходят, значительно меньше, чем тех, кто этого не делает. Этот дисбаланс может привести к искажению производительности модели.
    Решение: Признавая дисбаланс классов, мы приняли стратегическое решение использовать показатель F1 в качестве основного показателя оценки. В отличие от точности, оценка F1 учитывает как точность, так и полноту, что делает ее хорошо подходящей для несбалансированных наборов данных. Кроме того, мы экспериментировали с различными алгоритмами машинного обучения и настройкой гиперпараметров, чтобы улучшить производительность модели в классе меньшинства. Такой подход гарантировал, что наша модель сможет эффективно выявлять и прогнозировать отток даже при наличии несбалансированных данных.
  3. Разработка функций
    Задача: определение важных функций для прогнозирования оттока клиентов было сложной задачей. Решение о том, какие атрибуты пользователей и события взаимодействия включить в модель, требовало тщательного рассмотрения.
    Решение: мы провели обширный исследовательский анализ данных (EDA), чтобы получить представление о потенциальных индикаторах оттока. Такие характеристики, как пол, уровень пользователя, продолжительность пребывания и деятельность, связанная с песнями, были определены в нашем EDA как решающие факторы. Эти идеи послужили основой для наших усилий по разработке функций.
  4. Выбор алгоритма и настройка параметров
    Задача: выбор правильных алгоритмов машинного обучения и настройка их параметров для достижения оптимальной производительности были нетривиальной задачей.
    Решение: мы экспериментировали с тремя алгоритмами классификации. : классификатор дерева решений, классификатор случайного леса и классификатор дерева с градиентным усилением. Мы задокументировали процесс настройки параметров для каждого алгоритма, чтобы обеспечить прозрачность и воспроизводимость.

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

Улучшения:

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

Подтверждение:

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

Блокнот с более подробной информацией можно найти здесь.

Использованная литература:

*Популярные модели классификации для машинного обучения
*Исследовательские исследования: каковы их методы и примеры?
*Spark Общая документация MLlib
*Документация по дереву Spark Gradient Boosted
*Документация по случайному лесу Spark
* Документация по дереву решений Spark
*Документация по реализации конвейера Spark