主成分分析(PCA)以及python实现

前置知识

  • 二次型
  • 对角化
  • 奇异值分解
  • 施密特正交化

PCA

主成分分析是一种从原始数据中消除冗余信息,只需要一个或者几个属性合成的属性就可以提供大部分信息的方法。大概过程是找出一个特殊的线性组合,给要分析的元素赋予一个权值,综合得到一个新的数据。

假设每一个样本有p个属性,一共有n个样本,那么这些向量可以构成一个 p × n p\times{n} p×n的矩阵,称为观测矩阵

主成分分析实际上相当于变换坐标轴,并降低维度。
如一个二维数据集如下图:
原始二维数据
经过PCA进行降维之后可以使用一个维度进行表示,如下图
降维之后的数据

均值和协方差

均值

[ X 1 ⋯ X N ] [\boldsymbol{X}_1\cdots \boldsymbol{X}_N ] [X1XN]为一个 p × N p\times{N} p×N观测矩阵,则其样本平均值M为:

M = 1 N ( X 1 + ⋯ + X N ) \boldsymbol{M}=\frac{1}{N}(\boldsymbol{X}_1+\cdots+\boldsymbol{X}_N) M=N1(X1++XN)

X ^ k = X k − M , k = 1 , 2 , ⋯   , N \boldsymbol{\hat{X}}_k=\boldsymbol{X}_k-\boldsymbol{M},k=1,2,\cdots,N X^k=XkM,k=1,2,,N

则新矩阵
B = [ X ^ 1 ⋯ X ^ N ] B=[\boldsymbol{\hat{X}}_1\cdots\boldsymbol{\hat{X}}_N] B=[X^1X^N]

具有零样本均值,这种矩阵 B B B被称为 平均偏差形式

协方差矩阵

协方差矩阵是一个 p × p p\times{p} p×p的矩阵 S S S,其定义为

S = 1 N − 1 B B T S=\frac{1}{N-1}BB^T S=N11BBT

由于任何具有 B B T BB^T BBT形式的矩阵都是半正定的,所以 S S S也是半正定的。

PS: 虽然协方差矩阵是半正定矩阵,但是由于计算误差,算出来的特征值可能是负数。

其中的对角线元素 s j j s_{jj} sjj称为 x j x_j xj的方差。方差用来度量 x j x_j xj的分散性。

数据的总方差被称为矩阵的,即 S S S的对角线元素之和,记做 t r ( S ) tr(S) tr(S)

S S S中的元素 s i j , i ≠ j s_{ij},i\not ={j} sij,i=j称为 x i x_i xi x j x_j xj的协方差。若协方差为0,则称 x i x_i xi x j x_j xj无关的。当协方差矩阵是对角阵或几乎是对角阵时, X 1 ⋯ X N \boldsymbol{X}_1 \cdots\boldsymbol{X}_N X1XN中多变量分析可以简化。

主成分分析

变量代换

设矩阵 [ X 1 ⋯ X N ] [\boldsymbol{X}_1\cdots \boldsymbol{X}_N ] [X1XN]已经称为平均偏差形式,主成分分析的目标是找到一个 p × p p\times{p} p×p的正交矩阵 P = [ u 1 ⋯ u p ] P=[\boldsymbol{u}_1 \cdots \boldsymbol{u}_p] P=[u1up],确定一个变量代换 X = P Y \boldsymbol{X}=P\boldsymbol{Y} X=PY,或
[ x 1 x 2 ⋮ x p ] = [ u 1 ⋯ u p ] [ y 1 y 2 ⋮ y p ] \left[\begin{matrix} x_1 \\ x_2 \\ \vdots \\ x_p \end{matrix}\right] =[\boldsymbol{u_1} \cdots \boldsymbol{u_p}]\left[\begin{matrix} y_1 \\ y_2 \\ \vdots \\ y_p \end{matrix}\right] x1x2xp=[u1up]y1y2yp
满足新的变量 y 1 , ⋯   , y p y_1,\cdots,y_p y1,,yp两两无关,并保证整理后的方差具有递减顺序。
变量正交变换 X = P Y X=PY X=PY说明,每一个观测向量 X k \boldsymbol{X}_k Xk得到一个新”名称“ Y k \boldsymbol{Y}_k Yk,即 Y k \boldsymbol{Y}_k Yk X k \boldsymbol{X}_k Xk P P P为基的坐标。
易得对任何正交矩阵 P P P Y 1 , ⋯   , Y N \boldsymbol{Y}_1,\cdots,\boldsymbol{Y_N} Y1,,YN的协方差是 P T S P P^TSP PTSP,于是可以构造符合要求的P。设 D D D是对角矩阵且 S S S的特征值在 D D D的对角线上,重新整理使得 λ 1 ≥ λ 2 ≥ ⋯ ≥ λ p ≥ 0 \lambda_1\geq\lambda_2\geq\cdots\geq\lambda_p\geq 0 λ1λ2λp0
D = [ λ 1 0 ⋯ 0 0 λ 2 ⋯ 0 ⋮ ⋱ ⋮ 0 ⋯ ⋯ λ p ] D = \left[\begin{matrix} \lambda_1 & 0 & \cdots & 0 \\ 0 & \lambda_2 & \cdots & 0 \\ \vdots & \enspace & \ddots & \vdots \\ 0 & \cdots &\cdots & \lambda_p \end{matrix}\right] D=λ1000λ200λp找到正交矩阵 P P P,它的列对应单位特征向量 u 1 , ⋯ u p \boldsymbol{u}_1,\cdots\boldsymbol{u}_p u1,up,且有 S = P D P T S=PDP^T S=PDPT
协方差矩阵 S S S的单位特征向量 u 1 , ⋯ u p \boldsymbol{u}_1,\cdots\boldsymbol{u}_p u1,up称为(观测矩阵中)数据的主成分。第一主成分是 S S S中最大特征值对应的特征向量,第二主成分以此类推。
c 1 , c 2 , ⋯   , c p c1,c2,\cdots,c_p c1,c2,,cp u 1 \boldsymbol{u}_1 u1中的元素,第一主成分 u 1 \boldsymbol{u}_1 u1可以通过公式 y 1 = u 1 T X = c 1 x 1 + c 2 x 2 + ⋯ + c p x p y_1=\boldsymbol{u}_1^T\boldsymbol{X} =c_1x_1+c_2x_2+\cdots+c_px_p y1=u1TX=c1x1+c2x2++cpxp来确定新变量 y 1 y_1 y1,可以看出 y 1 y_1 y1是原变量 x 1 , ⋯   , x p x_1,\cdots,x_p x1,,xp的线性组合。通过同样的方式,可以确定 y 2 y_2 y2等。
通过这种方式,可以将变量进行代换,但是优点并不明显。但是如果在对角矩阵 D D D中,前 p ′ p' p个方差和比其他方差大得多,那么我们就可以近似的把数据当成 p ′ p' p维数据而不是 p p p维的。

多维数据的降维

选取一个重构阈值 t t t,选取使得下式成立的最小 p ′ p' p

∑ i = 1 p ′ λ i ∑ i = 1 p λ i ≥ t \frac{\sum^{p'}_{i=1}\lambda_i}{\sum^{p}_{i=1}\lambda_i}\geq{t} i=1pλii=1pλit

PCA仅需保留 P P P和样本均值 M M M即可将新样本投影到低维空间。转换过程不可避免的造成数据的损失,但是舍弃这部分信息往往是必要的。一方面降维之后可以使样本的采样密度增大,这也是降维的主要动机,其次可以在一定程度上起到降噪的效果,因为最小的特征值对应的特征向量往往与噪声有关。

算法步骤

input

样本集 [ X 1 ⋯ X N ] [\boldsymbol{X}_1\cdots \boldsymbol{X}_N] [X1XN],重构阈值 t t t

process

  1. 进行去中心化,得到矩阵 B B B
  2. 计算样本的协方差矩阵 S = B B T S=BB^T S=BBT(常用对输入矩阵的奇异值分解代替特征值分解)
  3. 对协方差矩阵进行特征值分解
  4. 取出最大的 p ′ p' p个特征值对应的特征向量 u 1 , ⋯ u p ′ \boldsymbol{u}_1,\cdots\boldsymbol{u}_{p'} u1,up

Output

投影矩阵 P P P = [ u 1 ⋯ u p ′ \boldsymbol{u}_1\cdots\boldsymbol{u}_{p'} u1up]

代码实现

特征值分解

from numpy import *

def PCA( data, t ):
    m, n = data.shape
    M = data.sum(1) / n
    M = tile(M,(1,n))
    B = data - M
    D, P = linalg.eig( B*B.T /(n - 1) )
    index = argsort(-D)
    D = D[index]; P = P[index];D[D<0] = 0
    denominator = sum(D); numerator = 0
    for i in range(len(D)):
        numerator += D[i]
        if numerator / denominator >= t:
            return diag(D[:i + 1]),P[:,:i + 1], M
    return diag(D), P, M

奇异值分解

from numpy import *

def PCA( data, k ):
    m, n = data.shape
    M = data.sum(1) / n
    M = tile(M,(1,n))
    B = data - M
    U, S, V = linalg.svd( B*B.T /(n - 1) )
    return U[:,:k+1], S[:,:k+1]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值