【问题标题】:Obtain eigen values and vectors from sklearn PCA从 sklearn PCA 获取特征值和向量
【发布时间】:2015-11-01 19:12:07
【问题描述】:

如何获取 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)

我在docs 中找不到它。

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. 我希望获得所有特征值和特征向量,而不仅仅是具有收敛条件的约简集。

【问题讨论】:

  • 显然,我误认为.explained_variance_ 给出了实际的特征值,所以我删除了我的答案,因为它不准确。如果我想出任何办法,我会告诉你的。好问题。
  • @Akavall 一种简单的方法是将方差作为1 传递,然后获取值。但是再次运行它没有意义。请问sklearn功能中的PCA之前是否对数据进行了缩放?
  • @Akavall 我不认为你弄错了。特征值由.explained_variance_ 给出。这里代码使用了correlation矩阵,所以得到的特征值是不同的。

标签: python scipy scikit-learn pca


【解决方案1】:

您的实施

您正在计算相关矩阵的特征向量,即归一化变量的协方差矩阵。
data/=np.std(data, axis=0) 不是经典 PCA 的一部分,我们只将变量居中。 所以 sklearn PCA 没有预先缩放数据

除此之外,如果我们抽象出您提供的代码没有运行的事实,那么您是在正确的轨道上;)。 您只会对行/列布局感到困惑。老实说,我认为从 X = data.T 开始并从那里只使用 X 会容易得多。我在帖子末尾添加了您的代码“已修复”。

获取特征值

您已经注意到可以使用clf.components_ 获取特征向量。

所以你有主要的组成部分。它们是协方差矩阵?ᵀ?的特征向量。

从那里检索特征值的一种方法是将此矩阵应用于每个主成分并将结果投影到该成分上。 令 v_1 为第一主成分, lambda_1 为相关特征值。我们有:
,因此: 。 (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)

希望这会有所帮助,请随时要求澄清。

【讨论】:

  • 从 pca.get_covariance() 得到的协方差和 cov(data) 有什么区别?使用 linalg.eigh,您可以将 evals 与 evacs 相乘以得到 cov(data),但是如果将 clf.expained_variance 与 clf.components__ 相乘,您会得到什么?
  • 根据我的实验,如果 n_samples >= n_features,您只能从 clf.components_ 获得特征向量,在这种情况下,clf.components_ 是一个方阵,假设您生成所有组件。如果 n_samples clf.components_ 是一个形状为 (n_components, n_features) 的矩阵,其行包含主成分向量。
【解决方案2】:

我使用了 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()

【讨论】:

    【解决方案3】:

    当您说“特征值”时,您是指 PCA 的“奇异值”吗?只有当应用的矩阵 PCA 是方阵时,特征值才有可能。

    如果您尝试使用“特征值”来确定 PCA 所需的正确维度,您实际上应该使用奇异值。您可以只使用 pca.singular_values_ 来获取奇异值。

    【讨论】:

      猜你喜欢
      • 2017-04-30
      • 1970-01-01
      • 1970-01-01
      • 2016-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-08
      • 2018-02-13
      相关资源
      最近更新 更多