我正在尝试使用sklearn的PCA功能将我的数据减少到2维。但是,我注意到当使用fit_transform()函数执行此操作时,结果与使用components_ attribute与输入数据相乘的结果不匹配。
为什么这些不匹配?哪个结果是正确的?
def test_pca_fit_transform(self):
from sklearn.decomposition import PCA
input_data = np.matrix([[11,4,9,3,2,2], [7,2,8,2,0,2], [3,1,2,5,2,9]])
#each column of input data is an observation, each row is a dimension
#method1
pca = PCA(n_components=2)
data2d = pca.fit_transform(input_data.T)
#method2
component_matrix = np.matrix(pca.components_)
data2d_mult = (component_matrix * input_data).T
np.testing.assert_almost_equal(data2d, data2d_mult)
#FAILS!!!
答案 0 :(得分:2)
您缺少的唯一步骤(内部sklearn
处理)是数据居中。为了执行PCA,您的数据需要居中,如果不是,那么sklearn PCA的最佳方法之一就是:
X -= X.mean(axis=0)
将数据沿第一轴居中。
为了获得与sklearn(这是正确的)相同的结果,您只需要在适合之前或method2
之前将数据居中。
在这里找到一个有效的例子:
X = np.array([[11,4,9,3,2,2], [7,2,8,2,0,2], [3,1,2,5,2,9]])
X = X.T.copy()
# PCA
pca = PCA(n_components=2)
data = pca.fit_transform(X)
# Your method 2
data2 = X.dot(pca.components_.T)
# Centering the data before method 2
data3 = X - X.mean(axis=0)
data3 = data3.dot(pca.components_.T)
# Compare
print np.allclose(data, data2) # prints False
print np.allclose(data, data3) # prints True
请注意,我在numpy矩阵中使用标准numpy数组而不是.dot
*
,因为我希望尽可能避免使用matrix
,但结果是相同的。