机器学习(降维)PCA原理及实现

降维概述

降维的目的

维度灾难

在数据挖掘中,特征工程是极其重要的一环,不断寻找特征的过程,就是不断给数据增加维度。通常特征更丰富,算法就更容易捕获数据之间的模式。
维度高了之后,计算开始变得非常困难; 同时特征之间会相互干扰,而不是相互独立,从而影响算法性能;
还有一个很重要的原因是维度高了之后,样本在空间的分布会变得很稀疏,这容易导致过拟合,比如决策树的叶子节点上样本太少。
——机器学习 - 降维算法概述

具体来说,做m次实验,有m个样本,每个样本有n个随机值,用矩阵表示数据集就是 Amn 。一行代表一个样本,一列代表一个特征。

降维的要求

降维就是说把A变成 Amk ,其中 k<n ,如此样本可以由更少维度的特征来表示。

降维的要求则是新矩阵能近似地刻画原矩阵(线性变换),数据的主要信息要能保留下来。

如何才能刻画呢,就是把各维度中最能表征此线性变换的维度(真正的特征)抽出来,把那些相关的维度合并处理,而不是简单的去掉一些维度。

PCA降维的手段

PCA目标

PCA(Principal Component Analysis,主成分分析)常用于提取一系列多维样本的主要成分。那么,怎么理解主成分?

假设三维空间中有一系列点,这些点分布在一个过原点的斜面上,如果你用自然坐标系x,y,z这三个轴来表示这组数据的话,需要使用三个维度,而事实上,这些点的分布仅仅是在一个二维的平面上,那么,问题出在哪里?如果你再仔细想想,能不能把x,y,z坐标系旋转一下,使数据所在平面与x,y平面重合?这就对了!如果把旋转后的坐标系记为x’,y’,z’,那么这组数据的表示只用x’和y’两个维度表示即可!当然了,如果想恢复原来的表示方式,那就得把这两个坐标之间的变换矩阵存下来。这样就能把数据维度降下来了!但是,我们要看到这个过程的本质,如果把这些数据按行或者按列排成一个矩阵,那么这个矩阵的秩就是2!这些数据之间是有相关性的,这些数据构成的过原点的向量的最大线性无关组包含2个向量,这就是为什么一开始就假设平面过原点的原因!那么如果平面不过原点呢?这就是数据中心化的缘故!将坐标原点平移到数据中心,这样原本不相关的数据在这个新坐标系中就有相关性了!有趣的是,三点一定共面,也就是说三维空间中任意三点中心化后都是线性相关的,一般来讲n维空间中的n个点一定能在一个n-1维子空间中分析!所以,不要说数据不相关,那是因为坐标没选对!

——主成分分析(PCA)原理及推导

实际上PCA是要找到样本空间中的一组新的基(维度更低),将原数据在这组新基上进行投影(将每一个样本表示为这组基的线性组合),使得投影后的方差(variance)最大(因为选取了方差最大的维度,所以这样可以存储最多的信息)或者说投影使损失最小。

下图应该是对PCA第二种解释(损失最小化)展示得最好的一张图片了(ref:svd,pca,relation)

这里写图片描述

降维步骤

  1. 数据表示为 A={z1,z2,,zn} 对数据A进行中心化得新矩阵
    X={x1,x2,,xn}={z1μ,z2μ,...,znμ}
    其中 μ=1nn1zi
    注意这里的向量都是列向量
  2. 求X的协方差矩阵; cov(X)=XX/(m1) ;实际中不需要分母,因为去掉后特征向量是一致的
  3. 对协方差矩阵 cov(X) 进行特征值分解;
  4. 取特征值矩阵中最大的K个特征值对应的”k-特征向量”矩阵 P
  5. 将原数据A乘以 P 得到降维后的新矩阵

为什么这么做

目标是投影后使方差最大
为什么要得协方差的特征向量呢?

这里有一个推导过程:

我们先考虑矩阵在新坐标的第一主轴 u1 上的投影,使投影后的方差最大化,即使下式最大化:

1nni=1(xiu1)2

=1nni=1(xTiu1)2 # 点积转矩阵乘法

=1nni=1(xTiu1)T(xTiu1) # 括号里面就是矩阵乘法表示内积,转置以后的行向量乘以列向量得到一个数。因为一个数的转置还是其本身,所以可以写成这样

=1nni=1uT1xixTiu1 # 去括号

=1nuT1(ni=1xixTi)u1 # 因为 u1 和i无关,可以把它拿到求和符外面

=1nuT1XXTu1 # 因为 X={x1,x2,,xn}

XX’是半正定的对称阵,所以上式为半正定的二次型,存在最大值。

现在问题就是如何求目标函数的最大值?以及取最大值时u1的方向?

上式是关于u1的函数,现在求函数极值且存在约束条件 uT1u1=1 适用拉格朗日乘数法。参考资料:拉格朗日乘数法 - Poll的笔记
目标函数和约束条件构成了一个最大化问题:

max{uT1XXTu1}uT1u1=1

构造拉格朗日函数:

f(u)=uT1XXTu1+λ(1uT1u1)

对u1求导(找驻点):

fu1=2XXTu12λu1=0XXTu1=λu1

显然,u1即为XX’特征值 λ 对应的特征向量!XX’的所有特征值和特征向量都满足上式,那么将上式代入目标函数表达式即可得到:

uT1XXTu1=λuT1u1=λ
所以,如果取最大的那个特征值,那么得到的目标值就最大

第二主轴方向为第二大特征值对应的特征向量方向,以此类推,证明类似。

这样我们就能依次找到每个轴的方向。

综上,我们将 XXT 做特征值分解即可找到新的一组基,而且新的一组基就是特征向量!

代码实现

import numpy as np


class PCA:
    def __init__(self, dimension, train_x):
        # 降维后的维度
        self.dimension = dimension
        # 原始数据集
        self.train_x = train_x

    @property
    def result(self):
        '返回降维后的矩阵'
        # 1. 数据中心化
        data_centering = self.train_x - np.mean(self.train_x, axis=0)
        # 2. 计算协方差矩阵
        cov_matrix = np.cov(data_centering, rowvar=False)
        # 3. 特征值分解
        eigen_val, eigen_vec = np.linalg.eig(cov_matrix)
        # 4. 生成降维后的数据
        p = eigen_vec[:, 0:self.dimension]
        return np.dot(data_centering, p)

后面我们会看一些具体的应用案例

猜你喜欢

转载自blog.csdn.net/zhengwei223/article/details/78921181