PCA(主成分分析)简介与使用

1 PCA(Principal Component Analysis)简介

在平常的研究和应用中处理的数据都是多变量的(多维),能够提供丰富的信息,但是很难对多维的数据各维指标进行分析,因为往往孤立地分析每个指标不能完全利用数据中的信息,但盲目减少指标会损失很多有用的信息。

所以我们需要找到一种合理的方法,在减少需要分析的指标的同时尽量减少原指标包含信息的损失。

数据的各变量之间存在一定的相关关系,所以我们可以考虑将关系紧密的变量变成尽可能少的新变量,使得新得到的变量是两两不相关的。这样就可以用较少的综合指标分别代表存在于各个变量中的信息。

主成分分析(PCA)就是利用上述方法对多维数据进行降维,将拥有多个属性的数据转换为少数属性的数据,便于分析数据。PCA的主要思想是将n维特征映射到k维上(k维特征是从n维特征重新构造出来的正交特征,也称为主成分)

PCA的算法流程是利用数据的协方差矩阵计算其特征值和特征向量,然后选出少量(想要最后拥有多少属性就选择多少)的较大特征值的特征向量与原始数据点积得到降维后的数据。下面来看具体的内容。

降维:对高维度特征数据预处理,保留最重要的一些特征,去除噪声和不重要的特征(伴随着些许信息的损失)。

1.1 协方差矩阵

首先我们想知道什么是协方差矩阵,先来看协方差:协方差是用来衡量两个变量相关性的变量,当这两个变量是同一变量时协方差便是方差。

假设两个变量\(X\)\(Y\),那么\(X\)\(Y\)的协方差为: \[ Cov(X,Y)=\frac{\sum_{i=1}^n{(x_i-\overline x)(y_i-\overline y)}}{n-1} \]

其中,\(\overline x\)\(X\)的均值。除以n-1而不是n是因为

  1. 当两个变量是正相关关系(同增同减)时,协方差>0;
  2. 当两个变量是负相关关系(一增一减)时,协方差<0;
  3. 当两个变量不相关时,协方差=0。

所以,协方差矩阵表示的是所有变量之间两两相关的关系。

从二维协方差矩阵矩阵开始,其实二维的协方差矩阵没有实际意义,为了方便后面多维协方差矩阵的推广,先从二维协方差矩阵开始看。

假设我们有样本Z如下: \[ Z=\begin{bmatrix} 1 & 2 \\ 3 & 6 \\ 4 & 2 \\ 5 & 2 \end{bmatrix} \]

利用两个变量空间\(X\)\(Y\)来表示上面的两列(即两个特征): \[ X=\begin{bmatrix} 1 \\ 3 \\ 4 \\ 5 \end{bmatrix}, \ \ \ Y=\begin{bmatrix} 2 \\ 6 \\ 2 \\ 2 \end{bmatrix} \]

那么协方差矩阵\(Cov(Z)\)为: \[ Cov(Z)=\begin{bmatrix} Cov(X,X) & Cov(X,Y) \\ Cov(Y,X) & Cov(Y,Y) \end{bmatrix} \]

由协方差的计算公式计算协方差矩阵中的各项:

首先需要出\(X\)\(Y\)两个特征空间的平均值\(\overline x = 3.25\), \(\overline y = 3\)

接下来计算矩阵中的各项: \[ Cov(X,X)=\frac{(1-3.25)^2+(3-3.25)^2+(4-3.25)^2+(5-3.25)^2}{4-1}=2.9167 \]

\[ Cov(X,Y)=\frac{(1-3.25)(2-3)+(3-3.25)(6-3)+(4-3.25)(2-3)+(5-3.25)(2-3)}{4-1}=-0.3333 = Cov(Y,X) \]

\[ Cov(Y,Y)=\frac{(2-3)^2+(6-3)^2+(2-3)^2+(2-3)^2}{4-1}=4 \]

所以最后得到的协方差矩阵为: \[ Cov(Z)=\begin{bmatrix} 2.9167 & -0.3333 \\ -0.3333 & 4.000 \end{bmatrix} \]

经过上面二维协方差矩阵的计算可以总结出协方差矩阵的计算方式(任意维):

首先对样本Z按列进行中心化,即Z中的每列数据减去这列的平均值。(将中心化后的Z重新赋值给Z)。

然后通过公式\(Cov(Z) = \frac{1}{n} ZZ^{T}\)即可得到协方差矩阵。

1.2 特征向量

参考链接:link1 , link2

对于线性代数而言,特征向量和特征值体现了矩阵的本质。借一个比喻来看,把矩阵看做运动,那么特征值是速度的大小,而特征向量是速度的方向。还可以说特征向量是在其矩阵的作用下进行伸缩,伸缩的幅度由特征向量对应的特征值确定。

特征值和特征向量的定义如下:

假设A是n阶矩阵,如果存在常数λ和n维非零向量X使得: \[ AX = \lambda X \]

通常来说,矩阵A会有一组特征向量,将它们进行正交化单位化,就能得到一组正交单位特征向量。

2 PCA的使用

2.1 数据

这里使用的数据是谷歌新闻的词向量数据集的一部分,也就是部分词的词向量。

数据文件在这里

导入数据,即获取词向量:

1
2
3
4
5
6
7
8
import numpy as np
import pickle
import pandas as pd
import matplotlib.pyplot as plt

word_embeddings = pickle.load(open('./word_embeddings_subset.p','rb'))
print(len(word_embeddings))
print("dimension: {}".format(word_embeddings['Spain'].shape[0]))
243 dimension: 300

所以数据是300维的。

2.2 PCA

利用PCA算法将上述300维的数据转换为2维数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def compute_pca(X,n_components=2):
"""
Input:
X: of dimension (m,n) where each row corresponds to a word vector
n_components: Number of components you want to keep.
Output:
X_reduced: data transformed in 2 dims/columns + regenerated original data
"""

## 对数据按列去中心化
X_demeaned = X - np.mean(X, axis=0)

## 计算协方差矩阵
covariance_matrix = np.cov(X_demeaned, rowvar=False)

## 计算协方差矩阵的特征值和特征向量
eigen_vals, eigen_vecs = np.linalg.eigh(covariance_matrix, UPLO='L')

## 对特征值按从大到小排序
idx_sorted_decreasing = np.argsort(eigen_vals)[::-1]
eigen_vals_sorted = eigen_vals[idx_sorted_decreasing]
eigen_vecs_sorted = eigen_vecs[:, idx_sorted_decreasing]

## 选择前n个特征向量来对数据进行降维
eigen_vecs_subset = eigen_vecs_sorted[:, 0:n_components]
X_reduced = np.dot(eigen_vecs_subset.transpose(), X_demeaned.transpose()).transpose()

return X_reduced

3 利用PCA进行降维

首先来一个帮助函数来获取词向量矩阵:

1
2
3
4
5
6
7
8
9
10
def get_vectors(embeddings, word):
m = len(words)
X = np.zeros((1, 300))

for word in words:
emb = embeddings[word]
X = np.row_stack((X, emb))

X = X[1:, :] ## 最开始的一行零去掉
return X
获取需要降维的数据矩阵:
1
2
words = ['oil', 'gas', 'happy', 'sad', 'city', 'town','village', 'country', 'continent', 'petroleum', 'joyful']
X = get_vectors(word_embeddings, words)
利用PCA进行降维:
1
2
3
4
5
6
result = compute_pca(X, 2)

plt.scatter(result[:, 0], result[:, 1])
for i, word in enumerate(words):
plt.annotate(word, xy=(result[i, 0] - 0.05, result[i, 1] + 0.1))
plt.show()

从图中可以分析得出, 'gas', 'oil' 和 'petroleum' 属于同一类,'sad', 'joyful' 和 'happy' 为一类,其他的聚集为一类。