scipy 从sklearn PCA获取特征值和向量

4szc88ey  于 2022-11-10  发布在  其他
关注(0)|答案(3)|浏览(261)

如何获得PCA应用程序的特征值和特征向量?

from sklearn.decomposition import PCA
clf=PCA(0.98,whiten=True)      #converse 98% variance
X_train=clf.fit_transform(X_train)
X_test=clf.transform(X_test)

我在文档里找不到。
1.我“不”能够理解这里的不同结果。

编辑

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)
    print("_"*30)
    print(evecs)
    print("_"*30)
    #using scipy package
    clf=PCA(var_per)
    X_train=data.T
    X_train=clf.fit_transform(X_train)
    print(clf.explained_variance_)
    print("_"*30)
    print(clf.components_)
    print("__"*30)

1.我希望得到所有的特征值和特征向量,而不仅仅是收敛条件下的约化集。

nzk0hqpo

nzk0hqpo1#

您的实现

您正在计算相关矩阵的特征向量,即 * 归一化 * 变量的协方差矩阵。
data/=np.std(data, axis=0)不是经典PCA的一部分,我们仅将变量置于中心。因此sklearn PCA不会预先对数据进行特征缩放
除此之外,你是在正确的轨道上,如果我们抽象的事实,你提供的代码没有运行;)。你只是对行/列布局感到困惑。老实说,我认为从X = data.T开始,然后从那里开始只使用X要容易得多。我在帖子的最后添加了你的代码“fixed”。

获取特征值

你已经注意到,你可以用clf.components_得到特征向量。
所以你有主成分,它们是协方差矩阵的特征向量𝑋𝑋。
一种从那里检索特征值的方法是将该矩阵应用于每个主成分,并将结果投影到该成分上。设v_1为第一主成分,λ _1为相关的特征值。我们有:
x1c 0d1x,因此:

,因为

.(x,y)是向量x和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)))

然后你得到了与特征向量相关的特征值,在我的测试中,它对最后的几个特征值不起作用,但我认为这是因为我缺乏数值稳定性方面的技巧。
这不是得到特征值的最佳方法,但知道它们来自哪里是很好的。
特征值表示特征向量方向上的方差,因此可以通过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)
uz75evzq

uz75evzq2#

我使用了sklearn PCA函数。返回参数“components_”是特征向量,“explained_variance_”是特征值。下面是我的测试代码。

from sklearn.decomposition import PCA
import numpy as np

def main():
    data = np.array([[2.5, 2.4], [0.5, 0.7], [2.2, 2.9], [1.9, 2.2], [3.1, 3.0], [2.3, 2.7], [2, 1.6], [1, 1.1], [1.5, 1.6], [1.1, 0.9]])
    print(data)
    pca = PCA()
    pca.fit(data)

    print(pca.components_)
    print(pca.explained_variance_)

if __name__ == "__main__":
    main()
kqhtkvqz

kqhtkvqz3#

当你说“特征值”时,你是指PCA的“奇异值”吗?只有当PCA应用的矩阵是方阵时,特征值才是可能的。
如果你试图用“特征值”来确定PCA所需的适当维数,你实际上应该使用奇异值。你可以只使用pca.singular_values_来得到奇异值。

相关问题