用于计算 PCA 尺度上的点的特征向量和样本

Eigenvectors and samples to calculate the points on PCA scale

我想在 PC1PC2 的新等级上获得新分数。 我计算了特征值、特征向量和贡献。

现在我想计算新尺度(分数)上的点,以对其应用 K-Means 聚类算法。

每当我尝试通过说 z_new = np.dot(v, vectors)(使用 v = np.cov(x))来计算它时,我得到一个错误的分数,PC1 为 [[14. -2. -2. -1. -0. 0. 0. -0. -0. 0. 0. -0. 0. 0.],PC2 为 [-3. -1. -2. -1. -0. -0. 0. 0. 0. -0. -0. 0. -0. -0.]。正确的分数分数(使用 SciKit 的 PCA() 函数计算)应该是 PC1: [ 4 4 -6 3 1 -5]PC2: [ 0 -3 1 -1 5 -4]

这是我的代码:

dataset = pd.read_csv("cands_dataset.csv")
x = dataset.iloc[:, 1:].values

m = x.mean(axis=1);
for i in range(len(x)):
    x[i] = x[i] - m[i]

z = x / np.std(x)
v = np.cov(x)
values, vectors = np.linalg.eig(v)
d = np.diag(values)
p = vectors
z_new = np.dot(v, p) # <--- Here is where I get the new scores
z_new = np.round(z_new,0).real
print(z_new)

我得到的结果:

[[14. -2. -2. -1. -0.  0.  0. -0. -0.  0.  0. -0.  0.  0.]
 [-3. -1. -2. -1. -0. -0.  0.  0.  0. -0. -0.  0. -0. -0.]
 [-4. -0.  3.  3.  0.  0.  0.  0.  0. -0. -0.  0. -0. -0.]
 [ 2. -1. -2. -1.  0. -0.  0. -0. -0.  0.  0. -0.  0.  0.]
 [-2. -1.  8. -3. -0. -0. -0.  0.  0. -0. -0. -0.  0.  0.]
 [-3.  2. -1.  2. -0.  0.  0.  0.  0. -0. -0.  0. -0. -0.]
 [ 3. -1. -3. -1.  0. -0.  0. -0. -0.  0.  0. -0.  0.  0.]
 [11.  6.  4.  4. -0.  0. -0. -0. -0.  0.  0. -0.  0.  0.]
 [ 5. -8.  6. -1.  0.  0. -0.  0.  0.  0.  0. -0.  0.  0.]
 [-1. -1. -1.  1.  0. -0.  0.  0.  0.  0.  0.  0. -0. -0.]
 [ 5.  7.  1. -1.  0. -0. -0. -0. -0.  0.  0. -0. -0. -0.]
 [12. -6. -1.  2.  0.  0.  0. -0. -0.  0.  0. -0.  0.  0.]
 [ 3.  6.  0.  0.  0. -0. -0. -0. -0.  0.  0.  0. -0. -0.]
 [ 5.  5. -0. -4. -0. -0. -0. -0. -0.  0.  0. -0.  0.  0.]]

数据集(由评论请求):

在我看来,您有 6 个 14 维的样本。 PCA过程如下:

1。去掉均值

从以下数据开始:

data  = np.array([[10, 9, 1, 7, 5, 3],
                  [10, 8,10, 8, 8,10],
                  [ 4, 6, 8, 9, 8, 9],
                  [ 9, 9, 6, 6, 8, 7],
                  [ 4, 9,10, 9, 5, 5],
                  [ 7, 6, 9, 9,10,10],
                  [10, 9, 6, 6, 8, 7],
                  [ 5, 4, 2,10, 9, 1],
                  [ 4,10, 4, 9, 2, 6],
                  [ 8, 7, 7, 7, 7, 9],
                  [ 5, 5, 6, 6, 9, 1],
                  [ 9,10, 1, 9, 5, 6],
                  [ 7, 6, 6, 6,10, 4],
                  [10, 9, 9, 7, 9, 4]])

我们可以通过以下方式去除均值:

centered_data = data - np.mean(data, axis=1)[:, None]

2。创建协方差矩阵

可按如下方式进行:

covar = np.cov(centered_data)

3。获取主成分

这可以使用协方差矩阵的特征值分解来完成

eigen_vals, eigen_vecs = np.linalg.eig(covar)
eigen_vals, eigen_vecs = np.real(eigen_vals), np.real(eigen_vecs)

4。降维

现在我们可以通过选择具有最高匹配特征值(方差)的两个PC来进行降维。在您的示例中,您需要 2 维,因此我们采用两台主要 PC:

eigen_vals = 
array([ 3.34998559e+01,  2.26499704e+01,  1.54115835e+01,  9.13166675e+00,
        1.27359015e+00, -3.10462438e-15, -1.04740277e-15, -1.04740277e-15,
       -2.21443036e-16,  9.33811755e-18,  9.33811755e-18,  6.52780501e-16,
        6.52780501e-16,  5.26538300e-16])

可以看出前两个特征值最高:

eigen_vals[:2] = array([33.49985588, 22.64997038])

因此,我们可以将前两台PC上的数据投影如下:

projected_data = eigen_vecs[:, :2].T.dot(centered_data)

现在可以打散了,我们可以看到14维降为2维:

PC1 = [0.59123632, -0.10134531, -0.20795954,  0.1596049 , -0.07354629, 0.19588723,  0.19151677,  0.33847213,  0.22330841, -0.03466414, 0.1001646 ,  0.52913917,  0.09633029,  0.16141852]
PC2 = [-0.07551251, -0.07531288,  0.0188486 , -0.01280896, -0.07309957, 0.12354371, -0.01170589,  0.49672196, -0.43813664, -0.09948337, 0.49590461, -0.25700432,  0.38198034,  0.2467548 ]

一般分析

自从我们做了 PCA 之后,现在每个维度都有正交方差(对角协方差矩阵)。为了更好地理解降维的可能性,我们可以看到数据的总方差是如何分布在不同维度上的。这可以通过特征值圆顶:

var_dim_contribution = eigen_vals / np.sum(eigen_vals)

绘制此结果:

我们可以在这里看到,使用 2 个主要 PC,我们可以描述 ~67% 的方差。添加第三个维度将使我们接近 90% 的方差。这是 14 的一个很好的减少。这在累积方差图中看起来更好。

var_cumulative_contribution = np.cumsum(eigen_vals / np.sum(eigen_vals))

与sklearn的比较

sklearn.decomposition.PCA 比较时,我们得到以下结果:

from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pca.fit(centered_data.T)
print(pca.explained_variance_ratio_)  # [0.40870097 0.27633148]
print(pca.explained_variance_)        # [33.49985588 22.64997038]

我们看到我们得到了与手动计算相同的解释方差和方差值,此外,结果 PC 为:

print(pca.components_)
[[-0.59123632  0.10134531  0.20795954 -0.1596049   0.07354629  0.19588723 0.19151677 -0.33847213 -0.22330841  0.03466414 -0.1001646  -0.52913917 -0.09633029 -0.16141852]
 [-0.07551251 -0.07531288  0.0188486  -0.01280896 -0.07309957  0.12354371 -0.01170589  0.49672196 -0.43813664 -0.09948337  0.49590461 -0.25700432 0.38198034  0.2467548 ]]

而且我们看到我们得到了与 scikit

相同的结果