PCA稿

2018-11-13  本文已影响0人  HAN_望向

首先我们明确一点:期望,方差,协方差都是描述数据总体分布的参数。

什么是协方差(covariance)?

在回答这个问题之前我们回忆一下方差(variance)的知识:

(从协方差、方差的英文我们可以理解到一个关注的是“变换、不同”,另一个关注的是“协同变化、互相不同”)

假设有一个向量x=(x_{1} ,x_{2} ...x_{m} )

在这里我想先讲一个m是什么:比如二维空间中有一堆点,m就是点的个数,即样本数。而这个向量x是指把这些点投影到x轴所得到的数值,以此类推,其他向量也是这m个点投影到其他轴后,投影得到的m个值所形成的一个向量。这里切忌的是:如果二维空间有一个点(3,5),不可以认为得到了一个向量(3,5),正确的理解是x1=(3, □,..., □m),x2=(5, □,..., □m)。这样在二维里只有这两个向量,没有第3个向量了。这样的表示方式跟数学里有很大不同,我也困扰了很久才get到。这是理解PCA的关键。

我们知道方差的公式是σ^2=\frac{\Sigma(x_{i} -μ)^2}{m},方差描述的是一个向量中各个元素的发散程度:越集中方差越小。

方差的数学表示为:var(X)=DX=E[(X-EX)(X-EX)]=E[(X-EX)^2],对于这个公式我们先不细讲,只许记住上面的几何意义即可。

协方差的定义为cov(X,Y)=E[(X-EX)(Y-EY)],此时我们已经可以发现如果X=Y,即cov(X,X)其实就是X的方差。

协方差是对两个随机变量(只有两个!)联合分布线性相关程度的一种度量。两个随机变量越线性相关,协方差越大;完全线性无关,协方差为零(即如果x与y正交,协方差为0)。(有此处可知:不相关可推导E(XY)=EXEY,我之前总觉得独立这个式子才成立)

这里补充一下正交为什么协方差为0?(可跳过)首先我们可以先了解下独立、正交、不相关的关系。独立→不相关,正交→不相关,反之不成立。

image

还想补充一下不相关的意义?(可跳过)。相关关系描述的是一系列点里有没有线性关系。概率里有个定义是相关系数,定义为:ρ=\frac{cov(X,Y)}{\sqrt{DX·DY} } 。如果点分布有绝对的线性关系,那么ρ=±1,+1代表成正比,如y=2x+1,ρ=-1代表成负比,如y=-3x+5。\vert ρ \vert <1代表点分布之间夹杂着曲线,比如点分布是一个圆。如果ρ=0,代表各个坐标轴之间没有任何关系,即比如二维坐标里的点是没有任何规律随便点的若干点。从这里我们也可以稍微理解下如果正交的话,任一垂直x轴上的一条线上可以随意点点,即(x_{0},\forall )

实际上我们计算方差的时候分母除以的是m-1,\hat{σ} ^2=\frac{\Sigma(x_{i} -\bar{x} )^2}{m-1},(因为如果去求方差和协方差,随机变量才是最理想的求解方式,而我们通过样本求解只是相当于近似值。比如我们通过样本求期望EX,对于离散数据来说其实是求\bar{x}。也可以理解随机变量是曲线,而样本是离散的。数学期望未知,而用\bar{x}代替,我们算出来的是统计方差,而不是真正的方差,-1是为了使算出来的方差来无偏估计原方差σ2。)。所以样本协方差其实求解过程是:若有x_{a}=(x_{a1} ,x_{a2} ...x_{an} )x_{b}=(x_{b1} ,x_{b2} ...x_{bn} )两个向量,则两个变量样本协方差为cov(x_{a} ,x_{b})=E[(Xa-EXa)(Xb-EXb)]=\frac{∑(x_{ai}−\bar{x}_{a})(x_{bi}−\bar{x}_{b})}{m-1}

样本:

通常在我们之前学习过程中习惯于把一个样本中各个属性写成一行的形式,像[姓名,身高,体重] 这样。但是这里因为我们是以轴为单位,最终是要降维的,所以我们按原来的思路形成矩阵后,实际上每一列才是我们关注的每个轴,每个维度,每个“真样本”。所以我们一共有n个真样本,第i个真样本表示为x_{·j} =[x_{1j},x_{2j},......,x_{nj} ]^T。所以我们得到的样本矩阵是shape=n*m的,也就是m才是样本,每个样本是以列为单位的。

样本X表示为X= \begin{bmatrix} \ x_{11} & x_{12} &... & x_{1m} \\[0.3em] \ x_{21} & ... & .&. \\[0.3em] \ .& ... & .&. \\[0.3em] \ x_{n1} & . &.& x_{nm} \end{bmatrix}

image

协方差矩阵(理解PCA的关键)

在此基础上,协方差矩阵是每两个变量(样本,竖列)两两组合的协方差形成的矩阵。

最终这个列向量组形成的协方差矩阵表示为:

Σ=E[(X−E[X])(X−E[X])^T ]=

Σ= \begin{bmatrix} \ cov(x_{1·} ,x_{1·})& cov(x_{1·} ,x_{2·}) &... & cov(x_{1·} ,x_{n·}) \\[0.3em] \ cov(x_{2·} ,x_{1·}) & ... & .&. \\[0.3em] \ .& ... & .&. \\[0.3em] \ cov(x_{n·} ,x_{1·}) & . &.&cov(x_{n·} ,x_{n·}) \end{bmatrix}

Σ= \frac{1}{m-1} \begin{bmatrix} \ ∑(x_{1j} −\bar{x}_{·1} ) (x_{1j} −\bar{x}_{·1}) & ∑(x_{1j} −\bar{x}_{1} ) (x_{2j} −\bar{x}_{·2}) &... & ∑(x_{1j} −\bar{x}_{·1} ) (x_{nj} −\bar{x}_{·n}) \\[0.3em] \ ∑(x_{2j} −\bar{x}_{·2} ) (x_{1j} −\bar{x}_{·1})& ... & .&. \\[0.3em] \ .& ... & .&. \\[0.3em] \ ∑ (x_{nj} −\bar{x}_{·n}) (x_{1j} −\bar{x}_{·1}) & . &.& ∑ (x_{nj} −\bar{x}_{·n}) (x_{nj} −\bar{x}_{·n}) \end{bmatrix}

\bar{x} _{·j}是第j列的均值,我们可以观察到主对角线是n个方差,其他元素是一般的协方差。

\bar{X}是X每列均值所组成的一维向量(np.mean(X,axis=0)),那么协方差矩阵还可以表示为\frac{1}{m-1} (X-\bar{X} )(X-\bar{X} )^T,实际上我们后面处理的矩阵都是去均值的,所以我们接下来出现的X都可以认为是取均值后的。\frac{1}{m-1} XX^T

插播一下特征值:A\eta=λ\eta,则认为η是矩阵A的特征向量,λ是对应的特征值。矩阵可以对角化即纯在可逆P使A满足P^{-1}AP=\Lambda,其中\Lambda是A的n特征值作为主对角线元素组成的主对角矩阵,P的列向量是\Lambda每个对角线元素对应的特征向量。若A是对称的,则一定可以对角化,且对角化后的特征向量可以互相正交,即互不相关。

PCA:

终于写到PCA了,我们先抛开前面讲的内容,讲一下PCA。

比如我们简单地认为横坐标是身高,纵坐标是体重,而标签是“能吃”,“不能吃”。但是我们不想考虑那么多特征,只想考虑一个特征,显然单独地把一些特征扔掉是不合理的,所以我们想要求出一个“合力”,即在这条坐标轴上超过一点就是“能吃”了,即红线。但这条红线意义不是那么好解释,他只是把点垂直投影到红线上,去掉了点到直线的距离这个不太重要的噪声。


红线.png

降维的时候我们要找的是方差大的方向作为新坐标轴,因为方差大意味着点之间区别大,信息量多(类似于信息论里信息熵,越不确定信息量越大)。降维的过程是:

以方差最大的方向作为坐标轴方向,因为数据的最大方差给出了数据的最重要的信息。第一个新坐标轴选择的是原始数据中方差最大的方法,第二个新坐标轴选择的是与第一个新坐标轴正交且方差次大的方向。重复该过程,重复次数为原始数据的特征维数。

PCA 本质上是将方差最大的方向作为主要特征,并且在各个正交方向上将数据「去相关」,也就是让它们在不同正交方向上没有相关性。通常我们认为信息具有较大的方差,而噪声有较小的方差

讲协方差矩阵的最大原因在于想说明想要主成分分析,我们即想要协方差尽可能小,而方差大,我们观察到即让协方差矩阵对角线方差元素非0,其他元素等于0。怎么才能让协方差矩阵变到这种形状呢,答案在于矩阵对角化。正好协方差矩阵是对称矩阵,所以对角化后的特征向量正好正交,即特征向量无关,特征向量即我们需要的新轴。所以我们得到最大方差轴后,由此需要的是与最大方差轴正交的轴作为第二个轴。

image.png
去除平均值
计算协方差矩阵
计算协方差矩阵的特征值和特征向量
将特征值排序
保留前N个最大的特征值对应的特征向量
将数据转换到上面得到的N个特征向量构建的新空间中(实现了特征压缩)
#导入numpy库
from numpy import *
import numpy as np

#解析文本数据函数
#@filename 文件名txt
#@delim 每一行不同特征数据之间的分隔方式,默认是tab键'\t'
def loadDataSet(filename,delim='\t')
    #打开文本文件
    fr=open(filename)
    #对文本中每一行的特征分隔开来,存入列表中,作为列表的某一行
    #行中的每一列对应各个分隔开的特征
    stringArr=[line.strip().split(delim) for line in fr.readlines()]
    #利用map()函数,将列表中每一行的数据值映射为float型
    datArr=[map(float.line)for line in stringArr]
    #将float型数据值的列表转化为矩阵返回
    return mat(datArr)

#pca特征维度压缩函数
#@dataMat 数据集矩阵
#@topNfeat 需要保留的特征维度,即要压缩成的维度数,默认4096    
def pca(dataMat,topNfeat=4096):
    #求数据矩阵每一列的均值
    meanVals=np.mean(dataMat,axis=0)
    #数据矩阵每一列特征减去该列的特征均值
    meanRemoved=dataMat-meanVals
    #计算协方差矩阵,除数n-1是为了得到协方差的无偏估计
    #cov(X,0) = cov(X) 除数是n-1(n为样本个数)
    #cov(X,1) 除数是n
    covMat=np.cov(meanRemoved,rowvar=0)
    #计算协方差矩阵的特征值及对应的特征向量
    #均保存在相应的矩阵中
    eigVals,eigVects=np.linalg.eig(mat(conMat))
    #sort():对特征值矩阵排序(由小到大)
    #argsort():对特征值矩阵进行由小到大排序,返回对应排序后的索引
    eigValInd=np.argsort(eigVals)
    #从排序后的矩阵最后一个开始自下而上选取最大的N个特征值,返回其对应的索引
    eigValInd=eigValInd[:-(topNfeat+1):-1]
    #将特征值最大的N个特征值对应索引的特征向量提取出来,组成压缩矩阵
    redEigVects=eigVects[:,eigValInd]
    #将去除均值后的数据矩阵*压缩矩阵,转换到新的空间,使维度降低为N
    lowDDataMat=meanRemoved*redEigVects
    #利用降维后的矩阵反构出原数据矩阵(用作测试,可跟未压缩的原矩阵比对)
    reconMat=(lowDDataMat*redEigVects.T)+meanVals
    #返回压缩后的数据矩阵即该矩阵反构出原始数据矩阵
    return lowDDataMat,reconMat
import matplotlib
import matplotlib.pyplot as plt
fig=plt.figure()
ax=fig.add_subplot(lll)
#三角形表示原始数据点
ax.scatter(dataMat[:,0].flatten().A[0],dataMat[:,1].flatten().A[0],\
                    marker='^',s=90)
#圆形点表示第一主成分点,点颜色为红色
ax.scatter(reconMat[:,0].flatten().A[0],reconMat[:,1].flatten().A[0]\, marker='o',s=90,c='red')

写不动了,有机会再写

参考
https://www.cnblogs.com/terencezhou/p/6235974.html

上一篇 下一篇

猜你喜欢

热点阅读