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

如何从scikit-learn MDS计算解释方差?预计算矩阵是否为经典MDS?

好问题!这确实是scikit-learn MDS模块的一个常见困惑点,我来逐一拆解你的问题:

问题1:如何从scikit-learn的MDS计算解释方差

首先明确:scikit-learn的MDS类实现的是SMACOF算法,属于迭代式的非经典度量MDS,它不像经典MDS那样直接基于特征分解输出特征值。所以你提到的那个针对经典MDS的特征值提取方法确实不适用。

不过,我们可以手动近似计算解释方差,核心思路是衡量SMACOF得到的低维嵌入对原始相异矩阵的拟合程度,具体步骤如下:

  1. 用MDS得到低维嵌入后,计算嵌入空间中的重构距离矩阵
  2. 计算原始相异矩阵与重构矩阵的平方误差(对应SMACOF的应力分子)
  3. 用经典MDS中的双重中心化矩阵的迹来代表原始数据的总方差
  4. 解释方差 = 1 - (平方误差 / 总方差)

下面是完整的代码示例:

from sklearn.manifold import MDS
import numpy as np

# 示例:预计算的对称相异矩阵
np.random.seed(42)
D = np.random.rand(15, 15)
D = (D + D.T) / 2  # 确保矩阵对称
np.fill_diagonal(D, 0)  # 对角线元素为0

# 拟合MDS模型
mds = MDS(n_components=2, dissimilarity="precomputed", random_state=42)
embedding = mds.fit_transform(D)

# 步骤1:计算嵌入空间的重构距离矩阵
d_hat = np.sqrt(((embedding[:, np.newaxis] - embedding) ** 2).sum(axis=2))

# 步骤2:计算原始与重构矩阵的平方误差
sse = ((D - d_hat) ** 2).sum()

# 步骤3:计算原始相异矩阵的总方差(基于经典MDS的双重中心化)
D_sq = D ** 2
row_means = D_sq.mean(axis=1, keepdims=True)
col_means = D_sq.mean(axis=0, keepdims=True)
grand_mean = D_sq.mean()
# 双重中心化后的矩阵B
B = -0.5 * (D_sq - row_means - col_means + grand_mean)
# B的迹等于所有特征值之和,即总方差
total_variance = np.trace(B)

# 步骤4:计算解释方差
explained_variance = 1 - (sse / total_variance)
print(f"近似解释方差: {explained_variance:.4f}")

注意:这个值是近似值,因为SMACOF的目标是最小化应力,而不是直接最大化方差解释率,但它能有效衡量嵌入的拟合质量。

问题2:使用预计算相异矩阵时,scikit-learn的MDS是否运行经典MDS?

答案是否定的。无论你使用dissimilarity='precomputed'还是'euclidean',scikit-learn的MDS始终使用SMACOF算法,不会切换到经典MDS的特征分解方法。

经典MDS其实是SMACOF的一个特例:当原始相异矩阵可以被完美嵌入到低维空间(即应力为0)时,SMACOF的迭代结果会和经典MDS一致,但算法本身仍然是通过迭代优化应力函数来求解,而非直接对双重中心化矩阵做特征分解。

如果你确实需要经典MDS的特征值和精确的方差解释率,你可以手动实现经典MDS的特征分解逻辑,或者使用其他工具来完成。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:59:45