文章目录
算法目标预处理算法过程逆过程主成分数kkk的选取应用算法目标
PCA的目标就是实现维数约减,即在尽可能保留信息的同时减少数据的维度。通过维数约减,我们可以实现数据压缩节省存储空间,还能加快一些算法的运算速度。
具体来讲,PCA算法要在高维空间中找到一个低维度的面(子空间),使高维空间中的点到自身投影到低维子空间的对应点之间的距离之和(也称投影误差)最小。下面是一些简单的例子,它们可以被可视化,分别是从二维平面投影到一条直线和从三维空间投影到一张平面。
预处理
首先在运行PCA算法之前对数据进行特征缩放与均值归一化,使所有数据均值为0且取值范围相近,这将有利于我们找到投影子空间。实施过程也很简单,对于每一维特征值,先求出均值,然后减去均值,再除以方差或二分之一极差。
算法过程
假设我们想把nnn维的数据降低到kkk维。
首先,求出协方差矩阵Σ\SigmaΣ
Σ=1m∑i=1m(x(i))(x(i))T\Sigma=\frac{1}{m}\sum_{i=1}^m(x^{(i)})(x^{(i)})^T Σ=m1i=1∑m(x(i))(x(i))T
若定义样本矩阵为
X=[−(x(1))T−−(x(2))T−⋮−(x(m))T−]X=\left[\begin{matrix} -(x^{(1)})^T-\\ -(x^{(2)})^T-\\ \vdots\\ -(x^{(m)})^T-\\ \end{matrix}\right] X=⎣⎢⎢⎢⎡−(x(1))T−−(x(2))T−⋮−(x(m))T−⎦⎥⎥⎥⎤
则上面的求和式可直接写为
Σ=1mXTX\Sigma=\frac{1}{m}X^TX Σ=m1XTX
接下来,求解该矩阵的特征向量,在matlab中,可以使用svd
函数,进行奇异值分解,对于协方差矩阵该函数的结果就是它的特征向量。具体的使用方式为
[U,S,V]=svd(Sigma);
取出n×nn\times nn×n矩阵U
中的前kkk列,就得到了我们的kkk个向量,它们张开的kkk维子空间就是我们要投影的空间,我们把这前kkk列提取出来后构成的矩阵称为UrU_rUr
要求样本向量在这个子空间的投影,则将UrU_rUr转置(k×nk\times nk×n),乘以样本的特征列向量x⃗\vec{x}x(n×1n\times 1n×1),得到降维后的特征向量z⃗=UrTx⃗\vec{z}=U_r^T\vec{x}z=UrTx(k×1k\times 1k×1)。对于上面定义的样本矩阵,则是
Z=XUrZ=XU_r Z=XUr
证明吴恩达说难,不给我讲,我也不急着学。
逆过程
逆过程不是完全还原,还原后的数据跟使用PCA之前的数据是有略微不同的,在nnn维空间中看,还原后的数据点都落在UrU_rUr中的向量张开的kkk维子空间里(比如2D压缩到1D再还原,还原后的点都在同一直线上,而不会是压缩前那样在直线左右略有误差的情况)。公式为
x⃗approx=Urz⃗\vec{x}_{\text{approx}}=U_r\vec{z} xapprox=Urz
推广到mmm行(即每行一个样本)的矩阵上则是
Xapprox=ZUrTX_\text{approx}=ZU_r^T Xapprox=ZUrT
主成分数kkk的选取
定义平均平方投影误差(Average Squared Projection Error)
1m∑i=1m∣∣x(i)−xapprox(i)∣∣2\frac{1}{m}\sum_{i=1}^m||x^{(i)}-x_\text{approx}^{(i)}||^2 m1i=1∑m∣∣x(i)−xapprox(i)∣∣2即PCA算法希望最小化的代价函数。
再定义总变差(Total Variation)
1m∑i=1m∣∣x(i)∣∣2\frac{1}{m}\sum_{i=1}^m||x^{(i)}||^2 m1i=1∑m∣∣x(i)∣∣2衡量样本长度的平均值。
一般而言,我们希望选择的kkk使得
1m∑i=1m∣∣x(i)−xapprox(i)∣∣21m∑i=1m∣∣x(i)∣∣2≤0.01\frac{\frac{1}{m}\sum_{i=1}^m||x^{(i)}-x_\text{approx}^{(i)}||^2}{\frac{1}{m}\sum_{i=1}^m||x^{(i)}||^2}\le0.01 m1∑i=1m∣∣x(i)∣∣2m1∑i=1m∣∣x(i)−xapprox(i)∣∣2≤0.01即保存99%99\%99%的差异性(英文是variance,意义不好理解但明白99%99\%99%对应0.010.010.01即可)。
上面这个式子计算比较复杂,我们需要把还原后的数据也计算出来。一种更简单的计算方法是利用svd
返回的第二个矩阵S
,这是一个对角阵,可以证明
1m∑i=1m∣∣x(i)−xapprox(i)∣∣21m∑i=1m∣∣x(i)∣∣2=1−∑i=1kSii∑i=1nSii\frac{\frac{1}{m}\sum_{i=1}^m||x^{(i)}-x_\text{approx}^{(i)}||^2}{\frac{1}{m}\sum_{i=1}^m||x^{(i)}||^2}= 1-\frac{\sum_{i=1}^kS_{ii}}{\sum_{i=1}^nS_{ii}} m1∑i=1m∣∣x(i)∣∣2m1∑i=1m∣∣x(i)−xapprox(i)∣∣2=1−∑i=1nSii∑i=1kSii所以一个等价的判断是
∑i=1kSii∑i=1nSii≥0.99\frac{\sum_{i=1}^kS_{ii}}{\sum_{i=1}^nS_{ii}}\ge0.99 ∑i=1nSii∑i=1kSii≥0.99
这样,要找到一个合适的kkk,只需要调用一次svd
函数,然后在S
矩阵的对角线上遍历求和,直到满足上面的等式为止。
相应地,即使事先已经选定了kkk值,你也可以通过上面的式子来衡量PCA的性能。
应用
第一个就是节省存储空间了,这个很显然。
第二个则是对其他机器学习算法中的特征值向量(如数字识别中图片的像素点灰度)进行维数约减,降低特征值维数提升算法运行速度。注意应该对训练集数据使用PCA得到UrU_rUr,不能包含验证集和测试集。
三则是可视化,对于一些维数较高的数据,我们无法将其可视化。但是将它们降维到2D或者3D之后,我们就可以在一张纸上将数据形象地展示出来了。
不建议的应用:将PCA用于防止过拟合。看起来PCA能减少数据的维数(即特征值数目),在机器学习的改进方法中讲到过,似乎是个防止过拟合的好方法。因为PCA在运算时并不会考虑与原数据的拟合程度(因为我们只传入的特征值x(i)x^{(i)}x(i),没有使用y(i)y^{(i)}y(i)),使得PCA更容易丢失原数据中的信息。虽然PCA可能会得到一个好的结果,但相较而言正则化是更加稳妥而有效的解决方案。
通常,不建议一上来就将PCA加入到你的机器学习算法中,当算法运行速度太慢或者占用空间太大的时候,我们再考虑PCA。