点击量:1869
一、降维(Dimensionality Reduction)
我们知道在实际场景中,很多特征向量之间都是有强相关性的,比如有两个特征分别用英尺和平方米来丈量房屋的面积大小,那么这两组数据就 是冗余的(为什么会出现这么明显的冗余?因为在实际场景中会有几百甚至是上千的特征,很难判断两个特征之间是否是冗余的。),我们完全可以使用一个一维的特征变量来表示房屋的面积大小,这就是降维。举个例子:
如上图所示,我们把原来的两个向量x1和x2降维到只是用一个向量z1来使用。更直观的,可以看一个三维降低到二维的例子:
我们可以发现三维空间里离散的点被映射到了一个二维空间平面之中。
那么为什么要降维呢?
二、主成分分析(Principal Component Analysis)
1.PCA的数学表达
在介绍PCA的计算方法和原理之前,我们先了解下PCA主要做的事情是什么,并且用数学语言把它表达出来。看个例子:
这个例子是把二维的数据降低到一维,它所做的事情就是:找到一条直线(图中红色的直线,也就是向量z),使得各个样本点到这条直线的垂直距离(上图蓝色线段的长度,也被称为投影误差)之和最小。这个乍一看有点像线性回归啊,但两者还是有很大差别的,线性回归求得是y-x的值,而这里是向量的投影误差。再者说,两者所表达的数学含义是完全不一样的,一个是特征数据之间的运算,而另一个则是预测值与真实值之间的运算。具体差别如下图所示,一目了然(左边是线性回归,右边是PCA):
2.PCA算法的具体实现
$$\sum = \frac{1}{2}\sum_{i=1}^{n}\left ( x^{\left ( i \right )} \right )\left( x^{\left ( i \right )} \right )^{T}$$
注意,这个公式最左边的符号并不是求和符号,而表示协方差矩阵,一般被读成sigma。
在MATLAB/Octave中可以使用如下代码计算出C的特征向量(基于奇异值分解):
1 |
[U,S,V] = svd(Sigma); |
当然我们也可以使用eig函数,这是一个基于特征值分解来求解特征向量的函数,结果都是一样的。
$$Z(m*k) = X(m*n) \cdot U_{reduce}(n*k)$$
3.PCA的数学原理
根据第一部分对PCA的数学表达描述:PCA的主要目标就是找到这样一个k维空间,使得原始数据投影到这个空间后的分布的方差最大化!。参照这个目标,建立数学表达式,然后一步一步进行推导、求解。具体的数学推导和证明比较复杂,可以参考下面的几篇文章:
1.主成分分析(Principal components analysis)-最大方差解释
2.PCA的数学原理
3.线性代数之主成分分析(PCA)算法
涉及到基础的线性代数的知识可以参考:
4.特征值和特征向量
5.协方差矩阵
6.如何通俗易懂地解释「协方差」与「相关系数」的概念?
二、PCA的使用(Applying PCA)
(图片出处)
如上图所示(左中右分别称为图一图二图三),图一中的蓝色的点是二维的原始数据,经过PCA降维之后变成了图二中的一维数据(y轴=0),那么重构(还原)就意味着要把图二中的一维数据投影在图一的直线Z上,这样就能得到还原后的二维数据,结果如图三所示,所有的点都在直线Z上。我们可以发现最终还原得到的数据和真实值之间是有略微差异的,这部分差异就是降维后丢失掉的数据。
根据上面的介绍我们可以得出重构之后的数据为:
$$X_{approx}(m*n) = Z(m*k) \cdot U_{reduce}^{T}(k*n)$$
根据经验我们可以通过如下公式来选择k的值,也就是说要找到最小的k使得Loss<=0.01即可。
$$Loss = \frac{\frac{1}{m}\sum_{i=1}^{m}\left \| x^{\left ( i \right )} - x_{approx}^{\left ( i \right )} \right \|^{2}}{\frac{1}{m}\sum_{i=1}^{m}\left \| x^{\left ( i \right )} \right \|^{2}}<= 0.01$$
上面的公式中:
分子表示:平均投影误差的平方(Average squared projection error),其实就是原始值和重构值之间差的平方的平均值。
分母表示:原始数据的总变差(Total varia1on in the data)
这个公式所表达的意思就是:99%的差异性被保留了(我个人觉得可以简单理解为:降维后的数据损失率)。这个值当然是越小越好,如果是0则表示没有损失,一般可以是1%,5%,15%等等,这些都是典型的取值范围。那么这个算法实现起来就非常简单了,不断尝试不同的K值,当损失率小于某个值p时,则输出k,跳出循环。
这里还有一个小技巧可以提高计算效率,因为这个算法每次都要把两个矩阵数据重新计算一遍,当样本数据量很大时,计算会很慢。实际上,我们之前通过奇异值分解(svd函数)得到的三个矩阵存在着如下关系:$$[U,S,V] = svd(A)$$ 则有: $$A = U*S*V’$$其中第二个矩阵S是很特殊的,它是一个对角线矩阵,也就是说除了对角线以外的元素都为0,大致形式是这样的:$$S = \begin{bmatrix}
s_{11} & 0 & … & 0 & \\
0 & s_{22}&… & 0 & \\
0 & 0 & s_{33} & 0 & \\
0 & 0 & … & 0 & \\
0 & 0 & … & s_{nn}&
\end{bmatrix}$$
而且可以证明的是:
$$Loss = 1 – \frac{\sum_{i=1}^{k}S_{ii}}{\sum_{i=1}^{m}S_{ii}}$$
这样我们就可以直接使用矩阵S来计算Loss而不必每次循环都拿原始样本数据来计算了。
三、PCA使用的建议(Advice for applying PCA)
这部分内容只记录两点有价值的信息:
课后编程作业已经上传至本人GitHub,如有需要可以参考,但请遵守课堂准则,不要抄袭。