最近频繁在论文中看到「PCA」的影子,所以今天决定好好把「PCA」的原理和算法过程弄清楚。
「PCA」是什么
PCA,又称主成分分析,英文全称「Principal Components Analysis」。维基百科上的解释是:「PCA」是一种分析、简化数据集的技术,经常用于减少数据集的维数,同时保持数据集中对方差贡献最大的特征。说得通俗一点,就是把数据集中重要的特征保存下来,把不重要的特征去除掉。 为什么要做这种事情呢?特征越多不是对分析问题更有帮助吗?确实,特征越多,涵盖的信息理论上会越多。但要注意一点,这个假设成立的前提是特征本身都彼此无关,并能描述事物的某些属性。如果由特征 A 可以推出特征 B,或者特征 B 所描述的属性与问题本身无关,或者特征 A 和特征 B 描述的是同一个特征,那么特征 B 是没有价值的。在机器学习里面,特征越多意味着需要更多的训练样本(否则容易 overfit ),但真实情况是,训练数据并不容易获取。基于以上种种,如果能构提取出特征的主要部分,那么,不仅数据将变得简单清晰,训练过程也会更快,效果理论上也会更好才是。
「PCA」算法过程
「PCA」的目标是把原来 n 维特征的数据压缩成 k 维特征。 接下来用一个例子说明「PCA」的执行流程(这个例子参考自文末链接主成分分析(Principal components analysis)-最大方差解释)。
假设我们得到 2 维数据如下: \[ Data=\begin{array}{c|lcr} x & y \\ \hline 2.5 & 2.4 \\ 0.5 & 0.7 \\ 2.2 & 2.9 \\ 1.9 & 2.2 \\ 3.1 & 3.0 \\ 2.3 & 2.7 \\ 2 & 1.6 \\ 1 & 1.1 \\ 1.5 & 1.6 \\ 1.1 & 0.9 \\ \end{array} \] 行代表样例,列代表特征,这里有 10 个样例,每个样例有两个特征。
step1 归一化样本数据
分别求出 x 和 y 的平均值,对于所有样本,都减去平均值。这里 x 的均值为 1.81,y 的均值为 1.91。归一化后得到: \[ Data=\begin{array}{c|lcr} x & y \\ \hline 0.69 & 0.49 \\ -1.31 & -1.21 \\ 0.39 & 0.99 \\ 0.09 & 0.29 \\ 1.29 & 1.09 \\ 0.49 & 0.79 \\ 0.19 & -0.31 \\ -0.81 & -0.81 \\ -0.31 & -0.31 \\ -0.71 & -1.01 \\ \end{array} \]
step2 求协方差矩阵
由于原样本中的特征是 2 维的,所以得到的协方差矩阵的维度是 \(2*2\) (关于协方差矩阵的求法,参见上一篇文章协方差矩阵)。这里省略过程,直接给出结果:
\(cov=\begin{bmatrix} 0.616555556 & 0.615444444 \\ 0.615444444 & 0.716555556 \end{bmatrix}\)
step3 求协方差矩阵的特征值和特征向量
由于协方差矩阵是对称矩阵,因此在数学计算上更加方便。关于矩阵如何求特征值和特征向量,下次再写一篇相关的文章。这里假设我们已经求出了特征值和特征向量:
\[ eigenvalues=\left( \begin{matrix} 0.490833989 \\ 1.28402771 \end{matrix} \right) \]
\[ eigenvectors=\left( \begin{matrix} -0.735178656 & -0.677873399 \\ 0.677873399 & -0.735178656 \end{matrix} \right) \]
上面是两个特征值,下面是对应的特征向量,特征值 0.0490833989 对应的特征向量为 \((-0.735178656, 0.677873399)^T\),这里的特征向量都为归一化后的向量。
step4 选取特征向量矩阵
将特征值按照从大到小的顺序排列,选择其中最大的 k 个,然后将其对应的 k 个特征向量分别作为列向量组成特征向量矩阵。由于这里特征值只有两个,我们选择较大的那个,也就是 1.28402771,得到的特征向量矩阵为: \[ \begin{bmatrix} -0.677873399 \\ -0.735178656 \end{bmatrix} \]
step5 将样本投影到特征矩阵上
假设样本数为 m,特征数为 n,归一化后的样本矩阵为 DataAdjust(m * n),协方差矩阵为 n * n,选取的 k 个特征向量组成的矩阵为 EigenVectors(n * k),则投影后得到的最终数据为: FinalData(m * k) = DataAdjust(m * n) * EigenVectors(n * k) 在本例中, \[ FinalData(m*k)=\begin{array}{c|lcr} x \\ \hline -0.82797 \\ 1.77758 \\ -0.992197494 \\ -0.27421 \\ -1.67580 \\ -0.91294 \\ 0.09910 \\ 1.14457 \\ 0.43804 \\ 1.22382 \\ \end{array} \] 这样,我们就将原始的 n 维特征数据变成了 k 维(本例中,是 2 维到 1 维)。
总结
讲到这,「PCA」的流程就基本结束了。 不过,总结之前还有个细节要交代。虽然 step1 的时候我们已经对数据做了归一化,让数据的特征值都平移到原点附近,但对不同特征之间方差差异较大的问题仍然没解决(比如:样本第一个特征是汽车速度「0~100」,第二个特征是汽车座位数「2~6」,那么很明显,第一个特征的方差比第二个大很多)。这个问题会导致方差较大的特征对样本起到主导作用。为了消除这种差异的方法,除了减去均值外,还需要除以各自的标准差,流程归纳如下:
- Let \(\mu = \frac{1}{m} \sum_{i=1}^m{x^{(i)}}\)
- Replace each \(x^{(i)} \text{with} \ x^{(i)}-\mu\)
- Let \(\sigma_{j}^2 = \frac{1}{m} \sum_{i}{({x_{j}^{(i)}})^2}\)
- Replace each \(x_j^{(i)} \text{with} \ \frac{x_j^{(i)}}{\sigma_j}\)
(注:\(x^{(i)}\) 代指每个样例)
PCA的总体流程为: 1. 样本归一化; 2. 求样本特征的协方差矩阵; 3. 选取 k 个最大的特征值; 4. 组成特征向量矩阵; 5. 将样本数据投影到特征向量矩阵上。
实际应用
在机器学习中,我们通过训练集计算出特征向量矩阵并降维,然后在降维后的训练集上进行训练。预测的时候,我们同样需要对测试集进行降维(要保证数据模型的统一),降维的方法是用训练集计算出来的特征向量矩阵与测试集的数据相乘,然后再对降维的测试数据进行预测评估。