前两个主成分反转

First two Principal components are reversed

我正在尝试计算 python 中图像 using this code by Alyssa 的 PCA。

# Read the image into palmFingers_mask:  
# we use PCA and otain 2 principal components
y, x = np.nonzero(palmFingers_mask)
# Subtract mean from each dimension
x = x - np.mean(x)
y = y - np.mean(y)
coords = np.vstack([x, y]) 
# Covariance matrix and its eigenvectors and eigenvalues
cov = np.cov(coords)
evals[:,frm_cnt], evecs = np.linalg.eig(cov)
# Sort eigenvalues in decreasing order
sort_indices = np.argsort(evals[:,frm_cnt])[::-1]
evec1[:,frm_cnt], evec2[:,frm_cnt] = evecs[:, sort_indices]
x_v1, y_v1 = evec1[:,frm_cnt]  # Eigenvector with largest eigenvalue
x_v2, y_v2 = evec2[:,frm_cnt]
# Plot the principal components
scale = 20
plt.figure(1)
plt.plot(x, y, 'y.')
plt.plot([x_v1*-scale*2, x_v1*scale*2],
                 [y_v1*-scale*2, y_v1*scale*2], color='red')
plt.plot([x_v2*-scale, x_v2*scale],
                 [y_v2*-scale, y_v2*scale], color='blue')
plt.axis('equal')
plt.gca().invert_yaxis()  # Match the image system with origin at top left
plt.show()

我用红线和蓝线标记了两个轴(红色是较大的部分,线的长度不代表任何东西)。

在这样做的过程中,我遇到了一个错误案例,如下所示:

这怎么可能?这描绘了红色特征向量更大,但从直觉上看,不应该是这样。轴(沿蓝线)应该是较大的,对吧?对于我数据库中的所有其他图像,我发现轴是正确的。只为这个形象,互换;我附上了输入图像 (Img 209.png)

我的理解有问题吗?

这是我所期望的:

例如,我附上了它适用的 BinImg_20.png。

Attached files are on Dropbox.

我会说问题出在这里:

evec1, evec2 = evecs[:, sort_indices]

此时你有

evecs = [[ 0.70926191  0.70494507]
         [-0.70494507  0.70926191]]
evec1 = [ 0.70926191  0.70494507]
evec2 = [-0.70494507  0.70926191]

sort_indices 的索引正确排序了 。但是解包作业然后按 解包,导致您观察到的错误。

另见 the documentation for numpy.linalg.eig 其中指出:

v: (..., M, M) array – The normalized (unit “length”) eigenvectors, such that the column v[:,i] is the eigenvector corresponding to the eigenvalue w[i].

tutorial 写道:

Iterating over multidimensional arrays is done with respect to the first axis


我在 R 中做了一些交叉检查,以确保计算本身是合理的,并且特征向量与您期望的一样。如果您有兴趣,这里是输入和输出,中心偏离 1,因为 R 执行基于 1 的索引。

> install.packages("pixmap")
> library(pixmap)
> pix <- read.pnm("BinImg_209.pbm")
> mask = which(pix@grey != 0, arr.ind=T)
> mask = data.frame(x=mask[,"col"], y=mask[,"row"])
> prcomp(mask)         # single step principal component analysis
Standard deviations (1, .., p=2):
[1] 117.84952  44.23114

Rotation (n x k) = (2 x 2):
         PC1       PC2
x  0.7092619 0.7049451
y -0.7049451 0.7092619

> cov <- cov.wt(mask)  # manual covariance computation
> cov                  # show computed data
$cov
          x         y
x  7958.874 -5965.947
y -5965.947  7886.030

$center
       x        y 
593.1907 519.1019 

$n.obs
[1] 47909

> eigen(cov$cov)       # manual computation of eigenvectors
eigen() decomposition
$values
[1] 13888.510  1956.394

$vectors
           [,1]       [,2]
[1,] -0.7092619 -0.7049451
[2,]  0.7049451 -0.7092619

这里,vectors 矩阵的 也是特征向量。 prcomp中的旋转矩阵标注的更清楚:列为主成分,行为原始坐标。