You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于多维向量矩阵在hyperbolic space中构建distance matrix?

双曲空间中构建距离矩阵的实现指南

没问题!把欧氏空间里构建距离矩阵的操作迁移到双曲空间,核心是先搞清楚双曲空间的距离度量规则,再把你的多维向量适配到双曲空间中,最后批量计算点对距离。下面我一步步给你讲具体实现方法:

一、先选好双曲空间模型

最适合从欧氏空间迁移的是Poincaré球模型(n维),这个模型里所有点都落在n维单位球内部(向量的欧氏范数严格小于1),计算规则直观,容易和你的输入向量适配。

二、把输入向量投影到双曲空间

你的输入是多维向量矩阵,但这些向量大概率不在Poincaré球内部,所以第一步要做投影缩放:

  • 对每个向量,计算它的欧氏范数,然后将其缩放到单位球内,确保范数小于1(加个极小的ε避免刚好落在球面上,因为球面是双曲空间的无穷远点)。

用Python + NumPy实现的投影函数:

import numpy as np

def project_to_poincare_ball(X, eps=1e-8):
    # 计算每个向量的欧氏范数
    vec_norms = np.linalg.norm(X, axis=1, keepdims=True)
    # 处理零向量,避免除以0
    vec_norms[vec_norms == 0] = eps
    # 缩放向量到单位球内
    return X / (vec_norms + eps)

三、实现双曲空间的距离计算

Poincaré球模型中,两个点u和v的双曲距离公式是:

d(u, v) = arccosh(1 + 2 * ||u - v||² / [(1 - ||u||²)(1 - ||v||²)])

注意事项:

  • 当两个点非常接近时,公式里的arg可能因为数值精度略小于1,这时候要把它截断到1.0,否则arccosh会返回NaN。
  • 批量计算距离矩阵时,用广播代替双重循环能大幅提升效率。

距离矩阵的实现(两种方式)

方式1:基础循环版(适合小数据量,易理解)

def hyperbolic_distance(u, v):
    # 计算两点欧氏距离的平方
    delta_sq = np.linalg.norm(u - v, axis=-1)**2
    # 计算每个点的范数平方
    u_norm_sq = np.linalg.norm(u, axis=-1)**2
    v_norm_sq = np.linalg.norm(v, axis=-1)**2
    # 计算分母项
    denominator = (1 - u_norm_sq) * (1 - v_norm_sq)
    # 计算arccosh的输入值
    arg = 1 + 2 * delta_sq / denominator
    # 修正数值精度问题,确保arg >= 1
    arg = np.clip(arg, 1.0, None)
    return np.arccosh(arg)

def build_hyperbolic_dist_matrix(X):
    # 先把输入向量投影到Poincaré球
    X_hyper = project_to_poincare_ball(X)
    n_samples = X_hyper.shape[0]
    dist_matrix = np.zeros((n_samples, n_samples))
    
    # 计算上三角矩阵,再对称填充
    for i in range(n_samples):
        for j in range(i+1, n_samples):
            dist_matrix[i, j] = hyperbolic_distance(X_hyper[i], X_hyper[j])
            dist_matrix[j, i] = dist_matrix[i, j]
    return dist_matrix

方式2:广播优化版(适合大数据量,速度快)

def build_hyperbolic_dist_matrix_fast(X):
    X_hyper = project_to_poincare_ball(X)
    n_samples = X_hyper.shape[0]
    
    # 用广播一次性计算所有点对的欧氏距离平方
    delta_sq = np.sum((X_hyper[:, None, :] - X_hyper[None, :, :])**2, axis=-1)
    # 计算所有点的范数平方,转成适合广播的形状
    u_norm_sq = np.sum(X_hyper**2, axis=1)[:, None]
    v_norm_sq = np.sum(X_hyper**2, axis=1)[None, :]
    
    denominator = (1 - u_norm_sq) * (1 - v_norm_sq)
    arg = 1 + 2 * delta_sq / denominator
    arg = np.clip(arg, 1.0, None)
    
    dist_matrix = np.arccosh(arg)
    # 手动把对角线设为0(避免数值误差导致的微小非零值)
    np.fill_diagonal(dist_matrix, 0.0)
    return dist_matrix

四、额外注意点

  • 数值稳定性:如果你的输入向量范数很大,投影时一定要确保缩放后范数严格小于1,ε的取值建议在1e-8~1e-6之间。
  • 模型替代:如果你需要用其他双曲空间模型(比如Lorentz模型),距离公式会不同,但Poincaré球模型是最适合从欧氏空间迁移的场景。
  • 库支持:如果不想自己实现,可以用专门的几何学习库(比如geomstats),但自己实现核心逻辑能更清楚地理解双曲距离的计算过程。

内容的提问来源于stack exchange,提问作者user40267

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:25:12