有时我们的数据中包括很多属性,有些是没意义的,有些是重复的,有些组合后意义更明显。此时,我们需要简化属性节约算力,去噪,去冗余,求取更典型的属性,同时又希望不损失数据本身的意义。
 主成分分析(Principal Component Analysis,PCA),是一种统计方法。通过正交变换将一组可能存在相关性的变量转换为一组线性不相关的变量,转换后的这组变量叫主成分。数据分析中常使用PCA给数据降维,它能在指定的损失范围内最大的简化属性。本篇将介绍PCA的原理,Python实现及应用场景。

1. 特征值与特征向量

 PCA的核心算法是:协方差矩阵和特征值分解,先来看看特征值分解相关的知识点。

1) 基

 我们无时无刻不用到基,十进制就是以10为基底的描述,一个小时60分钟,60就是基底,再说复杂一点,傅里叶变换中,余弦(或正弦)波是基底,小波变换中小波是基底,可以把它理解成一种基本的参照,比如1公斤,1海里,1升…
 一个点在宇宙中本没有坐标,但只要定义了基,它就能被描述。任何的东西都可以借助基来描述。但不管使用什么样的基,上层的实体(逻辑关系)是不变的。比如,珠峰的高度=8848米=8.848千米,实体(高度)并没有改变,只是换了一种表述的方式。这里单位千米对应的就是基底,而数值对应的是坐标,描述的是向线段。

2) 坐标系

 我们可以把不同坐标理解成不同的视角,比如两人看同一场电影,A坐在第一排最左边,B坐在最后一排的正中间。他们看到的是同一个等腰直角三角形(人脑会自动对三维空间做一些校正,所以真实世界中我们感觉变形并不明显)。但如果脱离了屏幕,单看左边的三角形,会难以描述它。而B的视角是直角坐标系,且三角形的两边与坐标轴垂直。同样是把它拉长的操作,在B视角延坐标轴的缩放即可,它比A视角描述和计算都更容易。不过无论坐在哪儿看到的都是同一部电影。

 为了简化问题,也可以A移到B的视角,也就是转换的是它的基,具体方法是线性变换,也就是乘矩阵。下图是在坐标系中的视角变换。

3) 矩阵相乘的意义

两个矩阵相乘的意义是将右边矩阵中的每一列列向量变换到左边矩阵中每一行行向量为基所表示的空间中去。图形还是同一个图形,只是变了视角。将结果乘它的逆矩阵又变回了原来的坐标,于是,可以把复杂的变换拆分成:变视角->简单变换->视角变回去。

4) 特征值分解

先来看看特征值,特征向量到底长什么样?

i. 代码

import numpy as np
a = np.array([[2, -1], [-1, 2]]) # 矩阵
print np.linalg.eig(a) # 特征值分解

ii. 运行结果

(array([ 3.,  1.]), 
array([[ 0.70710678,  0.70710678],
       [-0.70710678,  0.70710678]]))

iii. 分析
 运行结果的第一个数组是特征值,它是一个对角阵,所以只给出了对角线上的数据,第二个数组是特征矩阵。
 它将矩阵A的变换拆分成了:旋转->拉伸->再转回去



 其中P是负责旋转到正交的坐标系(各轴相互垂直)的“特征向量”,而 则是负责拉伸的“特征值”,它在一个方向上拉伸了3倍,另一个方向拉伸了1倍。拉抻值大的,就是它的主方向。
 也可以把乘以特征向量当成正交分解。从物理角度上讲,是将一个力分解为Fx和Fy两个相互垂直的分力的方法,叫作力的正交分解。在这里是把矩阵分解成由特征向量指定的垂直(正交)的坐标系中的分量。

2. 协方差矩阵

 协方差表达的是属性与属性间的相关程度,就是一个值变时,另一个值发生多大变化。
 公式是Cov[X,y]=E((X-E(X))(Y-E(Y))),E是期望值(重心),这里先简单看作均值(即每种可能出现概率一样),每个X,Y都会多少偏离均值,当X和Y偏离方向总是一致是它们正相关,总是相反时负相关,不一定时无关。
协方差的值也会由于具体属性值的大小而受影响,相关系数更进一步,它是用X、Y的协方差除以X的标准差和Y的标准差,因此我们也常用相关系数来判断特征之间的关系。
 协方差矩阵也有它解决不了的问题,它能判断两两属性间的关系,但遇到A,B共同决定C时就无能为力了,而且它只能表述线性关系,对于非线性也视为不相关(这就是为什么不线性相关的属性却不一定相互独立)
 PCA就是对协方差矩阵做特征值分解。

3. PCA步骤

  • 去除平均值
    先求每个属性的均值,然后将整个矩阵减去均值,为计算协方差做准备。
  • 计算协方差矩阵
    协方差矩阵是度量维度间的差异,而非样本间差异。协方差矩阵的主对角线上的元素是各个维度上的方差
  • 计算协方差矩阵的特征值和特征向量
    对角化,使得除对角线外,其它元素为0,将能量归于主要方向。
  • 将特征值排序
  • 保留最大的N个特征值
  • 将数据转换到特征向量构建的新空间中

4. 程序

from numpy import *
import matplotlib.pyplot as plt

def pca(dataMat, topNfeat=9999999): # 只何留特征值最大的前topNfeat个特征
    meanVals = mean(dataMat, axis=0) # 均值
    meanRemoved = dataMat - meanVals
    covMat = cov(meanRemoved, rowvar=0) # 协方差
    eigVals,eigVects=linalg.eig(mat(covMat)) # 计算特征值、特征向量
    eigValInd = argsort(eigVals) # 从小到大排序,返回索引值数组
    eigValInd = eigValInd[:-(topNfeat+1):-1] # 保留后topNfeat个,然后调转先后
    fig = plt.figure(0)
    plt.plot(eigVals) # 特征值绘图,看看前几个最重要
    redEigVects = eigVects[:,eigValInd] # 按eigValInd排序和去掉列
    print(redEigVects)
    lowDDataMat = meanRemoved * redEigVects # 转向新空间,行数不变,列按参数减少
    reconMat = (lowDDataMat * redEigVects.T) + meanVals # 再转回旧空间
    return lowDDataMat, reconMat

5. 程序分析

1) 特征值

 特征值分解之后,特征值越大说明该方向上的变化越大,越重要,反之不重要,则可以去掉,此方法可用于降维。如果对50维数据求特征值,发现只有5个值较大,其它都非常小,则说明只需要考虑这5个综合因素即可。
 分解将向量拆分成正交的线性组合,正交也保证了“综合因素”的相互独立。

2) 方差

 协方差矩阵的对角线就是各个特征的方差,方差阐释了数据的发散程度,在几个维度中,某一维方差最大,说明数据在该轴上分布得越广,该轴就是覆盖差异最大的坐标轴。具体应用比如:在聚类问题中,我们更希望最后汇聚成发散的几块,而不是团在一起。因此可以考虑以方差最大的方向分成几块,作为聚类的初始点。

3) 协方差

 协方差Cov(X,Y)=E((X-E(X)(Y-E(Y))),其中E为期望值, E(XY),就是XY乘积的均值,是两个变量总体误差的期望。如果把均值作为0,而上下波动的误差作为能量,则协方差就是能量的期望,协方差矩阵就是能量矩阵。它呈现的不是值的关系,而是变化的关系。具体应用比如:配置资产时,相关性高可能带来更高风险,选择独立的资产配置,或负相关的,可以对冲风险。

6. 使用

  • PCA一般用于多维数据,它可以把N维数据转到M维空间,比如50维变5维,运算量就少了很多。
  • PCA只是分析特征间的关系,与结果无关,可视为一种无监督学习。
  • 虽然转换后意义不够直观,但低维向量再乘特征向量的逆矩阵,还可以转回来。
  • 从协方差矩阵看各属性的相互关系, 启发得到一些重要属性。
  • 可取到特征值,通过其大小,判断信息量的多少。
  • 用PCA去噪的原理是,认为被去掉的那些小的特征值是噪差干扰导致。
  • 上例只为说明原理,实际应用中,一般直接调用sklearn库提供的PCA类


技术文章定时推送
请关注公众号:算法学习分享

posted on 2017-11-21 22:40  xieyan0811  阅读(58)  评论(0编辑  收藏  举报