主成分分析(Principal Component Analysis, PCA)是一种常用的数据分析方法。PCA通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取数据的主要特征分量,常用于高维数据的降维。
本文从PCA的目的、思想、原理背后的含义出发,试图清晰地解决几个问题:
- 为什么用PCA
- 怎么用PCA
- 为什么这么用PCA
1 问题背景
所谓数据分析,我个人觉得就是在大量数据中找到数据背后隐藏的规律。可以说,机器学习包括深度学习的目的也就在此。
现在我有某个淘宝店2012年全年的流量及交易情况,我想要拿这个数据集来做点事情。这组数据可以看成一组记录的集合,其中每一天的数据是一条记录,格式如下:
我们得到一组记录,每条记录可以被表示为一个六维向量,这样的一条五维数据看起来是这个样子的:
(2019/2/3,100,100,240,235,70000)
我们可以拿这个数据集来进行分析,预测在下一个季度该淘宝店的销售额,帮助这家淘宝店决定什么时候多进货。
然而,我们在面对这组数据时,我们会发现,下单数和成交数,概念虽然不一样,但其实差不多,毕竟绝大部分人下单了就不会退了。所以,我们在分析数据时,如果把其中一个去掉,几乎不会影响我们的分析结果。
我们当然可以还是对这一组六维向量进行分析和挖掘,毕竟,下单数和成交数还是不同的概念,表达的信息也有所不同。不过我们知道,很多机器学习算法的复杂度和数据的维数有着密切关系,甚至与维数呈指数级关联。当然,这里区区六维的数据,也许还无所谓,但是实际机器学习中处理成千上万甚至几十万维的情况也并不罕见,在这种情况下,机器学习的资源消耗是不可接受的。
这时候,我介绍一个概念:数据高维导致的维度灾难。
数据的高维导致所谓的维灾 ,本质上是说数据的关键特性主要分布在少量维度(属性)上,其分布于所有维度张成空间的概率接近于0。简单地说,就是真正能看出这组数据规律的重要特性,只集中在个别几个属性上,大部分属性都是没用的,都是一个干扰项。
维度灾难会导致两个问题:
- 难以得到结论。流行的Euclidean距离平等地对待每一个属性,而不加区分,同时是一种pairwise的距离,故不能真实的描述出数据之间的关系和分布特性。简单地说,因为我们把每一个属性都平等的对待,都平等地进行分析,所以那极少数最能代表数据特征的属性,被淹没在了大量无用的属性中。
- 时间复杂度极高。不考虑那些没用的属性对我们找出数据规律的影响,就算我们找得到规律,也要花费很大的功夫。因为我们把每一个属性都平等的对待,都平等地进行分析。而分析,就代表着我们要对每一个属性进行计算。要知道,在现实应用中,一个数据集有上千万的属性(维度)是非常常见的。
因此,我们要对一组高维度数据进行分析,最好找出那些最具代表性的维度,来减少我们要分析的维度。请注意,我们不是选出,而是找出最具代表性的维度。
还是拿淘宝店的例子来说,下单数和成交数是不同的概念,虽然两者很接近,但是细微的差别还是显示了这家店的特征,比如说,如果下单数比成交数高了100单,那么就说明这家店的货可能有问题,有100个人退货。所以,单纯去掉其中的一个维度,选择另一个,是会出问题的。那么,我们是不是可以创造一个维度,这个维度即显示了下单数的特征,又显示了成交数的特征呢?我们说”找出维度”,其实就是这个意思。
1.2 简单实例
现在,我们有这么一组二维数据 (虽然二维数据没必要做降维,但是超过三维的数据画不出来,所以以二维数据为例)。
这组二维数据的维度可以由横坐标和纵坐标所代表,因此每个观测值都有相应于这两个坐标轴的两个坐标值。
我们看到,这些数据形成一个椭圆形状的点阵,这个椭圆有一个长轴和一个短轴。在短轴方向上,数据变化很少。短轴上的数据都差不多集中在一个部分,说明每一个数据在这个方向上的变化不大。所以,即使我们把这个椭圆沿着短轴方向往里压,压成一条直线,还是能很好地表示这组数据的变化趋势。这样,由二维到一维的降维就自然完成了。
这个长轴的方向叫做主成分方向,n个数据在主成分方向的离散程度最大,数据在主成分方向上的投影代表了原始数据的绝大部分信息,即使不考虑短轴,信息损失也不多。
我们可以看到,椭圆的长短轴相差得越大,损失的信息就越少。
问题是,我们怎么找到这个主成分方向呢?
2 矩阵乘法的本质——基变换(向量缩放)
找到主成分方向是我们最终的目标,我们需要对这个问题进行分析、细化、分解,从而可以将这个问题形式化为数学问题。在进行分析之前,我们首先得回顾一下线性代数的知识。我们回顾线性代数的知识,是为了解决一个问题:怎么把这个椭圆沿着短轴方向往里压,压成一条直线呢?这就涉及到线性变换的问题。
这里直接给出结论:矩阵乘法的实质,就是线性变换。把这些数据压成一条直线,实际上就是把这些数据进行一个特定的拉伸缩放,数学化就是乘上一个特定的矩阵。下面进行简单的阐述。
向量实际上是由基向量组成的,任何向量都可以分解成基向量的线性组合,我们一般都默认基向量→i=(1,0),→j=(0,1),向量A=(3,2),其实是A=3→i+2→j,如图
但是,其实只要线性无关,任何一对向量都可以成为一组基,如图就是另一组基。
线性变换是什么?
线性变换实际上是对整个空间的拉伸缩放,而向量的变换只是整个空间变换的体现。我认为,我们的宇宙由一组规则组成,万物从一片寂静构成这个世界,都只是在依照这一组规则。这个想法套用在线性代数里,可以这么想:整个线性空间是由一组基构成的,线性空间实际上是基的另一种表现形式。那么,所谓线性空间的变换,实际上就是基的变换。
之前我们说过,向量实际上是由基向量组成的,任何向量都可以分解成基向量的线性组合,向量A=(3,2)可以表示为:
(1001)(32)=(32)
我们看到,就是基向量与(3,2)的内积运算。可以这样理解:(3,2)是某个绝对标尺,表示对某个事物属性的绝对表示,这个表示不受任何外部因素的影响。而为了把这个标尺表现在一个线性空间中,我们需要对这个标尺做一个变换,使得这个标尺能够合理地出现在这个线性空间里,而这个变换,就是与基向量的内积。
下面是一个形象的例子,描述了(−1,2)在基向量(3,1),(1,2)作用下的变换:
如果我们把→i=(1,0),→j=(0,1)这个基向量逆时针旋转45°,那么此时,→i=(1√2,1√2)→j=(−1√2,1√2)就作为了基向量,此时(3,2)在哪儿了呢?我们只要仍然把基向量与(3,2)相乘,就可以了:
(1/√21/√2−1/√21/√2)(32)=(5/√2−1/√2)
可以画出来看看,这个结果确实是(3,2)旋转45°的结果。
所以,我们可以看到,矩阵乘法的实质,就是线性变换。详细的内容,可以转到线性代数的本质 - 03 - 矩阵与线性变换(“线性代数的本质”系列非常非常棒,强烈推荐看一遍)。
这和我们的降维有什么关系呢?接着看。
假设我有三个值,(1,1),(2,2),(3,3),组成一个数据矩阵,行代表维度,列代表样本数,这里表示二维三个样本。
(123123)
这三个值在y=x这条直线上,所以这条直线就是我们的主成分方向。我们的目标就是把我们的二维空间X,Y变换到一维空间里,这个一维空间就是y=x这条直线。我们就这样表示:
(1/√21/√2−1/√21/√2)(123123)=(2/√24/√26/√2000)
因为第二行都是0,无意义,所以我们把第二行去掉,原本的二维数据就变成了一个一维的数据。
3 方差
我们在上文说,我们要找到一个方向,在这个方向上,数据散得最大,而分散程度,可以用方差来表示。一个维度的方差是:
Var(a)=1mm∑i=1(ai−μ)2
其中,a是一个维度,ai是指这个维度下的第i个数据值,μ是指这个维度下所有数据值的平均值。
于是上面的问题被形式化表述为:寻找一个一维基,使得所有数据变换为这个基上的坐标表示后,方差值最大。
4 协方差
对于上面二维降成一维的问题来说,找到那个使得方差最大的方向就可以了。不过对于更高维,我们没办法只考虑使得方差最大,比如说我要把考虑三维降到二维,我要找到两个主成分方向,这时候几乎不可能同时最大化两个方差。
所以我们换一种思路,从直观上说,让两个维度尽可能表示更多的原始信息,我们是不希望它们之间存在(线性)相关性的,因为相关性意味着两个维度不是完全独立,必然存在重复表示的信息。所以,我们要做的是,找出两个相关性为0的维度。
数学上,可以用协方差来表示两个属性的相关性,两个属性a, b的协方差为:
Cov(a,b)=1mm∑i=1(ai−μa)(bi−μb)
协方差为正时,说明X和Y是正相关关系;协方差为负时,说明X和Y是负相关关系;协方差为0时,说明X和Y是相互独立。Cov(X,X)就是X的方差。当样本是n维数据时,它们的协方差实际上是协方差矩阵(对称方阵)。
例如,对于2维数据(x,y),计算它的协方差就是:
Cov(X,Y)=[Cov(x,x)Cov(x,y)Cov(y,x)Cov(y,y)]
我们可以看到,协方差矩阵的主对角线就是x、y的方差,方差与协方差被统一在一个协方差矩阵里了。
所以,我们寻找主成分方向的问题,变成了下面这个问题:将一组N维向量降为K维(K大于0,小于N),其目标是选择K个单位(模为1)正交基,使得原始数据变换到这组基上后,各字段两两间协方差为0,而字段的方差则尽可能大(在正交的约束下,取最大的K个方差)。
这时候,我们来做一个神奇的操作,我们把每一个维度的每一个数值都减去这个维度的均值(期望)。这样之后,每一个维度的期望都是0,那么协方差就变成了:
Cov(a,b)=1mm∑i=1aibi
协方差矩阵就是:
(1m∑mi=1a2i1m∑mi=1aibi1m∑mi=1aibi1m∑mi=1b2i)
我们把a、b两个维度的数据放在一个,形成一个数据矩阵X:
X=(a1a2⋯amb1b2⋯bm)
最神奇的事情发生了,我们就会发现,协方差矩阵实际上就等于数据矩阵的内积:
1mXX⊤=(1m∑mi=1a2i1m∑mi=1aibi1m∑mi=1aibi1m∑mi=1b2i)
4.1 协方差矩阵对角化
我们接下来要做的,就是把除主对角线以外的元素化为0,并且将对角线上的元素从大到小排列,选择几个方差最大的元素,作为我们的主成分方向。
由第2部分的基变换,我们知道,找出主成分方向,实际上就是把数据所在的空间进行伸缩扭曲,也就是一个矩阵乘法。所以,我们的目的其实是找出一个P,使得Y=PX的协方差除对角线外的元素都是0。那么怎么求P呢?我们来推导一下。
假设Y的协方差矩阵是D,X的协方差矩阵是C,那么:
D=1mYYT=1m(PX)(PX)T=1mPXXTPT=P(1mXXT)PT=PCPT
这是不是很熟悉?看看特征向量与特征值的定义:
设A是n阶矩阵,如果数λ和n维非零向量x使关系式Ax=λx成立,那么,这样的数λ称为矩阵A的特征值,非零向量x称为A的对应于特征值λ的特征向量。
我们把这个式子挪一挪,则有:
λ=xTAx
由上文知道,协方差矩阵C是一个是对称矩阵,在线性代数上,实对称矩阵有一系列非常好的性质:
1)实对称矩阵不同特征值对应的特征向量必然正交。
2)设特征向量λ重数为r,则必然存在r个线性无关的特征向量对应于λ,因此可以将这r个特征向量单位正交化。
由上面两条可知,一个n行n列的实对称矩阵一定可以找到n个单位正交特征向量,设这n个特征向量为e1,e2,⋯,en我们将其按列组成矩阵:
E=(e1 e2 …en)
则对协方差矩阵C有如下结论:
ETCE=Λ=(λ1λ2⋱λn)
其中,Λ的对角元素就是各特征向量对应的特征值。
到这里,我们发现我们已经找到了需要的矩阵P:
P=ET
P是协方差矩阵的特征向量单位化后按行排列出的矩阵,其中每一行都是C的一个特征向量。Λ则是将除对角线以外所有元素化为0后的结果。如果设P按照Λ中特征值的从大到小,将特征向量从上到下排列,则用P的前K行组成的矩阵乘以原始数据矩阵X,就得到了我们需要的降维后的数据矩阵Y。
算法步骤总结
设有m条n维数据。
1)将原始数据按列组成n行m列矩阵X
2)将X的每一行(代表一个属性字段)进行零均值化,即减去这一行的均值
3)求出协方差矩阵C=1mXXT
4)求出协方差矩阵的特征值及对应的特征向量
5)将特征向量按对应特征值大小从上到下按行排列成矩阵,取前k行组成矩阵P
6)Y=PX即为降维到k维后的数据
Reference
PCA的数学原理(这篇博文非常棒,简单易懂地介绍了PCA”是什么”(算法思想)、”从哪儿来”(算法基础)、”到哪儿去”(目的)的问题。)
- 本文作者: YA
- 本文链接: http://www.yuuuuang.com/2019/05/10/机器学习-主成分分析/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!