本文始发于个人公众号: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. mysql基础-数据库表的管理-记录(四)

    0x01 MySQL中字符大小写 1.SQL关键字及函数不区分大小写 2.数据库.表及视图名称的大小写区分与否取决于底层OS及FS 3.存储过程.存储函数及事件调度器的名字不区分大小写,但触发器区分大 ...

  2. mysql基础-数据库初始化操作必要步骤和客户端工具使用-记录(二)

    0x01 mysql启动时,读取配置文件的顺序 Default options are read from the following files in the given order:/etc/my ...

  3. 【 转】百度地图Canvas实现十万CAD数据秒级加载

    Github上看到: https://github.com/lcosmos/map-canvas 这个实现台风轨迹,这个数据量非常庞大,当时打开时,看到这么多数据加载很快,感到有点震惊,然后自己研究了 ...

  4. laravel clone后需要做的操作

    首先 安装依赖关系 composer install 第二步 复制配置文件 cp .env.example .env 第三步 创建新的应用程序密钥 php artisan key:generate 第 ...

  5. LR脚本信息函数-lr_get_vuser_ip

    lr_get_vuser_ip 返回Vuser的IP地址. char * lr_get_vuser_ip(); lr_get_vuser_ip函数返回Vuser的IP地址. 当执行IP欺骗时,每个Vu ...

  6. 1、安装配置Git私有服务器

    安装并配置一个私有的Git服务器吧,这样自己的代码就可以进行版本控制了,当然版本控制的重要性嘛,Please Baidu. 系统环境:64位Win10 Version 1909 安装步骤: 1.下载j ...

  7. cc26a_demo-CppPrimer_动态绑定_多态-代码示范

    //多态性    //从派生类到基类的转换    //引用或者指针既可以指向基类对象,也可以指向派生类对象    //只有通过引用或者指针调用虚函数才会发生动态绑定.    //为什么定义虚的函数?可 ...

  8. ConcurrentHashMap源码解析-Java7

    目录 一.ConcurrentHashMap的模型图 二.源码分析-类定义 2.1 极简ConcurrentHashMap定义 2.2 Segment内部类 2.3 HashEntry内部类 2.4 ...

  9. Andrew Ng - 深度学习工程师 - Part 1. 神经网络和深度学习(Week 2. 神经网络基础)

     =================第2周 神经网络基础=============== ===2.1  二分分类=== ===2.2  logistic 回归=== It turns out, whe ...

  10. SLS编写规范

    SLS编写规范 规范要点说明 首先,状态的执行不可回滚,执行完了就是执行完了,并不会中断回滚,其次,状态的执行,可以反复执行,也就是说一个状态文件,可以多次来进行调用. 在编写状态文件过程中,有以下几 ...