Пробуем алгоритм UMAP урожая 2018 — пакет Python для впечатляющих визуализаций и кластеризации данных. Статья напомнит об этой прекрасной альтернативе t-SNE или PCA и поможет с визуализацией на флагманском курсе Data Science.
Знакомство
Недавно мне посчастливилось познакомиться с UMAP — пакетом Python для потрясающе красивых визуализаций и кластеризации данных высокой размерности. Это было то, что нужно, чтобы вспомнить, почему два года назад я начал изучать науку о данных.
Сегодня мы узнаем, как анализировать многомерные наборы данных, проецируя их в 2D с помощью пакета Uniform Manifold Approximation & Projection (UMAP). Начнём с рекомендаций:
Запускайте UMAP, имея не меньше 16 Гб RAM.
Сократите потребление памяти, приведя каждый столбец к наименьшему подтипу с помощью NumPy.
Не забудьте преобразовать/масштабировать числовые признаки.
Примеры визуализаций:



Что такое UMAP?
UMAP — это алгоритм снижения размерности и мощный инструмент анализа данных. Он похож на PCA (Principal Component Analysis) в смысле скорости и напоминает t-SNE в смысле уменьшения размерности, сохраняя как можно больше информации набора данных.
PCA и t-SNE в сравнении с UMAP имеют два существенных недостатка:
PCA очень быстрый за счёт потери маленьких деталей в данных.
t-SNE крайне медленный, хотя сохраняет базовую структуру данных.
Попробуем UMAP на вкус, сразу начнём со сложного набора данных:
tps = pd.read_csv("data/train.csv").drop("id", axis=1) tps.head().sample(10, axis=1)

>>> tps.shape (957919, 119)
Набор данных Kaggle TPS за сентябрь содержит около 1 000 000 строк и 120 признаков с бинарной целью.
Все признаки численные, и мы довольно беспомощны в смысле надлежащего разведывательного анализа данных. Печать сводной статистики и построение гистограмм по каждому признаку — вот и всё, что мы можем.
Но посмотрим, что может UMAP. Перед его применением сделаем выборку из набора данных, чтобы избежать затрудняющих просмотр данных перекрытий, и заполним недостающие значения. В наборе мы прогнозируем, заявит ли клиент о своей страховке.
from sklearn.impute import SimpleImputer from sklearn.pipeline import make_pipeline # Sample the data - 100k tps_sample = tps.sample(100000) X, y = tps_sample.drop("claim", axis=1), tps_sample[["claim"]].values.flatten() # Preprocess pipe = make_pipeline(SimpleImputer(strategy="mean")) X = pipe.fit_transform(X.copy())
После установки (pip install umap-learn) и импортирования UMAP инициализируем алгоритм многообразия и обучим на X, y при помощи знакомого паттерна Sklearn:
%%time import umap # pip install umap-learn manifold = umap.UMAP().fit(X, y) X_reduced = manifold.transform(X) Wall time: 1min 14s
>>> X_reduced.shape (100000, 2)
По умолчанию UMAP проецирует данные на плоскость. Создадим диаграмму рассеяния, окрашенную в цвета целевых классов:
>>> plt.scatter(X_reduced[:, 0], X_reduced[:, 1], c=y, s=0.5);

На график интересно смотреть, но он не показывает никаких чётких закономерностей: перед установкой UMAP мы не масштабировали признаки. Чтобы группировать похожие точки данных, алгоритм использует метрику расстояния, а значит, признаки численно больше других смещают такие расчёты.
Выберем квантильное преобразование для масштабирования признаков на основе их квантилей и медиан. Такое масштабирование подходит для этого набора: он содержит много признаков с перекосами в данных и бимодальных признаков:
%%time from sklearn.preprocessing import QuantileTransformer # Preprocess again pipe = make_pipeline(SimpleImputer(strategy="mean"), QuantileTransformer()) X = pipe.fit_transform(X.copy()) # Fit UMAP to processed data manifold = umap.UMAP().fit(X, y) X_reduced_2 = manifold.transform(X) Wall time: 34.4 s
# Plot the results plt.scatter(X_reduced_2[:, 0], X_reduced_2[:, 1], c=y, s=0.5);

UMAP прекрасно передал скрытое различие между целевыми классами. Точки вокруг жёлтого пятна — это выбросы. Набор данных не такой уж и сложный, но график ни в коей мере не похож на то, что я вам показал.
Чтобы увидеть структурные закономерности внутри каждого кластера, придётся его перерисовать. Воспользуемся стандартным пакетом визуализации UMAP с большим количеством дополнительных функций. Понадобится и набор данных получше.
Уточняем визуализацию
Проанализируем набор данных конкурса Kaggle TPS за май, где на основе около 75 числовых признаков классифицировано ~200 000 объявлений электронной коммерции:
tps_june = pd.read_csv("data/train_june.csv").sample(15000) X, y = tps_june.drop("target", axis=1), tps_june[["target"]].values.flatten() X.head().sample(10, axis=1)

>>> X.shape (200000, 76) >>> np.unique(y) array(['Class_1', 'Class_2', 'Class_3', 'Class_4', 'Class_5', 'Class_6', 'Class_7', 'Class_8', 'Class_9'], dtype=object)
Снова масштабируем все признаки, теперь с помощью прямого логарифмического преобразования, а также установим UMAP:
import umap from sklearn.preprocessing import PowerTransformer # Scale pipe = make_pipeline(PowerTransformer()) X = pipe.fit_transform(X.copy()) # Encode the target to numeric y_encoded = pd.factorize(y)[0] %%time manifold = umap.UMAP().fit(X, y_encoded) Wall time: 1min 38s
Установим umap.plot:
pip install umap-learn[plot]
После обучения импортируем этот модуль и построим облако точек:
import umap.plot # pip install umap-learn[plot] umap.plot.points(manifold, labels=y, theme="fire");

Вот что мы видим:
Класс 8 доминирует и группируется вокруг центра.
Вокруг класса 8 видим полукруг смешанных точек.
Чётко отличается от остальных класс 6.
Одиночные точки данных можно классифицировать как выбросы.
Замечание по визуализации выше: мы просто передаём обученное многообразие (не преобразованные данные!) в
pointsи указываем метки цветового кодирования.
Чтобы проводить диагностику и лучше понимать структуру многообразия, вы можете построить графы связности в многообразии функцией umap.plot.connectivity. Это потребует много времени, вычислений и памяти.
Графы связности в многообразии


Документация с подробностями по визуализации.
Важнейшие параметры UMAP
UMAP имеет множество параметров, которые могут существенно повлиять на многообразие, а значит, на визуальные эффекты.
Вот самые важные:
n_components # 2 по умолчанию n_neighbors # 15 по умолчанию min_dist # 0,1 по умолчанию metric # euclidean по умолчанию
Как вы уже догадались, n_components управляет количеством измерений проекции.
В наборах с более чем сотней признаков 2D может не сохранить основную топологическую структуру данных, поэтому рекомендую попробовать значения от 2 до 20 с шагом 5 и оценить базовые модели, чтобы увидеть изменения точности.
n_neighbors контролирует область локальной окрестности, которую UMAP при построении многообразия рассматривает для каждого образца данных:
Меньшие значения сужают фокус до локальной структуры, принимая во внимание особенности и мелкие закономерности, но потенциально теряя общую картину.
Большие значения
n_neighborsдают бо́льшую гибкость и позволяют UMAP сосредоточиться на более широком «обзоре» данных в соответствующем измерении. Платить придётся потерей тонких деталей структуры.

Буквальное расстояние между точками данных — min_dist:
Значения меньше 0,1 приводят к более неровным вкраплениям, позволяя быстрее увидеть отдельные кластеры.
Близкие к единице значения дают точкам больше свободы, позволяя увидеть более широкую топологическую структуру.

Параметр metric — это название формулы вычисления расстояния между точками. Выбор широкий и включает manhattan, minkowski и chebyshev.
Лучшие практики работы с UMAP
Первое, на что следует обратить внимание, — это потребление памяти. Особенно много RAM UMAP потребляет в обучении и создании графов, например графов связности. Даже набор данных на 200 000 значений при построении диаграмм потреблял ~18 Гб. Исправлением в документации предлагается установить low_memory в True.
QuantileTransformerрекомендую для сумасшедших распределений — бимодальных, тримодальных и т. д.PowerTransformerлучше всего подходит для перекошенных признаков.
Какой бы преобразователь вы ни выбрали, цель всегда в том, чтобы привести признаки к наиболее нормальному распределению. А разобраться с визуализацией ещё лучше и научиться извлекать из неё пользу вы сможете на наших курсах:
Также вы можете перейти на страницы курсов из каталога, чтобы увидеть, как мы готовим к началу карьеры в других направлениях.

Профессии и курсы
Data Science и Machine Learning
Python, веб-разработка
Мобильная разработка
Java и C#
От основ — в глубину
А также:
