我正在尝试在python中计算图像的PCA using this code by Alyssa。
# 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,但它的工作原理。
答案 0 :(得分:2)
我想问题就在这里:
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)数组 - 标准化(单位“长度”)特征向量,使得列v[:,i]
是对应于特征值{{1}的特征向量}。
而tutorial写道:
多维数组的迭代是针对第一轴完成的
我在R中做了一些交叉检查,以确保这样的计算是理智的,并且特征向量就像你期望的那样。如果您感兴趣,这里是输入和输出,中心偏离1,因为R执行基于1的索引。
w[i]
此处,> 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
中的旋转矩阵标记更清晰:列是主要成分,行是原始坐标。