【问题标题】:PCA difference between python numpy and sklearnpython numpy和sklearn之间的PCA区别
【发布时间】:2018-05-01 16:15:09
【问题描述】:

我正在尝试使用 numpy.linalg.eig 和两种不同的方法(在 eigenface 中使用协方差和 pca 方法)来实现 PCA,并将我的结果与 sklearn 的 PCA 进行比较。但是我观察到我的结果是不同的,所以我想知道我在做什么错误。我有 3 个样本,每个样本有 4 个特征。我正在尝试将样本的维度减少到 3。 编辑:使用 SVD 方法添加。我使用协方差 PCA 得到的结果,来自 sklearn 的 SVD 和 PCA 非常接近。但是使用“特征脸”方法完全不同,为什么? 将 numpy 导入为 np 从 sklearn.decomposition 导入 PCA

x = np.array([[0.5, 0.8, 1.5, -2.4], [-1.9, -8.7, 0.02, 4.9], [5.5,6.1, -8.1,3.0]])
print(x)
K = 3

# -- sklearn -- #
pca = PCA(n_components=K).fit(x)
res = pca.transform(x)
print('sklearn :', res)

# -- numpy covariance -- #
X = x - np.mean(x, axis = 0)  

cov = np.cov(X.T)
print("covariance :", cov.shape)

evals , evecs = np.linalg.eig(cov)

idx = np.argsort(evals)[::-1]
evecs = evecs[:,idx]
evals = evals[idx]

res2 = X.dot(evecs[:,:K]) 
print("numpy with cov:", res2)

# -- numpy scatter matrix -- #
X = x - np.mean(x, axis = 0)
C = np.dot(X, X.T)
evals , evecs = np.linalg.eig(C)
idx = np.argsort(evals)[::-1]
evecs = evecs[:,idx]
evals = evals[idx]

v = np.dot(evecs, X)
print("v :", v.shape)
res3= X[:, :K].dot(v)
print('numpy with scatter matrix : ', res3)

# -- numpy svd -- #
X = x - np.mean(x, axis = 0)  
U, S, V = np.linalg.svd(X, full_matrices=False)
U, V = svd_flip(U, V)
res2 = X.dot(V.T) 
print("numpy with svd:", res2)

【问题讨论】:

    标签: python numpy pca


    【解决方案1】:

    首先:这是什么意思?您在 4 维空间中有三个点。它们跨越二维平面。 PCA 找到这个平面的基础,以及在该基础上的点的系数。使用 Matlab 的[C, S] = pca(x) 进行比较:我们得到 ​​p>

    C =
        0.4028    0.1082
        0.7895   -0.3198
       -0.4560   -0.5881
       -0.0806    0.7349
    

    S =
       -0.5865   -5.8249
       -8.9674    3.1891
        9.5539    2.6357
    

    这些矩阵具有S*C' 恢复居中数据的属性(在您的符号中为X)。 C 的列是二维子空间的基向量,S 的行是该子集中三个点的坐标。

    Sklearn 回归

    [[ -5.86525831e-01   5.82485371e+00  -2.65147201e-16]
     [ -8.96738194e+00  -3.18911605e+00   1.41061647e-16]
     [  9.55390777e+00  -2.63573766e+00  -5.28988843e-16]]
    

    其中第三列是噪声(基本上为零),反映了点位于二维平面中;没有找到第三个主成分。前两列与 Matlab 中的 S 匹配,符号选择除外。

    您对“NumPy with cov”的计算与 sklearn 相同,只是第 3 列中的随机噪声不同。顺便说一句,对于这种计算,您不需要将数据居中; cov 自己做。 cov = np.cov(x.T) 也可以。

    [[ -5.86525831e-01  -5.82485371e+00   5.26721273e-16]
     [ -8.96738194e+00   3.18911605e+00   3.83725073e-15]
     [  9.55390777e+00   2.63573766e+00  -3.35763132e-15]]  
    

    “特征脸”方法

    这里的主要思想是,我们将使用更小的C = np.dot(X, X.T),而不是计算np.dot(X.T, X)(本质上是协方差,直到一个常数因子)。我们需要的基向量将通过将 C 的特征向量与X.T 相乘来获得(如果您关注Wikipedia's article,请注意它们的 T 与您的 X 具有不同的方向)。但是,与np.linalg.eig 返回的向量不同,这些向量并未标准化。我们必须在使用之前对它们进行规范化:

    X = x - np.mean(x, axis = 0)
    C = np.dot(X, X.T)
    evals , evecs = np.linalg.eig(C)
    idx = np.argsort(evals)[::-1]
    evecs = evecs[:,idx]
    evals = evals[idx]
    v = np.dot(X.T, evecs)
    v /= np.linalg.norm(v, axis=0)
    res3 = X.dot(v)
    

    这会返回

    [[-0.58652583 -5.82485371  5.05711518]
     [-8.96738194  3.18911605  1.72266002]
     [ 9.55390777  2.63573766 -6.7797752 ]]
    

    在前两列中是正确的。同样,第三列是噪声,但现在是经过归一化的噪声,所以它一点也不小。必须明白第三列是没有意义的。

    【讨论】:

    • 感谢您的回答。我“随机”选择这些数据的目标是拥有比样本更多的特征。事实上,我将尝试使用 numpy.linal.eig 来实现特征脸过程,用于 pca 实现。所以我将有 n 个大小为 M 的图像(等于宽度 x 高度),其中 n
    • 我可能对“散布矩阵”这个名称有误,我试图实现的是一种在有关特征脸的文章中经常使用的方法。目标是不计算 M 特征值,而仅计算 n 个最佳特征值/特征向量。在 wikipedia 'computing the eigenvector' 部分:en.wikipedia.org/wiki/Eigenface 由于我的数据维度与 wiki 不同,我尝试转置它们,但这似乎是个坏主意。
    • 我用正确的“特征脸”方法编辑了答案。
    • 感谢您的帮助。我有最后一个问题,关于最后一个特征向量(第 3 列)。您说它是噪声,因为它本质上接近于 0,但它是由于它的特征值与其他特征值相比非常小吗?那么我们可以概括,如果特征值与之前的特征值相比非常小,那么特征向量本质上是由噪声组成的?
    • 在某种程度上,是的:在 PCA 中,一旦特征值急剧下降,人们就可以停止寻找新的组件。尽管如此,人们还是应该考虑每种特定情况下的过程来理解输出的含义。第三个特征向量本身是有意义的,它是一个垂直于包含我们数据的二维平面的向量。乘以X,理论上为0;在实践中,它们是舍入误差。理想情况下,它们应该被理解为“0向量”。使用特征脸方法,向量除以其范数,然后它就不再有意义了。
    【解决方案2】:

    我的猜测是,您计算特征向量的两种方法给出的结果与 scipy.linalg.svd 不同,这是 scipy 的 PCA 实现使用的 (https://github.com/scikit-learn/scikit-learn/blob/f3320a6f/sklearn/decomposition/pca.py#L399)。

    这可能是一个很好的起点:Eigenvectors computed with numpy's eigh and svd do not match

    【讨论】:

    • 感谢您的回答,确实它使用了 svd 但这是否意味着特征向量必须不同?我尝试改用 svd (可在编辑中获得),但我有同样的问题,有些值不同。我使用协方差 PCA 得到的结果,来自 sklearn 的 SVD 和 PCA 非常接近。但是使用“特征脸”方法就完全不同了,为什么?
    猜你喜欢
    • 2017-07-19
    • 2019-03-05
    • 2013-07-04
    • 2022-01-04
    • 2012-06-17
    • 2016-11-16
    • 2018-03-10
    • 2021-03-24
    • 2021-09-06
    相关资源
    最近更新 更多