保留全维度时PCA为何影响余弦相似度及排序?
问题:保留全维度PCA后,余弦相似度为何出现异常变化?
执行代码
from sklearn.decomposition import PCA import numpy as np from sklearn.metrics.pairwise import cosine_similarity def do_pca(X, n_components): print(f"Doing PCA from {X.shape[0]} vectors") pca = PCA(n_components=n_components) X_pca = pca.fit_transform(X) print('Explained variance:', sum(pca.explained_variance_ratio_[:n_components])) return pca def by_relevance(vectors, key_vector): rankings = [ (i, cosine_similarity(v.reshape(1,-1), key_vector.reshape(1,-1))) for i, v in enumerate(vectors)] rankings.sort(key=lambda el:-el[1]) for i, r in rankings: print(i, r) np.random.seed(1) X = np.random.random((50, 20)) pca = do_pca(X, n_components=20) X = X[:5] key_vector = X[[0]] by_relevance(X, key_vector) print() by_relevance(pca.transform(X), pca.transform(key_vector))
代码输出
Doing PCA from 50 vectors Explained variance: 1.0 0 [[1.]] 4 [[0.78738484]] 1 [[0.73532448]] 3 [[0.71538191]] 2 [[0.6614021]] 0 [[1.]] 4 [[0.01659682]] 3 [[-0.02417426]] 1 [[-0.02855172]] 2 [[-0.03232985]]
问题描述
这段代码对50个20维随机向量执行保留全部维度的PCA(解释方差为1.0),随后取前5个向量,基于余弦相似度对它们与第一个向量的相关性排序,分别在PCA变换前后调用排序函数。预期变换前后的相似度结果应相近,但实际输出中,变换后的相似度数值大幅减小,排序也发生了变化。
核心原因分析
1. PCA默认的中心化操作改变了向量方向基准
Sklearn的PCA类默认会对输入数据进行中心化(即每个特征减去整个数据集的均值),这是问题的核心:
- 原始向量是从[0,1)区间随机生成的,所有向量都分布在第一象限,彼此方向接近,因此余弦相似度普遍偏高。
- 中心化后,向量以数据集均值为原点重新分布,原本同向的向量可能被映射到完全不同的方向,甚至出现反向,直接导致余弦相似度骤降、符号改变。
2. 全维度PCA不等于原空间的恒等变换
虽然保留全部主成分意味着没有丢失数据信息,但PCA的中心化+正交旋转组合已经改变了向量的几何属性:
- 余弦相似度衡量的是向量相对于原点的方向相关性,中心化操作直接改变了每个向量的原点基准,因此变换后的向量方向和原始向量没有直接关联。
- 后续的正交旋转(主成分变换)不会改变向量间的夹角,但中心化已经彻底破坏了原始的方向关系,所以变换后的余弦相似度无法匹配原始结果。
3. 验证:关闭中心化即可恢复预期结果
如果初始化PCA时跳过中心化步骤,设置center=False,变换后的余弦相似度会和原始结果完全一致:
pca = PCA(n_components=20, center=False)
此时PCA仅执行正交旋转,不会改变向量间的夹角,余弦相似度得以完整保留,排序结果也和原始输出一致。
内容的提问来源于stack exchange,提问作者AlwaysLearning
相关产品推荐
相关产品推荐

