主成分分析法(PCA)详解与python实现

PCA原理

主成分分析(principal component analysis,PCA)是一种数据分析方法,出发点是从一组特征中计算出一组按重要性从大到小排列的新特征,它们是原有特征的线性组合,并且相互之间是不相关的。主要用来数据降维、可视化、去噪等。
以样本数据有两个特征为例,如图:
在这里插入图片描述
我们将样本点向x轴投影,得到图中红色点列;向y轴投影,得到图中绿色点列,可以看到红色点列比绿色的更好地保留了原数据样本的距离特点,因此若在x、y轴这两个中选一个,我们应选择x轴方向作为降维后的特征。
实际上,我们可以选择的最优方向是图中的黑色虚线方向,当样本数据点向黑色虚线投影后得到的点列比红色点列更优。这里为了进行定量计算,我们引用方差作为判别函数,也就是投影后新点列的方差越大,则该投影方向越优。
将二维推广至n维:设 x 1 , x 2 , ⋯   , x n x_1,x_2,\cdots,x_n x1,x2,,xn为数据的原始n个特征, ξ 1 , ξ 2 , ⋯   , ξ n \xi_1,\xi_2,\cdots,\xi_n ξ1,ξ2,,ξn为变换后的n个新特征,而变换方法是对原始特征作线性组合,即: ξ i = ∑ j = 1 n w i j x j ⋯ ⋯ ( ∗ ) \xi_i=\sum_{j=1}^n w_{ij}x_j\cdots\cdots(*) ξi=j=1nwijxj
而对变换的要求是新特征之间互不相关,(另外为了统一 ξ i \xi_i ξi的尺度,要求线性组合系数的模为1),选择函数则是新特征的方差,我们会选择使得新特征的方差达到最大值的一组系数作为主成分的变换系数,进而根据方差依次递减求出n个新特征。

利用梯度上升法求解主成分

现在来看主成分的一种求解方法。
将样本集如下表示成mxn矩阵:
X = ( x 11 x 12 ⋯ x 1 n x 21 x 22 ⋯ x 2 n ⋮ ⋮ ⋯ ⋮ x m 1 x m 2 ⋯ x m n ) X= \begin{pmatrix} x_{11} & x_{12} & \cdots & x_{1n} \\ x_{21} & x_{22} & \cdots & x_{2n} \\ \vdots & \vdots & \cdots & \vdots \\ x_{m1} & x_{m2} & \cdots & x_{mn} \\ \end{pmatrix} X=x11x21xm1x12x22xm2x1nx2nxmn
每行表示一个样本,共m个样本;每列表示一个特征,共n个特征。
变换向量: w = ( w 1 w 2 ⋮ w n ) w=\begin{pmatrix} w_1 \\ w_2 \\ \vdots \\ w_n \end{pmatrix} w=w1w2wn
m个样本求得的主成分: ξ i = x i w \xi_i=x_iw ξi=xiw,其中 x i = ( x i 1    x i 2    ⋯    x i n ) , i = 1 , 2 , ⋯   , m x_i=(x_{i1} \;x_{i2}\;\cdots\;x_{in}),i=1,2,\cdots,m xi=(xi1xi2xin),i=1,2,,m
于是有 V a r ( ξ ) = ∑ i = 1 m ( ξ i − ξ ˉ ) 2 m − 1 Var(\xi)=\frac{\sum_{i=1}^m (\xi_i-\bar{\xi})^2}{m-1} Var(ξ)=m1i=1m(ξiξˉ)2

公式推导

为了方便计算,我们将样本每个维度的特征值减去每个维度的均值。即: X    =    X − X ˉ X\;=\;X-\bar{X} X=XXˉ,容易计算出现在的 ξ ˉ = 0 \bar{\xi}=0 ξˉ=0,从而 V a r ( ξ ) = ∑ i = 1 m ( ξ i − ξ ˉ ) 2 m − 1 = ∑ i = 1 m ξ i 2 m − 1 = ∑ i = 1 m ( x i w ) 2 m − 1 Var(\xi)=\frac{\sum_{i=1}^m (\xi_i-\bar{\xi})^2}{m-1}=\frac{\sum_{i=1}^{m} \xi_i^2}{m-1}=\frac{\sum_{i=1}^{m} (x_iw)^2}{m-1} Var(ξ)=m1i=1m(ξiξˉ)2=m1i=1mξi2=m1i=1m(xiw)2
可求得梯度: ∂ V a r ∂ w k = 2 m − 1 ∑ i = 1 m ( x i w ) ∗ x i k = 2 m − 1 ∗ ( x 1 w    x 2 w    ⋯    x m w ) ( x 1 k x 2 k ⋮ x m k ) = 2 m − 1 ∗ ( X w ) T ( x 1 k x 2 k ⋮ x m k ) \frac{\partial Var}{\partial w_k}=\frac{2}{m-1}\sum_{i=1}^m(x_iw)*x_{ik}=\\\frac{2}{m-1}*(x_1w\;x_2w\;\cdots\;x_mw)\begin{pmatrix} x_{1k} \\ x_{2k} \\ \vdots \\ x_{mk} \end{pmatrix}= \\ \frac{2}{m-1}*(Xw)^T\begin{pmatrix} x_{1k} \\ x_{2k} \\ \vdots \\ x_{mk} \end{pmatrix} wkVar=m12i=1m(xiw)xik=m12(x1wx2wxmw)x1kx2kxmk=m12(Xw)Tx1kx2kxmk
因此 ∇ V a r = ( ∂ V a r ∂ w 1 ∂ V a r ∂ w 2 ⋮ ∂ V a r ∂ w n ) = 2 m − 1 X T ( X w ) \nabla Var=\begin{pmatrix} \frac{\partial Var}{\partial w_1} \\ \frac{\partial Var}{\partial w_2} \\ \vdots \\\frac{\partial Var}{\partial w_n} \end{pmatrix}=\frac{2}{m-1}X^T(Xw) Var=w1Varw2VarwnVar=m12XT(Xw)
求得方差函数的梯度后,我们便可按照梯度上升法求其最大值

python实现

仍以两个特征的样本为例
导入模块:

import numpy as np
import matplotlib.pyplot as plt

创建样本集:

X = np.empty((100,2))
X[:,0] = np.random.uniform(0,10,size=100)
X[:,1] = 3*X[:,0]+2+np.random.normal(0,1,size=100)
m = 100#样本数

初始样本集如图:
在这里插入图片描述
定义归零函数并将样本集归零:

def Zero(X):
    return X-X.mean(axis=0)
X = Zero(X)

归零后的样本集如图:
在这里插入图片描述
定义归一函数,初始化w:

def One(w):
    return w/np.linalg.norm(w)
w = One(np.ones((2,1)))

定义方差函数:

def Var(X,w):
    return (1/m-1)*np.sum(np.dot(X,w)**2)

下面进入梯度上升法循环:

alpha = 0.1#学习步长
#进入循环:
t = 0#循环次数
while t<1000:
    nabla = (2/m-1)*np.dot(X.T,np.dot(X,w))#梯度
    w0 = w#保存上次循环w值
    w += alpha*nabla#更新w
    w = One(w)#归一
    if np.abs(Var(X,w)-Var(X,w0))<0.001:#如果更新后的w使得方差变化不明显,退出循环
        break
    t += 1#更新循环次数

得出结果如图:
在这里插入图片描述
w = [[0.32036449]
[0.94729435]]
可知 ξ = 0.32036449 x 1 + 0.94729435 x 2 \xi=0.32036449x_1+0.94729435x_2 ξ=0.32036449x1+0.94729435x2即为降维后的新特征,从图中来看,将其作为主成分是合理的。

计算前k个主成分

之前我们计算了主成分,现在我们来看如何确定得出n个新特征并且选出k个最重要的

公式推导

不同的新特征对应的 w w w不同,由此会产生一个特征变换矩阵 W W W,有以下关系:
ξ = W T x \xi=W^Tx ξ=WTx其中字母含义同公式 ( ∗ ) (*) ()
现在我们要求的是最优的正交变换 W W W,使新特征 ξ i \xi_i ξi的方差达到极值(正交的原因是使得新特征之间两两不相关)
考虑第一个新特征 ξ 1 \xi_1 ξ1 ξ 1 = ∑ j = 1 n w 1 j x j = w 1 T x \xi_1=\sum_{j=1}^nw_{1j}x_j=w_1^Tx ξ1=j=1nw1jxj=w1Tx
它的方差是 V a r ( ξ 1 ) = E ( ξ 1 2 ) − ( E ( ξ 1 ) ) 2 = E ( w 1 T x x T w 1 ) − E ( w 1 T x ) E ( x T w 1 ) = w 1 T S w 1 Var(\xi_1)=E(\xi_1^2)-(E(\xi_1))^2=E(w_1^Txx^Tw_1)-E(w_1^Tx)E(x^Tw_1)=w_1^TSw_1 Var(ξ1)=E(ξ12)(E(ξ1))2=E(w1TxxTw1)E(w1Tx)E(xTw1)=w1TSw1其中 S S S为样本特征的协方差矩阵,可以用样本来估计,E是数学期望。又考虑到约束条件 w 1 T w 1 = 1 w_1^Tw_1=1 w1Tw1=1,因此可以用拉格朗日乘子法确定最大值
f ( w 1 ) = w 1 T S w 1 − λ ( w 1 T w 1 − 1 ) f(w_1)=w_1^TSw_1-\lambda(w_1^Tw_1-1) f(w1)=w1TSw1λ(w1Tw11)将上述函数对 w 1 w_1 w1求导并令其等于0,解得:
S w 1 = λ w 1 Sw_1=\lambda w_1 Sw1=λw1
这说明 w 1 w_1 w1是矩阵 S S S的特征向量,而 λ \lambda λ是对应的特征值。将此结果代入之前的方差表达式中
V a r ( ξ 1 ) = w 1 T S w 1 = λ w 1 T w 1 = λ Var(\xi_1)=w_1^TSw_1=\lambda w_1^Tw_1=\lambda Var(ξ1)=w1TSw1=λw1Tw1=λ这说明最大的方差就等于最大的特征值,从而第一主成分对应的 w w w即为矩阵 S S S最大特征值对应的特征向量。
进一步按照不相关以及模为1的要求,可以得出第二主成分对应的向量为矩阵 S S S的第二大特征值对应的特征向量,以此类推

python实现

仍以二维特征为例

import numpy as np
import matplotlib.pyplot as plt

#创建样本集:
X = np.random.uniform(0,10,size=100)
Y = 3*X+2+np.random.normal(0,1,size=100)
m = 100#样本数

#定义归零函数并将样本集归零:
def Zero(X):
    return X-X.mean(axis=0)
X = Zero(X)
Y = Zero(Y)

#协方差矩阵:
S = np.cov(X,Y)

#特征值与特征向量:
l,W = np.linalg.eig(S)#l为特征值集合,W为特征向量集合(W的列向量表示每个特征向量)
n = np.argmax(l)#取将l排序后最大值的下标
w = W.T[n]#第一主成分的向量
print(w)
print(l[n]/np.sum(l))
'''
#可视化:
plt.rcParams['font.sans-serif'] = [u'SimHei']
plt.rcParams['axes.unicode_minus'] = False

x = np.arange(-5,5,0.01)
y = w[1]*x/w[0]
plt.plot(x,y,c='r')
plt.text(1,0,'主成分(新特征)',c='r',fontsize=16)
plt.scatter(X,Y,c='lightskyblue')
plt.xlabel('原特征1')
plt.ylabel('原特征2')
plt.title('显示主成分')
plt.grid()
plt.show()
'''

结果:
[-0.3106425 -0.95052682]
0.9986514522294836
这说明该主成分所代表的的数据占全部方差的比例是0.9986514522294836,非常接近1,从而可以用其作为降维后的特征。
如果是多维的特征,可以用下式计算前k个主成分所占比例:
∑ i = 1 k λ i ∑ i = 1 n λ i \frac{\sum_{i=1}^k\lambda_i}{\sum_{i=1}^n \lambda_i} i=1nλii=1kλi进而根据需要选择使用几个主成分来表示数据,如使得比例达到80%或90%等

小结

使用PCA可以实现对特征的变换和降维,这种变化呢是非监督的,也就是没有考虑样本的类别信息。在监督模式识别情况下,这种以方差为目标函数的方法并不一定总有利于后续分类。
另外,除了降维,我们可以把特征值很小的成分视为噪声,将其去掉可以理解为对样本进行了去噪处理。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值