本文始发于个人公众号:TechFlow,原创不易,求个关注

今天是机器学习专题的第27文章,我们一起来聊聊数据处理领域的降维(dimensionality reduction)算法。

我们都知道,图片格式当中有一种叫做svg,这种格式的图片无论我们将它放大多少倍,也不会失真更不会出现边缘模糊的情况。原因也很简单,因为这种图片是矢量图,一般的图片存储的是每一个像素点的颜色值,而在矢量图当中,我们存储的是矢量,也就是起点终点以及颜色。由于矢量图只记录起点终点,所以无论我们如何放大,图片都不会失真,而传统的图片就做不到这一点。

其实svg就相当于图片的降维,我们将上百万的像素点简化成了若干个矢量完成了图片的存储,大大减少了数据的规模。机器学习领域中的降维算法其实也是差不多的原理。

背景与原理

现在降维算法这个词已经越来越少听到了,在面试当中也很少被提及,这是有时代因素的。因为现在的计算资源以及存储资源越来越廉价了,在以前很难承担的计算量,现在变得越来越轻松。所以相对而言,降维算法没有之前热门了,也越来越少在面试当中出现。

从现状倒推回从前,我们大概可以猜到,在若干年以前,当我们面临海量无法承担的数据的时候,降维算法是多么的重要。因为,我们都知道,机器学习训练的速度和它使用的数据量有这非常密切的关系,使用10维特征和使用100维特征的模型的收敛速度至少是10倍以上的差距。那么,自然而然地我们就会想到,如果有某种方法可以将100维的数据”压缩“成10维,该有多好?

但问题来了,数据不是实体,我们真的可以随意压缩吗,这其中的原理是什么呢?

最根本的原理是既然特征可以用来训练模型,那么特征的分布和label的分布必然是有一定的内在联系的。也就是说数据并不是随意分散的,而是彼此之间有联系的。我们各种各样的压缩算法,本质上都是利用了数据之间的关联。

举个不是非常恰当,但是很直观的例子。假设说我们现在有三个特征,分别是一个人的考试成绩、智商以及努力程度。我们会很明显地发现,考试成绩和智商以及努力程度这两个特征高度相关。如果我们能够找到它们之间的关联,我们完全可以去掉考试成绩这个特征,而通过智商、努力程度和它的这种关联来推算出这个值来。当然既然是推算出来的,显然会和原本的值有一定的误差,这也是不可避免的。

从这个例子当中,我们可以明确两点,首先,压缩数据是利用的数据分布的关联或者是特性,如果是完全随机的数据是无法降维压缩的。其次,降维压缩必然会带来信息损失,也就是误差,这是不可避免的。

降维算法

降维压缩的算法有好几种,常见的有PCA、ICA和FA,下面我们来简单介绍一下。

首先是PCA,PCA的英文全称是Principal Component Analysis即主成分分析。这种方法的主要原理是对数据进行坐标变换,即将数据从原来的坐标系更换到新的坐标系。新的坐标轴是通过最大方差理论推导得到的,即新的坐标轴包含了原始数据中大部分的方差,这里的方差可以理解成信息。

ICA的英文是Independent Component Analysis即独立成分分析,在这个算法当中它假设数据是通过N个数据源生成的。假设数据是这N个数据源数据混合观察的结果。这些数据源在统计上是互相独立的,如果数据源的数目少于原始特征的数目,也可以完成降维。

最后是FA即Factor Analysis即因子分析。在因子分析当中,我们假设样本当中存在一些隐变量,我们假设样本是这些隐变量和一些噪音的线性组合。那么只要这些隐变量的数量少于原始特征的数量,我们就可以用这些隐变量来作为新的数据从而实现降维。

这三种降维算法虽然各不相同,但是核心的思路都是一致的。都是假设数据的分布满足某一种特性,通过利用这一种特性来对数据进行压缩。这其中使用范围最广的是PCA,所以我们着重来了解一下PCA的原理以及实现。

理论推导

关于PCA算法有两种通俗的解释,一种是最大方差理论,另外一种是最小化降维损失,这两个思路推导出的结果是一样的。相比之下,最大方差理论更加容易理解一些,所以我们就选择最大方差理论来做个简单的解释。

在信号系统当中,我们普遍认为信号具有较大的方差,而噪音拥有较小的方差。信噪比就是信号与噪声的方差比,这个比值越大越好,越大说明噪音越小,信号的质量越高。比如下图当中的这个数据分布,我们可以在原始数据当中找到两个正交轴,根据方差最大理论,我们会把方差大的那个轴看成是信号,方差小的看成是噪音。

根据这个思路,最好的k维特征是将n维的样本转换成k维坐标之后,拥有最大方差的k个

协方差

到这里,我们虽然知道了要获取方差最大的方向作为新的坐标轴,但是如果我们直接去计算的话是会有问题的。最大的问题在于我们没办法选出K个来,如果只是选择类似的K个方向,这K个轴的信息都差不多,会丢失大量的信息。所以我们不仅要选择K个轴,而且要保证这K个轴尽可能线性无关

要做到线性无关,也就是说这K个轴应该是彼此正交的。如果两个轴正交,可以进一步得到这两个轴的协方差为零。为了简化运算,我们可以先让原始数据全部减去各自特征的均值。在去除均值之后,两个特征的协方差可以表示为:

两个特征正交等价于它们的协方差为0,我们假设去除了均值之后的矩阵为X,我们来写出它的协方差矩阵。

协方差矩阵

对于去除了均值的矩阵X而言,有一个性质是它的协方差矩阵。我们可以来简单证明一下,假设矩阵当中只有两个特征a和b,那么我们将它按行写成矩阵:

我们假设X的协方差矩阵为C,那么C是一个对称矩阵,它的对角线上的元素表示各个特征的方差,其他的元素则表示特征之间的协方差。我们的目标是希望能够得到一个类似形式的对角矩阵,也就是说除了对角线之外的其余元素全为0,这样这些特征之间就是正交矩阵,我们根据对角线上的值挑选出方差最大的K个特征即可。

我们的目的和方向已经很明确了,距离终点只有一步之遥,但是这一步怎么迈过去呢?

对角化

这里我们采用逆向思维来思考,假设我们已经找到了矩阵P,通过P对X进行线性变换的结果是Y,那么Y=PX,我们假设Y的协方差矩阵为D,那么根据刚才我们推导的结论可以得到:

我们希望D是一个对角矩阵,所以我们要寻找的就是P,P找到之后一切都迎刃而解。因为D是一个对角矩阵,我们将它对角的元素从大到小排列之后,对应P的行组成的矩阵就是我们寻找的基。我们用P的前K行组成的新矩阵对原始数据X进行线性变换,就将它从n维降低到了K维。

所以问题就只剩下了一个,这个P矩阵要怎么求呢?我们干想是很困难的,其实数据家们已经给了我们答案,就是C矩阵的特征向量

由于C是对称矩阵,根据线性代数的原理,它有如下两条性质:

  1. 对称矩阵不同的特征值对应的特征向量必然正交
  2. 特征值是实数,K重特征值对应的线性无关的特征向量刚好有K个

根据这两条性质,我们可以得到,对于n*n的矩阵C来说,我们可以找到n个特征向量。我们将它们按列组成矩阵:

我们通过E可以将C对角化:

我们对中的特征值从大到小排列,选出前K个特征值对应的特征向量组成矩阵即得到了最终的结果P。

最后,我们整理一下上述的整个过程。

  1. 每一维特征减去平均值
  2. 计算协方差矩阵
  3. 求解协方差矩阵的特征值和特征向量
  4. 对特征值降序排序,选择其中最大的K个,然后将对应的K个特征向量作为行向量组成特征向量P
  5. 转换之后的结果

我们把这个逻辑整理一下,写成代码:

import numpy as np

def pca(df, k):
mean = np.mean(df, axis=0)
new_df = df - mean
# 计算协方差矩阵,也可以用公式自己算
cov = np.cov(new_df, rowvar=0)
# 求解矩阵特征值和特征向量
eigVals, eigVects = np.linalg.eig(np.mat(cov))
# 对特征值排序,选最大的K个,由于是从小到大排,所以我们取反
eigValIndice = np.argsort(-eigVals)
# 构建变换矩阵
n_eigValIndice = eigValIndice[:k]
n_eigVect = eigVects[:, n_eigValIndice]
data_ret = new_df.dot(n_eigVect)
return data_ret

实战验证

为了验证程序效果,我们找了一份经典的机器学习数据:http://archive.ics.uci.edu/ml/datasets/SECOM。

我们把它下载下来之后,用pandas读入进来:

可以看到它的特征有590维,展开看的话会发现特征当中有许多空值:

我们对它进行一个简单地预处理,将空值替换成特征均值,并且再读入label的值:

为了验证PCA降维的效果,我们用同样一份数据,用同样的模型,比较一下做PCA之前和之后模型的效果

这里我选择的是随机森林,其实不管用什么模型都大同小异。我们将数据拆分成训练数据与测试数据,并且调用skelarn库当中的随机森林完成训练和预测,最后计算模型在测试集当中的表现。说起来挺复杂,但是由于sklearn替我们完成了大量的工作,所以用到的代码并不多:

我们可以看到,在PCA之前,随机森林在测试集上的表现是92.3%的准确率。

接下来,我们用同样的数据和模型来验证PCA之后对于模型性能的影响。为了保证数据集的完全一致,我们把测试集的随机种子也设置成一样

可以看到模型在测试集上的准确率完全一样,说明PCA并没有过多降低模型的性能,和我们的预期一致。

总结

在今天的文章当中,我们详细介绍并推导了PCA背后的原理,并采取实际数据集验证了PCA算法的效果。从最后的结果上来看,虽然我们将590维的特征缩减到了10维,但是模型的效果却几乎没有多大影响,可见PCA的威力。

当然,这背后的因素很多,除了PCA本身的原理之外,和数据的分布以及训练测试样本的数量也有关系。在极端场景下,可能特征的数量非常多,含有大量的噪音,如果我们不做降维直接训练的话,很有可能导致模型很难收敛。在这种情况下,使用降维算法是必要的,而且会带来正向的提升。如果特征数量不多,模型能够收敛,使用降维算法可能没什么助益,而且会稍稍降低模型的效果。但在一般的情况下,数据集特征的分布也符合二八定律,即20%的特征带来80%以上的贡献,大部分特征效果不明显,或者噪音很多。在这种情况下,使用PCA进行降维,几乎是一定起到正向作用的。

当然在实际的应用场景当中,降维算法用的越来越少,除了计算能力提升之外,另外一个很重要的原因是深度学习的兴起。深度神经网络本身就带有特征筛选的效果,它自己会选择合适的特征组合达到最好的效果,所以很多特征处理和降维等操作显得不是特别有必要了。虽然如此,但是算法本身的思想还是很有借鉴作用,PCA算法在Kaggle比赛当中使用频率也很高,对它进行详细地了解和学习还是很有必要的。

今天的文章就到这里,如果喜欢本文,可以的话,请点个赞和关注吧,给我一点鼓励,也方便获取更多文章。

本文使用 mdnice 排版

PCA算法 | 数据集特征数量太多怎么办?用这个算法对它降维打击!的更多相关文章

  1. 【HEVC帧间预测论文】P1.1 基于运动特征的HEVC快速帧间预测算法

    基于运动特征的 HEVC 快速帧间预测算法/Fast Inter-Frame Prediction Algorithm for HEVC Based on Motion Features <HE ...

  2. 如何开发一个异常检测系统:使用什么特征变量(features)来构建异常检测算法

    如何构建与选择异常检测算法中的features 如果我的feature像图1所示的那样的正态分布图的话,我们可以很高兴地将它送入异常检测系统中去构建算法. 如果我的feature像图2那样不是正态分布 ...

  3. Hihocoder 太阁最新面经算法竞赛18

    Hihocoder 太阁最新面经算法竞赛18 source: https://hihocoder.com/contest/hihointerview27/problems 题目1 : Big Plus ...

  4. hihoCoder太阁最新面经算法竞赛15

    hihoCoder太阁最新面经算法竞赛15 Link: http://hihocoder.com/contest/hihointerview24 题目1 : Boarding Passes 时间限制: ...

  5. zz 圣诞丨太阁所有的免费算法视频资料整理

    首发于 太阁实验室 关注专栏   写文章     圣诞丨太阁所有的免费算法视频资料整理 Ray Cao· 12 小时前 感谢大家一年以来对太阁实验室的支持,我们特地整理了在过去一年中我们所有的原创算法 ...

  6. SIFT算法:特征描述子

    SIFT算法:DoG尺度空间生产  SIFT算法:KeyPoint找寻.定位与优化 SIFT算法:确定特征点方向  SIFT算法:特征描述子 目录: 1.确定描述子采样区域 2.生成描述子 2.1 旋 ...

  7. hihocoder Round #c1(hihoCoder太阁最新面经算法竞赛1 )

    Test链接:https://cn.vjudge.net/contest/231849 选自hihoCoder太阁最新面经算法竞赛1 更多Test:传送门 A:区间求差 给一组区间集合A和区间集合B, ...

  8. [OpenCV]基于特征匹配的实时平面目标检测算法

    一直想基于传统图像匹配方式做一个融合Demo,也算是对上个阶段学习的一个总结. 由此,便采购了一个摄像头,在此基础上做了实时检测平面目标的特征匹配算法. 代码如下: # coding: utf-8 ' ...

  9. 【sklearn朴素贝叶斯算法】高斯分布/多项式/伯努利贝叶斯算法以及代码实例

    朴素贝叶斯 朴素贝叶斯方法是一组基于贝叶斯定理的监督学习算法,其"朴素"假设是:给定类别变量的每一对特征之间条件独立.贝叶斯定理描述了如下关系: 给定类别变量\(y\)以及属性值向 ...

随机推荐

  1. 汇编指令:push、pop

    8086CPU出栈入栈都是以字为单位进行的. push ax 由一下两步完成 1.SP=SP-2 2.将ax中的内容送入SS:SP指向的内存单元 pop ax 1.将SS:SP指向的内存单元中的内容送 ...

  2. pytorch入门2.2构建回归模型初体验(开始训练)

    pytorch入门2.x构建回归模型系列: pytorch入门2.0构建回归模型初体验(数据生成) pytorch入门2.1构建回归模型初体验(模型构建) pytorch入门2.2构建回归模型初体验( ...

  3. 环境篇:呕心沥血@CDH线上调优

    环境篇:呕心沥血@线上调优 为什么出这篇文章? 近期有很多公司开始引入大数据,由于各方资源有限,并不能合理分配服务器资源,和服务器选型,小叶这里将工作中的总结出来,给新入行的小伙伴带个方向,不敢说一定 ...

  4. @atcoder - AGC024F@ Simple Subsequence Problem

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定由若干长度 <= N 的 01 字符串组成的集合 S. ...

  5. ClientDataSet训练之1

    在做平面文件数据集时(ClientDataSet),需要引用单元,  uses Midaslib //D7,ClientDataSet选择文件(添加数据集) //为何D10.3.2不可右键添加数据集呢 ...

  6. 刷一遍《剑指Offer》,你还需要这些知识!(一刷)

    因为时间紧和基础薄弱,一刷<剑指Offer>就变成了速看. 我按照: 1.看题目思考一会: 2.上网找找关于题目里不懂的知识点: 3.看评论和官方题解的解法,尽量看懂,并及时弄懂不懂的地方 ...

  7. SSH网上商城四

    第29课:10-SSH网上商城:购物模块的实体的封装 1.现在我们要实现购物车的模块,当用户在点击 加入购物车按钮的时候需要跳转到 上面我们需要对购物车的对象进行封装 上面一个商品就对应一个记录项,购 ...

  8. linux 在指定文件夹下查找指定字符

    grep -r '119090610015743205' /data/html/www/gap_bz_middleware/storage/apiLogs/

  9. curl模拟调用接口

    curl模拟调用接口 1. get请求 curl -i -X GET http://url/bind/agentOnWork/v2?Sig=******* 2. post请求(带头信息以及参数) cu ...

  10. xdebug调试代码常用操作

    xdebug调试代码常用操作 1.查看变量中的值 2.常用快捷键 ①F8单步调试 ②F9可以直接快速结束调试 ③F7 可以进入调试代码的底层方法,我觉得查看底层代码时,这个特别的方便!