您的实施
您正在计算的特征向量相关矩阵,即协方差矩阵归一化变量。
data/=np.std(data, axis=0)
不是经典 PCA 的一部分,我们只将变量居中。
所以sklearn PCA不具有预先缩放数据的功能.
除此之外,如果我们抽象出您提供的代码未运行这一事实,那么您就走在正确的轨道上;)。
您只会对行/列布局感到困惑。老实说,我认为开始要容易得多X = data.T
从此以后只与 X 合作。我在帖子末尾添加了您的代码“已修复”。
获取特征值
您已经注意到,您可以使用以下方式获取特征向量clf.components_
.
这样你就有了主要组成部分。它们是特征向量协方差矩阵????ᵀ????。
A way to retrieve the eigenvalues from there is to apply this matrix to each principal components and project the results onto the component.
Let v_1 be the first principal component and lambda_1 the associated eigenvalue. We have:
and thus:
since
. (x, y) the scalar product of vectors x and y.
回到Python你可以这样做:
n_samples = X.shape[0]
# We center the data and compute the sample covariance matrix.
X -= np.mean(X, axis=0)
cov_matrix = np.dot(X.T, X) / n_samples
for eigenvector in pca.components_:
print(np.dot(eigenvector.T, np.dot(cov_matrix, eigenvector)))
您将获得与特征向量相关的特征值。
好吧,在我的测试中,结果证明它不适用于最后几个特征值,但我将其归因于我缺乏数值稳定性方面的技能。
现在那不是best获得特征值的方法,但很高兴知道它们来自哪里。
特征值表示特征向量方向上的方差。所以你可以让他们通过pca.explained_variance_
属性:
eigenvalues = pca.explained_variance_
这是一个可重现的示例,它打印您使用每种方法获得的特征值:
import numpy as np
from sklearn.decomposition import PCA
from sklearn.datasets import make_classification
X, y = make_classification(n_samples=1000)
n_samples = X.shape[0]
pca = PCA()
X_transformed = pca.fit_transform(X)
# We center the data and compute the sample covariance matrix.
X_centered = X - np.mean(X, axis=0)
cov_matrix = np.dot(X_centered.T, X_centered) / n_samples
eigenvalues = pca.explained_variance_
for eigenvalue, eigenvector in zip(eigenvalues, pca.components_):
print(np.dot(eigenvector.T, np.dot(cov_matrix, eigenvector)))
print(eigenvalue)
您的原始代码已修复
如果运行它,您会发现这些值是一致的。它们并不完全相等,因为 numpy 和 scikit-learn 在这里没有使用相同的算法。
最主要的是您使用的是相关矩阵而不是协方差,如上所述。另外你还得到了转置来自 numpy 的特征向量这使得它非常混乱。
import numpy as np
from scipy.stats.mstats import zscore
from sklearn.decomposition import PCA
def pca_code(data):
#raw_implementation
var_per=.98
data-=np.mean(data, axis=0)
# data/=np.std(data, axis=0)
cov_mat=np.cov(data, rowvar=False)
evals, evecs = np.linalg.eigh(cov_mat)
idx = np.argsort(evals)[::-1]
evecs = evecs[:,idx]
evals = evals[idx]
variance_retained=np.cumsum(evals)/np.sum(evals)
index=np.argmax(variance_retained>=var_per)
evecs = evecs[:,:index+1]
reduced_data=np.dot(evecs.T, data.T).T
print("evals", evals)
print("_"*30)
print(evecs.T[1, :])
print("_"*30)
#using scipy package
clf=PCA(var_per)
X_train=data
X_train=clf.fit_transform(X_train)
print(clf.explained_variance_)
print("_"*30)
print(clf.components_[1,:])
print("__"*30)