Сегменты клиентов меняются после обучения: как сравнить две кластеризации

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

Алгоритм группировки выдаёт обозначения, которые сами по себе не имеют бизнес-смысла. Кластер 0 одного запуска может соответствовать кластеру 2 другого. Простое сравнение old_label != new_label считает переименование настоящим переходом. Для корректного отчёта сначала надо сопоставить группы по составу.

Кого сравнивать между запусками

Возьмите одинаковый набор клиентов, существующих в обеих версиях. Сохраните их идентификаторы и полученные метки. Новых и исчезнувших клиентов посчитайте отдельно: их нельзя объявлять перешедшими из старого сегмента в новый. Если версии используют разные периоды активности, сначала объясните, как это меняет состав сравниваемой аудитории.

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

Посчитаем наилучшее соответствие групп

Строим матрицу: строки — старые кластеры, столбцы — новые, ячейка — число общих клиентов. Затем ищем взаимно однозначное сопоставление, сохраняющее максимум клиентов на диагонали. При одинаковом числе групп это задача назначения. Для неё используем настоящий вызов scipy.optimize.linear_sum_assignment с maximize=True.

import numpy as np
from scipy.optimize import linear_sum_assignment
old = np.array([0,0,0,1,1,1,2,2,2])
new = np.array([2,2,2,0,0,1,1,1,1])
old_ids, oi = np.unique(old, return_inverse=True)
new_ids, ni = np.unique(new, return_inverse=True)
matrix = np.zeros((len(old_ids), len(new_ids)), dtype=int)
np.add.at(matrix, (oi, ni), 1)
rows, cols = linear_sum_assignment(matrix, maximize=True)
mapping = {new_ids[c]: old_ids[r] for r, c in zip(rows, cols)}
aligned = np.array([mapping[v] for v in new])
print('overlap_matrix', matrix.tolist())
print('new_to_old', {int(k):int(v) for k,v in mapping.items()})
print('raw_changed', int((old != new).sum()))
print('aligned_changed', int((old != aligned).sum()))
print('moved_client_positions', np.flatnonzero(old != aligned).tolist())
assert (old != new).sum() == 8
assert (old != aligned).sum() == 1

По сырым номерам изменились восемь меток из девяти. После сопоставления остаётся один реальный переход: клиент на позиции 5. Новый кластер 2 соответствует старому 0, новый 0 — старому 1, новый 1 — старому 2. Теперь отчёт позволяет изучить конкретный переход вместо бессмысленного сигнала о почти полной перестройке аудитории.

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

Если кластер разделился или исчез

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

При разном числе кластеров SciPy поддерживает прямоугольную матрицу назначения, но часть групп останется без пары. Отметьте их как новые или несопоставленные. Не присваивайте им старое бизнес-название только ради непрерывности отчёта. Если сегментация изменилась принципиально, потребуется повторная договорённость с владельцами кампаний.

Для сравнения структуры независимо от названий можно дополнительно использовать Adjusted Rand Index. Такая метрика смотрит на совместное попадание пар клиентов в группы и учитывает случайное совпадение. Она полезна в исследовании устойчивости, а таблица переходов остаётся необходимой для объяснения конкретных бизнес-изменений.

От стабильности к рабочей сегментации

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

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

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

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

Платный курс «ML Engineer / Data Scientist: табличные модели в продакшн» даёт практику подготовки признаков, воспроизводимых экспериментов, интерпретации и сборки inference pipeline. Эти навыки нужны, чтобы отделять изменение данных от изменения модели и сохранять результат для следующего запуска. Посмотрите программу курса и выберите следующий этап работы с табличным проектом.

Продолжить на практике

  • ML Engineer / Data Scientist: табличные модели в продакшн ↗

    Практический курс для тех, кто хочет получить навыки ML Engineer / Data Scientist на реальных табличных задачах. В курсе Вы не просто обучите CatBoost/LightGBM, а соберёте полноценный production-style пайплайн: подготовка данных, feature engineering (генерация признаков), корректная валидация, защита от leakage (утечек), тюнинг через Optuna, интерпретация через SHAP, batch-инференс и REST API для предсказаний.