Пробуем алгоритм 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 имеют два существенных недостатка:

  1. PCA очень быстрый за счёт потери маленьких деталей в данных.

  2. t-SNE крайне медленный, хотя сохраняет базовую структуру данных.

Попробуем UMAP на вкус, сразу начнём со сложного набора данных:

tps = pd.read_csv("data/train.csv").drop("id", axis=1)
tps.head().sample(10, axis=1)
Синтетические данные, созданные для сентябрьского конкурса Kaggle TPS.
Синтетические данные, созданные для сентябрьского конкурса Kaggle TPS.
>>> 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)
Синтетические данные Kaggle TPS за сентябрь
Синтетические данные Kaggle TPS за сентябрь
>>> 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 сосредоточиться на более широком «обзоре» данных в соответствующем измерении. Платить придётся потерей тонких деталей структуры.

Обучение UMAP с различными n_neighbors на выборке данных TPS за июнь
Обучение UMAP с различными n_neighbors на выборке данных TPS за июнь

Буквальное расстояние между точками данных — min_dist:

  • Значения меньше 0,1 приводят к более неровным вкраплениям, позволяя быстрее увидеть отдельные кластеры.

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

Обучение многообразия UMAP с различными min_dist на выборке данных TPS за июнь
Обучение многообразия UMAP с различными min_dist на выборке данных TPS за июнь

Параметр metric — это название формулы вычисления расстояния между точками. Выбор широкий и включает manhattan, minkowski и chebyshev.

Лучшие практики работы с UMAP

Первое, на что следует обратить внимание, — это потребление памяти. Особенно много RAM UMAP потребляет в обучении и создании графов, например графов связности. Даже набор данных на 200 000 значений при построении диаграмм потреблял ~18 Гб. Исправлением в документации предлагается установить low_memory в True.

  • QuantileTransformer рекомендую для сумасшедших распределений — бимодальных, тримодальных и т. д.

  • PowerTransformer лучше всего подходит для перекошенных признаков.

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

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

Профессии и курсы

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