前两个主成分反转
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。
我会说问题出在这里:
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
中的旋转矩阵标注的更清楚:列为主成分,行为原始坐标。
我正在尝试计算 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。
我会说问题出在这里:
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 columnv[:,i]
is the eigenvector corresponding to the eigenvaluew[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
中的旋转矩阵标注的更清楚:列为主成分,行为原始坐标。