第 5 章 持久图解读与可视化 算出 只是开始。本章教你 如何读图、如何用 persim 可视化、如何用瓶颈距离比较两次实验,并介绍将持久图转为机器学习特征的常见思路。 5.1 持久图的几何解读 坐标轴 横轴 birth:特征出现的过滤尺度(VR 下≈边长/半径) 纵轴 death:特征消失的尺度;对角线 birth = death → 零持久性 显著性启发式 位置 | 含义 远离对角线 | 持久性大,更可能是真实拓扑结构 靠近对角线 | 常为噪声或短暂特征 death = inf | 过滤结束前未消失——可能是真结构,也可能是 截断 5.
算出
dgms只是开始。本章教你 如何读图、如何用 persim 可视化、如何用瓶颈距离比较两次实验,并介绍将持久图转为机器学习特征的常见思路。
| 位置 | 含义 |
|---|---|
| 远离对角线 | 持久性大,更可能是真实拓扑结构 |
| 靠近对角线 | 常为噪声或短暂特征 |
| death = inf | 过滤结束前未消失——可能是真结构,也可能是 thresh 截断 |
import numpy as np def top_features(dgm, k=5): pers = dgm[:, 1] - dgm[:, 0] mask = np.isfinite(pers) idx = np.argsort(pers[mask])[-k:] return dgm[mask][idx], pers[mask][idx] dgm1 = result['dgms'][1] top, pers = top_features(dgm1, k=3) for row, p in zip(top, pers): print(f"birth={row[0]:.3f} death={row[1]:.3f} pers={p:.3f}")
from persim import plot_diagrams # 多维同一张图,不同颜色 plot_diagrams( result['dgms'], labels=['H0', 'H1'], show=True, )
Rips 类封装:
rips = Rips(maxdim=1) dgms = rips.fit_transform(data) rips.plot(dgms)
from persim import plot_bars plot_bars(result['dgms'][1], show=True)
条形码与持久图一一对应:每条水平线段 [birth, death]。
瓶颈距离(Bottleneck Distance) 是两持久图之间 W∞ 最优匹配的匹配距离,是持久同调稳定性定理中的自然度量。
from persim import bottleneck dgm_a = ripser(data_a, maxdim=1)['dgms'][1] dgm_b = ripser(data_b, maxdim=1)['dgms'][1] # 需去掉 inf death 或 persim 内部处理 dist, matching = bottleneck(dgm_a, dgm_b) print("bottleneck H1:", dist)
用途:
n_perm 子采样是否改变形状摘要💡 稳定性定理(直观):点云微小扰动(Hausdorff 意义下)导致持久图瓶颈距离有界——这是 TDA 抗噪声的理论依据。
持久图是可变长度的点集,进机器学习需向量化。常见方法:
| 方法 | 思路 |
|---|---|
| 持久图像(Persistence Image) | 对持久图核平滑后栅格化 |
| 持久景观(Persistence Landscape) | 分段线性函数序列 |
| Betti 曲线 | 固定 t 处 Betti 数随 t 变化 |
| 统计摘要 | 各维 max/mean persistence、点数 |
persim 提供 PersistenceImager 等工具;giotto-tda 提供 Pipeline 封装。
# 概念示例:手工统计特征 def persistence_stats(dgms): feats = [] for d, dgm in enumerate(dgms): p = dgm[:, 1] - dgm[:, 0] p = p[np.isfinite(p)] feats.append(p.max() if len(p) else 0) feats.append(p.mean() if len(p) else 0) return np.array(feats)
详见第 10 章 ML 集成。
| 陷阱 | 说明 |
|---|---|
| 只画 H1 | H0 合并模式也含信息(聚类结构) |
| 忽略尺度 | birth/death 绝对值依赖点云单位;比较前应归一化 |
| inf 点 | 绘图库可能截断;分析时需单独处理 |
| 过拟合解读 | 单个高持久点不一定是业务「信号」 |
⚠️ 多实验比较:应用相同
thresh、maxdim、coeff,否则瓶颈距离混合了参数效应与数据效应。
import numpy as np from ripser import ripser from persim import plot_diagrams, bottleneck # 圆环 theta = np.linspace(0, 2*np.pi, 100, endpoint=False) circle = np.column_stack([np.cos(theta), np.sin(theta)]) circle += 0.05 * np.random.randn(*circle.shape) # 随机 random = np.random.rand(100, 2) dgms_c = ripser(circle, maxdim=1)['dgms'] dgms_r = ripser(random, maxdim=1)['dgms'] # H1 瓶颈距离应较大 d, _ = bottleneck(dgms_c[1], dgms_r[1]) print("circle vs random H1 bottleneck:", d)
bottleneck 比较同一圆环两次独立采样的 H1——距离应较小。persistence_stats,对 10 个圆环 vs 10 个随机集提取特征,用简单分类器区分(预告 ML 管线)。plot_diagrams、plot_bars、bottleneck。下一章:距离矩阵、稀疏过滤与贪心置换——大规模数据的加速之道。