【问题标题】:Different results with PCA and SVD on data with same unitsPCA 和 SVD 对相同单位数据的不同结果
【发布时间】:2020-08-06 18:14:34
【问题描述】:

一开始,我有 400,000 张经过归一化的图像(灰度值增加)。之后,我对每张图片进行了 DFT,得到了 400000 个样本的数据,具有 3200 个绝对傅立叶系数。

现在我想做一个 PCA 和 SVD。 由于我的数据已经标准化并且所有值都具有相同的单位,我认为我可以使用“原始数据”进行计算。 但是,PCA 的特征值和 SVD 的奇异值是不同的。 (显示图片/链接)

我做错了什么? PCA 和 SVD 应该如何获取数据?标准化、标准化、原始?

请帮帮我!谢谢

我的代码:

# samples 400000x3200
# SVD
U,S,VT = svd(samples, full_matrices=False) 

tot_S = sum(S)
var_exp_S = [(i / tot_S) for i in S]
cum_var_exp_S = np.cumsum(var_exp_S)

# PCA
cov_mat = np.cov(samples.T)
eigen_vals, eigen_vecs = np.linalg.eig(cov_mat)
eigen_vals = np.asarray(sorted(eigen_vals,reverse=True))

tot = sum(eigen_vals)
var_exp = [(i / tot) for i in eigen_vals]
cum_var_exp = np.cumsum(var_exp)


num= 3200
plt.figure(figsize=(10,5))
plt.subplot(121)
plt.title('PCA')
plt.step(range(1,num+1),cum_var_exp[:num], where='mid',color='r')
plt.ylabel('share of variance')
plt.xlabel('principal components')
plt.legend()
plt.grid()

plt.subplot(122)
plt.title('SVD')
plt.step(range(1,num+1),cum_var_exp_S[:num], where='mid',color='r')
plt.ylabel('share of variance')
plt.xlabel('principal components')
plt.legend()
plt.grid()

【问题讨论】:

  • pca 的标准化由 cov() 完成。数值问题可能存在问题。我建议使用来自维基百科或类似的一些简单数据来验证您的类型变量。 (我不记得 svd 和 pca 之间的依赖关系,因为在我的库中我使用幂迭代而不是 svd)
  • 首先,非常感谢您的回答。我找到了我在代码中使用的 svd 函数的依赖项:“相应的(可能非零)特征值由 s**2 给出。”所以关于你的回答我不需要 cov() 因为数据已经标准化了?然后我可以通过 np.linalg.eigh((samples.T).dot(samples) 直接用“原始数据”计算特征值?
  • 不,我猜你需要 SVD。我只是这样做,因为我不想自己实现 svd。对于标准化,问题可能就是您的意思。 PCA 中有一些部分会进行一些标准化。我把它放到一个答案中......:

标签: normalization pca svd eigenvalue standardized


【解决方案1】:

这些图像来自数据集 (400000x3200):

PCA

SVD

【讨论】:

    【解决方案2】:

    PCA 中有一些“规范化”。 这里是我自己的 PCA 库中的代码:

    
    //normalize to center
    centred = center( samples );
    //normalize to square matrix
    matrix = cov( centred );
    //eigenvalue decomposition
    vectors = evd( matrix );
    //get normalized eigenvectors:
    eigenvectors = get_eigenvectors( vectors );
    //get eigenvalues:
    eigenvalues = get_eigenvalues( vectors );
    
    

    relation between SVD and PCA被描述为:M*M的特征值是M的奇异值的平方。

    【讨论】:

    • 所以我应该对原始数据使用 PCA/SVD 吗?
    • 这取决于你想用它做什么。 PCA 通常会执行 SVD 以获得结果。你对奇异值的计划是什么? (我以前从未使用过它们。)
    • 好的,我尝试用一​​个单独的答案中的例子来解释它......
    【解决方案3】:

    这是一个例子:

    import numpy as np
    from scipy.linalg import svd
    from sklearn.preprocessing import StandardScaler
    
    X_train = np.asarray([[13.71,1.86,2.36,16.6],[12.22,1.29,1.94,19],
           [13.27,4.28,2.26,20],[13.16,3.57,2.15,21],
           [13.86,1.51,2.67,25]])
    
    #PCA
    sc = StandardScaler()
    X_train_std = sc.fit_transform(X_train)
    
    cov_mat = np.cov(X_train_std.T)
    eigen_vals, eigen_vecs = np.linalg.eigh(cov_mat)
    eigen_vals = np.asarray(sorted(eigen_vals, reverse=True))
    
    #SVD
    U,eigen_vals_S,V = svd(X_train)
    eigen_vals_S2 = (eigen_vals_S**2)
    
    print('\nEigenvalues \n%s' % eigen_vals)
    print('\nS \n%s' %eigen_vals_S)
    print('\nS**2 \n%s' %eigen_vals_S2)re
    

    输出(特征值和S**2不同):

    特征值 [2.79331043 1.28393579 0.90313734 0.01961644]

    S [55.02775284 3.37434634 2.52347705 0.28664958]

    S**2 [3.02805358e+03 1.13862132e+01 6.36793643e+00 8.21679822e-02]

    现在结果相同:

    #Same eigenvalues
    eigen_vals, eigen_vecs = np.linalg.eigh((X_train.T).dot(X_train))
    eigen_vals = np.asarray(sorted(eigen_vals, reverse=True))
    
    #SVD
    U,eigen_vals_S,V = svd(X_train)
    eigen_vals_S2 = (eigen_vals_S**2)
    
    print('\nEigenvalues \n%s' % eigen_vals)
    print('\nS \n%s' %eigen_vals_S)
    print('\nS**2 \n%s' %eigen_vals_S2)
    

    输出:

    特征值 [3.02805358e+03 1.13862132e+01 6.36793643e+00 8.21679822e-02]

    S [55.02775284 3.37434634 2.52347705 0.28664958]

    S**2 [3.02805358e+03 1.13862132e+01 6.36793643e+00 8.21679822e-02]

    这就是我不明白的。标准化和 cov() 的方法是 PCA 的方法。但是正如你所看到的,有不同的结果,这取决于我如何计算特征值......

    我有什么问题吗?或者为什么会这样?

    【讨论】:

    • svd 返回奇异值,而不是特征值。如我的回答中所述,它们相关但不相等
    • 我知道,但是在 svd 的描述中,它说“在这两种情况下,对应的(可能非零)特征值都由 s**2 给出。” link 它应该是相同的,当我平方奇异值时......或者不是?
    • 据我了解是:eigenvalue_i( PCA( M * M ) ) == single_value_i( M )^2
    • 如果你只是想验证特征值,还有其他方法。我总是用 pca 的分数重建样本,这表明存在数值问题。
    • 但是我通过标准化和 cov()“手动”完成的方式是 PCA,不是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2016-06-09
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    • 2013-04-09
    相关资源
    最近更新 更多