微信号:QunarTL

介绍:Qunar技术沙龙是去哪儿网工程师小伙伴以及业界小伙伴们的学习交流平台.我们会分享Qunar和业界最前沿的热门技术趋势和话题;为中高端技术同学提供一个自由的技术交流和学习分享平台.

机器学习之scikit-learn开发入门(6)

2019-01-15 09:30 曹华

曹华,2018 年加入去哪儿网技术团队。目前在火车票事业部/技术部小组。个人对图像处理、数据挖掘、图论、VR 等有浓厚兴趣。


机器学习之 scikit-learn 开发入门 - 

降维 - 主成分分析


一 为什么要使用降维?

不论是哪种机器学习方法都离不开样本的特征,例如西瓜的色泽、根蒂、敲声、密度等。一个复杂的事物有可能包括成百上千种特征,它使得机器学习生成模型算法计算过于复杂。这时候我们就希望可以减少特征来解决计算过于复杂的问题。那么我们该如何减少特征呢? 主成分分析(Principal components analysis,以下简称 PCA)是最重要的降维方法之一。在数据压缩消除冗余和数据噪音消除等领域都有广泛的应用。一般我们提到降维最容易想到的算法就是 PCA,下面我们就来探索PCA的奥秘所在。

二 scikit-learn PCA类介绍

在 scikit-learn 中,与 PCA 相关的类都在 sklearn.decomposition 包中。最常用的 PCA 类就是 sklearn.decomposition.PCA。

三 sklearn.decomposition.PCA参数介绍

我们主要基于 sklearn.decomposition.PCA 来讲解如何使用 scikit-learn 进行 PCA 降维。PCA 类基本不需要调参,一般来说,我们只需要指定我们需要降维到的维度,或者我们希望降维后的主成分的方差和占原始维度所有特征方差和的比例阈值就可以了。 sklearn.decomposition.PCA 的主要参数介绍: ncomponents:这个参数可以帮我们指定希望 PCA 降维后的特征维度数目。最常用的做法是直接指定降维到的维度数目,此时 ncomponents 是一个大于等于1的整数。当然,我们也可以指定主成分的方差和所占的最小比例阈值,让 PCA 类自己去根据样本特征方差来决定降维到的维度数,此时 ncomponents 是一个(0,1]之间的数。当然,我们还可以将参数设置为"mle", 此时 PCA 类会用 MLE 算法根据特征的方差分布情况自己去选择一定数量的主成分特征来降维。我们也可以用默认值,即不输入 ncomponents,此时 ncomponents=min(样本数,特征数)。 除了这些输入参数外,有两个 PCA 类的成员值得关注。第一个是 explainedvariance,它代表降维后的各主成分的方差值。方差值越大,则说明越是重要的主成分。第二个是 explainedvarianceratio,它代表降维后的各主成分的方差值占总方差值的比例,这个比例越大,则越是重要的主成分。下面我们使用 explainedvarianceratio_ 作为评判标准。

四 PCA示例

1、导入头文件

 
           
  1. #coding=utf-8

  2. import numpy as np

  3. import matplotlib.pyplot as plt

  4. from mpl_toolkits.mplot3d import Axes3D

  5. from sklearn.datasets.samples_generator import make_blobs

2、生成样本数据

 
           
  1. X, y = make_blobs(n_samples=10,

  2.       n_features=3, centers=[[3,3,3], [0,0,0], [1,1,1], [2,2,2]],

  3.       cluster_std=[0.2, 0.1, 0.2, 0.2],random_state =9)

3、可视化随机生成的样本

 
           
  1. fig = plt.figure()

  2. ax = Axes3D(fig, rect=[0, 0, 1, 1], elev=30, azim=20)

  3. plt.scatter(X[:, 0], X[:, 1], X[:, 2],marker='o')

  4. plt.show()

4、计算方差比率

我们先不降维,只对数据进行投影,看看投影后的三个维度的方差分布:

 
           
  1. from sklearn.decomposition import PCA

  2.    pca = PCA(n_components=3)

  3.    pca.fit(X)

  4.    print pca.explained_variance_ratio_

我们得到的方差比率是[0.98288449 0.00874633 0.00836918],我们可以将 n_components 设置为2,查看降维结果:

 
           
  1. from sklearn.decomposition import PCA

  2.    pca = PCA(n_components=2)

  3.    pca.fit(X)

  4.    print pca.explained_variance_ratio_

  5.    X_new = pca.transform(X)

  6.    plt.scatter(X_new[:, 0], X_new[:, 1],marker='o')

  7.    plt.show()

方差比例为:[0.98288449 0.00874633]。 降维结果可是为:

可见降维后的数据依然可以很清楚的看到我们之前三维图中的4个簇。 现在我们看看不直接指定降维的维度,而指定降维后的主成分方差和比例。

 
           
  1. pca = PCA(n_components=0.95)

  2.    pca.fit(X)

  3.    print pca.explained_variance_ratio_

  4.    print pca.n_components_

得到的结果为:[0.98288449]。 ncomponents 值为1。 可见只有第一个投影特征被保留。 最后我们看看让MLE算法自己选择降维维度的效果:

 
           
  1. pca = PCA(n_components='mle')

  2.    pca.fit(X)

  3.    print pca.explained_variance_ratio_

  4.    print pca.n_components_

得到的结果为:[0.98288449]。 ncomponents 值为1。 可见由于我们的数据的第一个投影特征的方差占比高达98.3%,MLE 算法只保留了我们的第一个特征。

五、PCA的思想

PCA 顾名思义,就是找出数据里最主要的方面,用数据里最主要的方面来代替原始数据。具体的,假如我们的数据集是 d 维的,共有 m 个数据(x1,x2,...,xm)。我们希望将这 m 个数据的维度从 d 维降到 d' 维,希望这 m 个 d' 维的数据集尽可能的代表原始数据集。我们知道数据从 d 维降到 d' 维肯定会有损失,但是我们希望损失尽可能的小。那么如何让这 d' 维的数据尽可能表示原来的数据呢? 我们先看看最简单的情况,也就是 d=2,d'=1,也就是将数据从二维降维到一维。数据如下图。我们希望找到某一个维度方向,它可以代表这两个维度的数据。图中列了两个向量方向,u1 和 u2,那么哪个向量可以更好的代表原始数据集呢?从直观上也可以看出,u1 比 u2 好。

为什么 u1 比 u2 好呢?可以有两种解释,第一种解释是样本点到这个直线的距离足够近,第二种解释是样本点在这个直线上的投影能尽可能的分开。是因为希望将数据进行差异化,得到更好的降维结果。 在这里我们有一个降维的标准:样本点到这个超平面的距离足够近,或者说样本点在这个超平面上的投影能尽可能的分开。

1、PCA的推导:基于最小的投影距离

假定数据样本进行了中心化(算法流程中会提到中心化的过程),再假定投影变换后得到的新坐标系为{w1,w2,...,wd},其中 wi 是标准正交基向量:

(i≠j)。若丢弃新坐标系中的部分坐标,即将维度降低到d'< d,则样本点 xi 在低维坐标系中的投影是 zi = (zi1;zi2;....zid'),其中:

是 xi 在低维坐标系下第 j 维的坐标。若基于 zi 来重构 xi,则会得到:

考虑整个训练集,原样本点 xi 与基于投影重构的样本点之间的距离为:

根据基于最小的投影距离,上式应被最小化,考虑到 wj 是标准正交基,有

这就是主成分分析的优化目标。

2、PCA的推导:基于最大投影方差

若所有样本点的投影能尽可能分开,则应该使投影后样本点的方差最大化如下图:

投影后样本点的方差是:

于是优化目标可写为:

这里上式与第三节最后的公式实质上是等价的。对他们使用拉格朗日定理可得:

于是,只需对协方差矩阵进行特征值分解,将求得的特征值排序,再取前 d' 特征值对应的特征向量构成 W,这就是主成分分析的解了。

3、PCA算法流程

从上面两节我们可以总结出 PCA 的算法流程: 输入:d 维样本集 D=(x1,x2,...,xm),要降维到的维数 d'。 (1)对所有的样本进行中心化; (2)计算样本的协方差矩阵; (3)对矩阵进行特征值分解; (4)取出最大的 d' 个特征值对应的特征向量(w1,w2,...,wd′),将所有的特征向量标准化后,组成特征向量矩阵 W; (5)对样本集中的每一个样本 xi,转化为新的样本。 输出:降维后的样本集 D′。

六 PCA实例

下面举一个简单的例子,说明 PCA 的过程。 假设我们的数据集有10个二维数据(2.5,2.4), (0.5,0.7), (2.2,2.9), (1.9,2.2), (3.1,3.0), (2.3, 2.7), (2, 1.6), (1, 1.1), (1.5, 1.6), (1.1, 0.9),需要用 PCA 降到1维特征。 首先我们对样本中心化,这里样本的均值为(1.81, 1.91),所有的样本减去这个均值后,即中心化后的数据集为(0.69, 0.49), (-1.31, -1.21), (0.39, 0.99), (0.09, 0.29), (1.29, 1.09), (0.49, 0.79), (0.19, -0.31), (-0.81, -0.81), (-0.31, -0.31), (-0.71, -1.01)。 现在我们开始求样本的协方差矩阵,由于我们是二维的,则协方差矩阵为:

注:这里我给出协方差矩阵的概念和求解过程: https://blog.csdn.net/shenziheng1/article/details/52955687

对于我们的数据,求出协方差矩阵为:

求出特征值为(0.490833989, 1.28402771),对应的特征向量分别为: (0.735178656,0.677873399)和(−0.677873399,−0.735178656),由于最大的k=1个特征值为1.28402771,对于的k=1个特征向量为(−0.677873399,−0.735178656)。则我们的W=(−0.677873399,−0.735178656)。

注:这里我给出矩阵特征值和特征值向量的求解过程: https://blog.csdn.net/zhangfuliang123/article/details/78953523 这里二阶矩阵[a b;c d]的特征值方程是(x-a)(x-d)-bc=0。

我们对所有的数据集进行投影,得到PCA降维后的10个一维数据集为:(-0.827970186, 1.77758033, -0.992197494, -0.274210416, -1.67580142, -0.912949103, 0.0991094375, 1.14457216, 0.438046137, 1.22382056)。

七 PCA算法总结

作为一个非监督学习的降维方法,它只需要特征值分解,就可以对数据进行压缩,去噪,因此在实际场景应用很广泛。为了克服 PCA 的一些缺点,出现了很多 PCA 的变种,比如非线性降维的 KPCA,还有解决内存限制的增量 PCA 方法 Incremental PCA ,以及解决稀疏数据降维的 PCA 方法 Sparse PCA 等。 优点: (1)仅仅需要以方差衡量信息量,不受数据集以外的因素影响; (2)计算方法简单,主要运算是特征值分解,易于实现。 缺点: (1)主成分各个特征维度的含义具有一定的模糊性,不如原始样本特征的解释性强; (2)方差小的非主成分也可能含有对样本差异的重要信息,因降维丢弃可能对后续数据处理有影响。

 
Qunar技术沙龙 更多文章 AIOps 助力航信运维百万级交易系统 0 宕机 Flutter动画的架构设计 你不知道的Sass RxJava学习以及在机票国内主系统重构经验分享 对NG-Nodejs方案下偶发502的探索
猜您喜欢 神鞭与张小龙 Unite 2017 Shanghai主日程曝光,建议收藏 Material Design适配(一) 【Spark 2.0系列】: Spark Session API和Dataset API 有趣的Code Poster