
经典多维尺度变换(cmds),又称主坐标分析(principal coordinate analysis, pcoa),是一种常用的降维技术,旨在将高维数据点映射到低维空间,同时尽可能保留原始数据点之间的距离关系。其核心思想是通过对距离矩阵进行双重中心化,然后进行特征分解,从而找到数据在低维空间中的最优表示。cmds广泛应用于数据可视化、模式识别和机器学习等领域。
CMDS算法的基本步骤如下:
在某些应用场景中,特别是当数据点表示图中的节点,而距离表示它们之间的路径长度时,两个不连通的节点之间的距离通常会被标记为无穷大(inf)。这在图论中是一个完全有效的概念,但在CMDS的数值计算中,无穷大值会导致严重问题。
原始CMDS算法在计算双重中心化平方距离矩阵$B$时,涉及$D^2$的操作。如果$D$中包含inf,那么$D^2$中的对应元素将变为inf,进而导致矩阵乘法H @ D**2 @ H的结果中包含inf或NaN(Not a Number)。随后的特征分解np.linalg.eigh(B)将无法处理这些非有限值,从而引发运行时错误。
为了使CMDS算法能够鲁棒地处理包含不连通点(即距离为inf)的场景,我们需要在计算$B$之前对距离矩阵进行预处理。
最直接且有效的方法是识别距离矩阵中的所有无穷大值,并将其替换为一个巨大的、但有限的数值。这个替换值应该足够大,以反映不连通点之间“无限远”的语义,但又不能真正是inf,以避免数值计算错误。Python的numpy库提供了np.finfo(D.dtype).max,它能返回给定数据类型所能表示的最大有限浮点数,这通常是一个理想的替换值。
实现步骤:
通过这种方式,我们既保留了不连通点距离“非常大”的语义,又避免了数值计算的崩溃。
以下是修改后的CMDS函数,它集成了处理无穷大距离值的功能:
import numpy as np
from sklearn.metrics.pairwise import euclidean_distances
def cmds(X, n_dim, input_type='raw'):
"""
Classical(linear) multidimensional scaling (MDS)
Parameters
----------
X: (d, n) array or (n,n) array
input data. The data are placed in column-major order.
That is, samples are placed in the matrix (X) as column vectors
d: dimension of points
n: number of points
n_dim: dimension of target space
input_type: it indicates whether data are raw or distance
- raw: raw data. (n,d) array.
- distance: precomputed distances between the data. (n,n) array.
Returns
-------
Y: (n_dim, n) array. projected embeddings.
evals: (n_dim) eigen values
evecs: corresponding eigen vectors in column vectors
"""
if input_type == 'distance':
D = X
elif input_type == 'raw':
# Transpose X to (n, d) for euclidean_distances
Xt = X.T
D = euclidean_distances(Xt, Xt)
else:
raise ValueError("input_type must be 'raw' or 'distance'")
# 检查距离矩阵中是否存在无穷大值,并进行替换
if np.any(np.isinf(D)):
# 将inf值替换为该数据类型所能表示的最大有限浮点数
# 这样做可以避免在后续计算中因inf值导致错误,同时保留其“非常远”的语义
D[np.isinf(D)] = np.finfo(D.dtype).max
# Centering matrix
n = D.shape[0]
H = np.eye(n) - np.ones((n, n)) / n
# Double-center the distance matrix
# 注意:这里D**2是元素级的平方操作
B = -0.5 * H @ (D**2) @ H
# Eigen decomposition
evals, evecs = np.linalg.eigh(B)
# Sorting eigenvalues and eigenvectors in decreasing order
sort_indices = np.argsort(evals)[::-1]
evals = evals[sort_indices]
evecs = evecs[:, sort_indices]
# Selecting top n_dim eigenvectors
evecs_selected = evecs[:, :n_dim]
# Projecting data to the new space
# 确保特征值非负,因为它们理论上应代表方差
# 实际应用中,由于数值精度或非欧氏距离,可能出现微小负特征值,
# 但对于CMDS,通常只考虑正特征值。这里假设前n_dim特征值是有效的。
valid_evals = np.maximum(0, evals[:n_dim]) # 避免负数开方
Y = np.sqrt(np.diag(valid_evals)) @ evecs_selected.T
return Y, evals, evecs
通过在CMDS算法中引入对距离矩阵中无穷大值的检测和替换机制,我们显著提升了算法的鲁棒性。这种方法使得CMDS能够有效处理包含不连通关系的数据集,从而扩展了其在复杂网络和图结构数据分析中的应用范围。在实际应用中,理解并妥善处理数据中的特殊值(如inf或NaN)是构建稳定、可靠数据分析流程的关键一环。
以上就是增强经典多维尺度变换(CMDS)对无穷大距离矩阵的处理能力的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号