Пробуем алгоритм 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#
От основ — в глубину
А также: