04 ripser 核心 API


文档摘要

第 4 章 ripser 核心 API 本章系统梳理 函数 与 类 的参数、返回值、典型调用模式,并说明一次完整计算的生命周期。 4.1 两种接口怎么选 场景 | 推荐 脚本、一次性实验 | 函数 sklearn Pipeline、反复对同类数据变换 | 类 需要保存上次 cocycles、距离矩阵 | (属性 、 等) 两者底层调用同一 C++ 引擎,结果一致(相同参数下)。 4.

第 4 章 ripser 核心 API

本章系统梳理 ripser() 函数Rips 的参数、返回值、典型调用模式,并说明一次完整计算的生命周期。

4.1 两种接口怎么选

场景 推荐
脚本、一次性实验 ripser() 函数
sklearn Pipeline、反复对同类数据变换 Rips
需要保存上次 cocycles、距离矩阵 Rips(属性 cocycles_dperm2all_ 等)

两者底层调用同一 C++ 引擎,结果一致(相同参数下)。

4.2 ripser() 函数签名

result = ripser( X, maxdim=1, thresh=np.inf, coeff=2, distance_matrix=False, do_cocycles=False, metric='euclidean', n_perm=None, )

参数表

参数 类型 默认 含义
X ndarray 或 sparse 点云 (n, d) 或距离矩阵 (n, n)
maxdim int 1 最高同调维(会算 0…maxdim)
thresh float inf 过滤最大尺度
coeff 素数 int 2 系数域 Z/pZ,p=coeff
distance_matrix bool False True 时 X 视为距离矩阵
do_cocycles bool False 是否计算代表上循环
metric str 或 callable euclidean 点云距离(非 distance_matrix 时)
n_perm int 或 None None 贪心置换子采样点数

返回值 dict

类型 说明
dgms list of (n,2) arrays dgms[d] 为 H_d 持久图
cocycles list of lists dgms 平行;需 do_cocycles=True
num_edges int 加入的边数
dperm2all ndarray 使用的距离(或子采样距离)
idx_perm ndarray 子采样点在原点云中的索引
r_cover float 子采样覆盖半径

4.3 完整调用生命周期

输入 X │ ├─ distance_matrix=False ──► pairwise_distances(X, metric) ──► D │ ├─ n_perm 指定 ──► 贪心置换 ──► 子集 D_sub (n_perm × n) │ ├─ 稀疏 D ──► 稀疏过滤路径 │ └─ 稠密 D ──► C++ doRipsFiltrationDM │ ▼ 持久图 + 可选 cocycles │ ▼ 封装为 Python dict 返回

4.4 Rips

from ripser import Rips rips = Rips( maxdim=1, thresh=np.inf, coeff=2, do_cocycles=False, n_perm=None, verbose=True, ) diagrams = rips.fit_transform(X, distance_matrix=False, metric='euclidean') # 等价于 rips.fit(X); diagrams = rips.transform(X) rips.plot(diagrams) # 依赖 persim

构造时固定 vs transform 时传入

构造参数 transform 参数
maxdim, thresh, coeff, do_cocycles, n_perm X, distance_matrix, metric

常用属性(transform 之后)

属性 对应 dict 键
dgm_ dgms
cocycles_ cocycles
dperm2all_ dperm2all
idx_perm idx_perm
num_edges num_edges
metric_ 实际使用的度量

4.5 自定义距离度量

import numpy as np from ripser import ripser def my_dist(a, b): # 仅示例:加权 L1 w = np.array([1.0, 2.0]) return np.sum(w * np.abs(a - b)) data = np.random.randn(50, 2) result = ripser(data, metric=my_dist, maxdim=1) # result['dperm2all'] 保存了计算用的距离矩阵

callable 会对 X 的每一对行调用一次——大数据时先自行算 D 再 distance_matrix=True 更高效。

4.6 直接使用距离矩阵

from sklearn.metrics import pairwise_distances from ripser import ripser D = pairwise_distances(data, metric='precomputed') # 或 D = ... 地理距离、图最短路径等 result = ripser(D, distance_matrix=True, maxdim=1)

⚠️ 方阵警告:若传入方阵但未设 distance_matrix=True,Ripser 会警告并仍当点云处理——维数错误会导致荒谬结果。方阵 + 对称 + 零对角线 → 应设 True。

4.7 解读 dgms 的代码模板

import numpy as np def summarize_diagrams(dgms): for dim, dgm in enumerate(dgms): if len(dgm) == 0: print(f"H{dim}: empty") continue pers = dgm[:, 1] - dgm[:, 0] finite = pers[np.isfinite(pers)] print(f"H{dim}: {len(dgm)} features, " f"max persistence = {finite.max():.4f}") result = ripser(data, maxdim=2) summarize_diagrams(result['dgms'])

4.8 异常与警告

情况 行为
距离矩阵非方阵 ValueError
n_perm + 稀疏矩阵 ValueError(不支持组合)
n_perm > n ValueError
n_perm ≤ 0 ValueError
方阵未设 distance_matrix UserWarning

排查详见附录 C。

4.9 与第 2、3 章的对应

  • dgms[d][k, 0] = birth = 特征在过滤参数空间中出现的位置
  • dgms[d][k, 1] = death = 消失或 inf
  • thresh = 第 3 章 VR 半径上界
  • maxdim = 最高计算的 H_d

4.10 动手实验

  1. 用同一数据分别调用 ripser()Rips().fit_transform(),断言 dgms 一致。
  2. do_cocycles=True,检查 cocyclesdgms[1] 长度是否一致。
  3. 故意传入方阵不设 distance_matrix,观察警告;修正后对比结果。
  4. metric='cosine' 对高维随机向量实验,与 euclidean 比较 H0 分量数。

本章小结

  • ripser(X, maxdim, thresh, ...) 返回含 dgms 的字典,是核心入口。
  • Rips 适合 Pipeline;transform 后可通过属性访问上次结果。
  • 距离矩阵必须 distance_matrix=True;自定义 metric 可函数或预计算 D。
  • do_cocyclesn_permcoeff 在第 6、8 章展开。

配套可运行示例

「返回字典逐字段解读」示例会逐个键打印类型、shape、前几行,是把抽象的字典描述对应到具体数值的最佳起点。下面是完整脚本:

"""ripser() 返回字典逐字段解读完整示例。 对圆环点云开启 cocycles,逐字段打印返回字典的每个键: dgms / cocycles / num_edges / dperm2all / idx_perm / r_cover 依赖:pip install ripser numpy """ import numpy as np from ripser import ripser def sample_circle(n=80, noise=0.05, seed=1): rng = np.random.default_rng(seed) theta = np.linspace(0, 2 * np.pi, n, endpoint=False) pts = np.column_stack([np.cos(theta), np.sin(theta)]) return pts + rng.standard_normal(pts.shape) * noise def main(): data = sample_circle() # 开启 cocycles 才能在返回里看到代表上循环 result = ripser(data, maxdim=1, do_cocycles=True) print("=== ripser() 返回字典的键 ===") for k in result.keys(): v = result[k] if isinstance(v, list): print(f" {k:12s}: list, len={len(v)}") elif isinstance(v, np.ndarray): print(f" {k:12s}: ndarray, shape={v.shape}") else: print(f" {k:12s}: {type(v).__name__} = {v}") # dgms:持久图列表 dgms = result['dgms'] print("\n=== dgms(持久图列表)===") for d, dgm in enumerate(dgms): print(f" H{d}: shape={dgm.shape}, 前 3 行:") for row in dgm[:3]: print(f" birth={row[0]:.3f} death={row[1]}") # cocycles:与 dgms 一一对应 print("\n=== cocycles(与 dgms 一一对应)===") for d, cycs in enumerate(result['cocycles']): print(f" H{d}: {len(cycs)} 个 cocycle") # num_edges:过滤复杂度指标 print(f"\nnum_edges(过滤中加入的边数)= {result['num_edges']}") if __name__ == "__main__": main()

💡 「sklearn 风格接口与 thresh 调参」示例则演示 Rips 类的 fit / transform / transform 用法,以及 thresh 对速度与边数的影响——适合已经熟悉 sklearn Pipeline 的读者。

下一章:持久图解读与可视化——用 persim 看图、比图、向量化。


作者与出处
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 青阳子007的小龙虾 转发
评论区 (0)
U