机器学习之PCA算法

数据降维

数据对于算法工程师来说可以说是无限复杂的,而这个复杂我们是不可能预估的,聪明而又懒惰嗯数据科学家发明一种方法叫做降维,不管你有多少维,维就要处理20维,所以这就是数据降维的由来,本文会介绍一种非常普通且好使的数据降维的方法–PCA

数据降维是机器学习下比较热门的一个话题,在数据挖掘的领域我们尝试使用一组特征来描述我们的主体,但是如何具体的描述一个主体呢?需要多少维度呢? 例如我们想要描述一个人,除了年龄、性别是不是还有血压温度、好人坏人、脾气好坏等等。简直就是枚举不完,如果我们无脑的罗列,那这些特征是不是就太多了,用1w维描述一个人吗? 好吧,这个我们也不知道,但是有一点我们是知道的,就是太多了,这里可能对于某些人来说没有什么用,例如对于医疗大数据来说,他们更关心血压、体温。对于性格、交际可能不需要特别了解。那怎么办呢?这个就是本文要说的,我们要降低维度,保留下来我们更加关心的维度,丢掉一些次要信息。当然如果你是一个专家,你可以通过特征选择来解决这个问题,如果不行,那么就需要本文的方法了。

PCA

中文名字叫做主成分分析算法,非常直白,就是把主要的成分提取出来,然后去除相关性[^1]的方法。它通过线性变换将原始特征映射到其他维度中。降低维度说明的是表示用一个近似的向量表示元素数据。

y=Wxy=Wx

从上面的公式中能看出,xx是原始数据,yy是投影以后的向量,那么WW如何来求呢?我们称这个WW投影矩阵,如果WW知道了,那么我们这个算法就讲完了,嗯 太好了了,思路非常清晰。我们先来无脑的思考一个问题,我们有nndd维向量xx,我们想把dd组向量压缩一个向量x0x_0,如何做比较合适呢?如果使用均方误差作为衡量标准。

L(x0)=i=0nxx02L(x0) = \sum_{i=0}^{n} ||x-x_0||^2

显然,这个问题的最优解是不是当xx每组取均值就可以让上面这个损失最小。当然本着科学的理念我们还是要证明的。就是求梯度为0的状态被。

L(x0)=2(x0x)=0\nabla L(x_0)=2(x_0-x)=0

求解上面的方程,可以得出上面提到的结论。

当然这个太过于简单,我会表示成如下形式:

m=1ni=1nxim=\frac{1}{n} \sum_{i=1}^{n} x_i

x=m+aiex=m+a_ie

aia_i是标量,ee是单位向量。这个时候的误差函数为:

L(a,e)=i=1nm+aiexi2L(a,e)=\sum_{i=1}^{n} ||m+a_ie-x_i||^2

求损失函数的最小值,对aia_i求导,另整个偏导数为0

2eT(m+aiexi)=02e^T(m+a_ie-x_i)=0

aieTe=eT(xim)a_ie^Te=e^T(x_i-m)

因为eTe=1e^Te=1,所以

ai=eT(xim)a_i=e^T(x_i-m)


上面这个公式表达的含义是,样本均值和样本的方差的差对向量eTe^T做投影。现在就会有另一个问题eTe^T如何来确认?下面我们来引入一个散布矩阵[^2].我们稍后会用到。

S=i=1n(xim)(xim)TS=\sum_{i=1}^{n}(x_i-m)(x_i-m)^T

不难发现,散布矩阵实际上是协方差矩阵的n倍。协方差矩阵定义如下

Σ=1ni=1n(xim)(xim)T\Sigma=\frac{1}{n} \sum_{i=1}^{n}(x_i-m)(x_i-m)^T


好的,我们言归正传,将上面求的的aia_i带入下面的目标函数,可以得到关于ee的变量。

L(e)=i=1n(aie+mxi)T(aie+mxi)L(e)=\sum_{i=1}^{n} (a_ie+m-x_i)^T(a_ie+m-x_i)

=eTSe+i=1n(mxi)T(mxi)=-e^TSe+\sum_{i=1}^{n}(m-x_i)^T(m-x_i)

这里的S就是上面提到的散布矩阵哦。其中过程大家可以动手练练。

上面这公式我们发现,后半部分是和ee无关的,也就是我们可以当成常数了,那么我们将关注点放到ee上,ee是单位向量,隐含条件就是eTe=1e^Te=1,那么上面这个公式就能引入拉格朗日函数变成一个优化问题。

L(e,λ)=eTSe+λ(eTe1)L(e,\lambda)=-e^TSe+\lambda(e^Te-1)

求导并且等于0就能得到。

2Se+2λe=0Se=λe-2Se+2\lambda e=0 \\ Se=\lambda e

很明显,等式两边都有ee,且结果是相等的,那么λ\lambda是散布矩阵SS的特征值。ee是特征向量,再一次转化为矩阵的特征值和特征向量的问题。矩阵SS是半正定的[散布矩阵],因此一定是可以对角化的,并且所有特征值非负,对于任意的非0向量xx,有

xTSx=xT(i=1n(mxi)T(mxi))xx^TSx=x^T(\sum_{i=1}^{n}(m-x_i)^T(m-x_i))x

=i=1n(xT(mxi)T)(xT(mxi))>=0= \sum_{i=1}^{n}(x^T(m-x_i)^T)(x^T(m-x_i))>=0

我们这里需要最大化`e^Te`,上面已经提到过了,将Se=λeSe=\lambda e两边同时乘以一个eTe^T,会有如下公式

eTSe=λeeT=λe^TSe=\lambda ee^T=\lambda

λ\lambda为散布矩阵的最大特征值的时候,`e^TSe`具有最大值,目标函数具有最小值。而λ\lambda是散布矩阵的特征值,也就是我们仅仅需要对散布矩阵进行特征值和特征向量分解,然后按照我们的需求和从大到小的顺序求我们想要的维度即可。

算法流程

计算样本集合的均值向量,将所有的向量减去均值向量,这个操作成为白化
计算样本协方差矩阵
对协方差矩阵进行特征值分解,得到所有的特征值和特征向量
将特征值从大到小排序,保留最大的一部分特征值对应的特征向量,以他们为行,形成投影矩阵。

降维过程

将样本减去均值向量
左乘投影矩阵,得到降维后的矩阵

数据重构

数据重构根据投影后的数据重构原始向量,于向量投影的作用相反
输入向量左乘以投影矩阵
加上均值向量就可以得到重构后的矩阵。

代码实例

行万里路,不如来段代码,咱们看看代码是如何实现这一个过程的,当然咱们生成环境中是有很多开源的控价来实现这一个过程的。

# coding=utf-8
import numpy as np
data = np.array([[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]])

print "原始数据:"
print data
def zeroMean(dataMat):
    # 白化
    meanVal = np.mean(dataMat, axis=0)
    newData = dataMat - meanVal
    return newData, meanVal


newData, meanVal = zeroMean(data)
covMat = np.cov(data, rowvar=0)
# 提取特征值和特征向量
eigVals, eigVects = np.linalg.eig(np.mat(covMat))

print "特征值:"
print eigVals
print "特征向量:"
print eigVects

# 降低维度
k = 1 # 期望降低维度
eigValIndice = np.argsort(eigVals) # 从小到大排序
n_eigValIndice = eigValIndice[-1:-(k+1):-1] # 取值最大的k个下标
n_eigVect = eigVects[:, n_eigValIndice] # 取对应的k个特征向量
lowDataMat = newData*n_eigVect
print "低维度空间:"
print lowDataMat
print "重构数据:"
reconMat = (lowDataMat * n_eigVect.T) + meanVal
print reconMat



为了便于观看和学习,输出数据咱们就放到这里了。

python
原始数据:
[[2.5 2.4]
 [0.5 0.7]
 [2.2 2.9]
 [1.9 2.2]
 [3.1 3. ]
 [2.3 2.7]
 [2.  1.6]
 [1.  1.1]
 [1.5 1.6]
 [1.1 0.9]]
特征值:
[0.0490834  1.28402771]
特征向量:
[[-0.73517866 -0.6778734 ]
 [ 0.6778734  -0.73517866]]
低维度空间:
[[-0.82797019]
 [ 1.77758033]
 [-0.99219749]
 [-0.27421042]
 [-1.67580142]
 [-0.9129491 ]
 [ 0.09910944]
 [ 1.14457216]
 [ 0.43804614]
 [ 1.22382056]]
重构数据:
[[2.37125896 2.51870601]
 [0.60502558 0.60316089]
 [2.48258429 2.63944242]
 [1.99587995 2.11159364]
 [2.9459812  3.14201343]
 [2.42886391 2.58118069]
 [1.74281635 1.83713686]
 [1.03412498 1.06853498]
 [1.51306018 1.58795783]
 [0.9804046  1.01027325]]





## 进一步
根据上面对PCA的数学原理的解释,我们可以了解到一些PCA的能力和限制。PCA本质上是将方差最大的方向作为主要特征,并且在各个正交方向上将数据“离相关”,也就是让它们在不同正交方向上没有相关性。如果处理不相关特征,可以了解一些关于流行学习的知识。

**PCA也存在一些限制,例如它可以很好的解除线性相关,但是对于高阶相关性就没有办法了**

## 备注
1: 去除相关性是什么鬼?其实对于我们的大多数的机器学习算法来讲,都是假设我们的特征是独立的,不希望有些特征是相互影响的,所以主成分分析算法,还有一个左右就是将相关性的特征进行剥离,抽取最重要的特征。
2: 在统计学与概率论中,散布矩阵是一个矩阵,其每个元素是各个向量元素之间的协方差。是从标量随机变量到高维度随机向量的自然推广。
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×