【TDA】mapper
https://giotto-ai.github.io/gtda-docs/latest/notebooks/tmp/mapper_quickstart.html?highlight=mapper
https://giotto-ai.github.io/gtda-docs/latest/modules/mapper.html?highlight=mapper
https://www.quantmetry.com/blog/topological-data-analysis-with-mapper/
https://research.math.osu.edu/tgda/mapperPBG.pdf 由这篇文章提出
给定一个点的数据集,Mapper 背后的基本步骤如下:
- 使用滤波函数 f 或透镜将其映射到低维空间。常见的滤波函数选择包括通过 PCA 或基于密度的方法投影到一个或多个轴上。
- 构建投影空间的覆盖 ( U i ) i ∈ I (U_i)_{i\in I} (Ui)i∈I,通常采用具有恒定长度的重叠区间集的形式。
- 对于每个区间 U i U_i Ui,在原像 f − 1 ( U i ) f^{-1}(U_i) f−1(Ui) 中对点进行聚类,形成集合 C i , 1 , … , C i , k i C_{i,1},\ldots,C_{i,k_i} Ci,1,…,Ci,ki。
- 构建一个图,其顶点是聚类集合,如果两个聚类有一些共同的点,则两个顶点之间存在一条边。
数据由二维黑色点表示(在左侧),这里的滤波函数简单地是一个高度函数(投影到 y 轴上),四个区间组成了投影空间的覆盖;在拉回这些区间后,即取滤波函数的原像(即左边的图的点),我们以最近邻的方式对每个原像进行聚类。生成的 Mapper 图在右侧描绘。
透镜(lens), 覆盖(cover)和聚类算法 都可以灵活的进行选择。
-
透镜(lens)的选择非常重要,因为输出图将明显依赖于这个选择。根据您正在分析的数据集类型,可以应用最有意义的透镜。例如,对于异常值检测,应用一个lens,将其投影到与 L2 范数或第一个 PCA 组件相结合的isolation forest score是有意义的。
- 在一维情况下,可以选择一些高度函数(如上图所示)、偏心率或中心性。
- 在更多维度的情况下,典型的选择是标准的降维算法,如 PCA、Isomap、MDS、t-SNE 或 UMAP。在生物应用中,通常使用基于密度的方法,例如距离第一个 k 近邻的距离。通过投影到变分自编码器产生的某个潜在空间,可以实现更微妙的结果。
-
覆盖,一个标准选择是一组 d 维区间(即 d 个一维区间的笛卡尔积),这些区间具有相同的长度,并且以指定的百分比成对重叠。这是另一个关键参数,因为重叠将决定 Mapper 图中的边的创建。
-
聚类技术。DBSCAN或层次聚类。全局选择聚类数量作为超参数可能很棘手:聚类应用于由覆盖元素的拉回产生的每组点,因此可能有不同的聚类数量需要选择。一种解决方案是根据规则停止凝聚聚类,例如,在树状图中发现足够大的间隙的第一个实例。
# Data wrangling
import numpy as np
import pandas as pd # Not a requirement of giotto-tda, but is compatible with the gtda.mapper module
# Data viz
from gtda.plotting import plot_point_cloud
# TDA magic
from gtda.mapper import (
CubicalCover,
make_mapper_pipeline,
Projection,
plot_static_mapper_graph,
plot_interactive_mapper_graph
)
# ML tools
from sklearn import datasets
from sklearn.cluster import DBSCAN
from sklearn.decomposition import PCA
data, _ = datasets.make_circles(n_samples=5000, noise=0.05, factor=0.3, random_state=42)
plot_point_cloud(data)
# Define filter function – can be any scikit-learn transformer
filter_func = Projection(columns=[0, 1])
# Define cover
cover = CubicalCover(n_intervals=10, overlap_frac=0.3)
# Choose clustering algorithm – default is DBSCAN
clusterer = DBSCAN()
# Configure parallelism of clustering step
n_jobs = 1
# Initialise pipeline
pipe = make_mapper_pipeline(
filter_func=filter_func,
cover=cover,
clusterer=clusterer,
verbose=False,
n_jobs=n_jobs,
)
fig = plot_static_mapper_graph(pipe, data)
fig.show(config={'scrollZoom': True})