11.4 特征抽取
从某种程度上说,当我们删除掉冗余特征和无关特征的后,经常会发现仍然还有过多的特征。无论使用什么机器学习方法,它们的效果都不会太好。我们可以理解,在给定的巨大特征空间中,实际上它们不可能做得很好。我们意识到,必须砍掉“皮肉”,删掉那些在常识意义上具有价值的特征。另一种需要降低维度,但特征选择又不会有多大帮助的情况是:对数据进行可视化。我们最多只能用3个维度,才能得到有意义的图形。
现在我们进入特征抽取方法。这些方法会对特征空间进行重构,使我们更容易接近模型,或者简单把维度砍到二维或三维,使我们能够把它们之间的依赖关系可视化地描绘出来。
同样,我们也可以把特征抽取方法分成线性和非线性的。跟特征选择那一节一样,我们对每个类型都会给出一种方法,线性的是主成分分析,非线性的是多维标度法。尽管这两种方法已经被广泛了解和使用,它们也只是更多有趣而强大的特征抽取方法中的代表。
11.4.1 主成分分析(PCA)
主成分分析(PCA),通常是你想要删减特征但又不知道用什么特征抽取方法时,第一个要去尝试的方法。PCA的能力是有限的,因为它是一个线性方法。但很可能它已经足以使你的模型学得很好。外加上它有着良好的数学性质、发现转换后特征空间的速度、以及在原始和变换后特征间相互转换的能力,我们几乎可以保证,它将会成为你最常用的一个机器学习工具。
总结起来,给定原始特征空间,PCA会找到一个到更低维度空间的线性映射。它具有如下性质:
保守方差是最大的;
最终的重构误差(从变换后特征回到原始特征)是最小的。
由于PCA只是简单对输入数据进行变换,所以它既可以用于分类问题也可以用于回归问题。在本节里,我们将使用一个分类任务来探讨这个方法。
1. PCA概述
PCA包含很多线性代数的内容,我们并不想深入探讨。然而,它的基础算法很容易用以下步骤描述:
1. 从数据中减去它的均值;
2. 计算协方差矩阵;
3. 计算协方差矩阵的特征向量。
如果我们从N 个特征开始,这个算法会返回一个变换后的N 维特征空间——到现在为止我们并没有得到什么。然而,这个算法的一个好处在于,矩阵的特征值预示着方差的大小,这是通过对应的矩阵特征向量来描述的。
让我们假设有N =1000个特征,同时我们知道我们的模型在多于20个特征的时候效果不会很好。然后我们从中挑选出20个具有最高矩阵特征值的特征向量。
2. PCA应用
让我们考虑如下人造数据集,如左图所示:
>>> x1 = np.arange(0, 10, .2) >>> x2 = x1+np.random.normal(loc=0, scale=1, size=len(x1)) >>> X = np.c_[(x1, x2)] >>> good = (x1>5) | (x2>5) # 一些任意类别 >>> bad = ~good # 使示例看起来比较好
Scikit-learn在它的decomposition 包里提供了PCA类。在这个例子里,我们可以明显看到,1个维度已经足以描述数据。我们可以用n_components 参数给出:
>>> from sklearn import linear_model, decomposition, datasets >>> pca = decomposition.PCA(n_components=1)
这里使用PCA的fit() 和transform() 方法(或者fit_transform() 组合)来分析数据,并把数据映射到变换后的特征空间中:
>>> Xtrans = pca.fit_transform(X)
Xtrans 只包含一个维度,正如我们指定的那样。你可以在右图中看到结果。在这个例子里,输出的结果是线性可分的。我们甚至不需要一个复杂的分类器,就可以区分出这两个类别。
要对重构误差有一个认识,我们看一下在变换中保留下来的数据方差:
>>> print(pca.explained_variance_ratio_) >>> [ 0.96393127]
这意味着,在数据从二维变成一维之后,我们仍然剩下96%的方差。
当然,情况并不总是如此简单。通常,我们事先并不知道有多少维是可取的。在那种情况下,我们在初始化PCA 的时候并不会指定n_components 参数,而是让它进行完全转换。对数据进行拟合之后,explained_variance_ratio_ 包含了一个以降序排列的比例数组。第一个值就是描述最大方差方向的基向量的比例,而第二个值就是次最大方差方向的比例,以此类推。画出这个数组之后,我们可以快速看到我们需要多少个成分:在图表里成分个数恰好出现拐角的地方,通常是一个很好的猜测。
提示 成分个数和方差之间的关系图,叫做Scree图。在http://scikit-learn.sourceforge.net/stable/auto_examples/plot_digits_pipe.html 可以下载到一个结合Scree图和网格搜索来为分类问题寻找最佳设置的例子。
11.4.2 PCA的局限性以及LDA会有什么帮助
作为一个线性方法,PCA在处理非线性数据时就有局限性了。我们在这里并不会深入探讨细节问题,但可以说,PCA的一些扩展,例如Kernel PCA,会引入非线性变换,使我们仍然可以使用PCA方法。
PCA另一个有趣的弱点出现在将它应用到特殊分类问题的时候。
让我们将下面的式子:
>>> good = (x1>5) | (x2>5)
替换为:
>>> good = x1>x2
来模拟一个特殊情况,我们可以很快发现问题所在。
在这里,当坐标轴代表方差最高的方向时,各个类别并不会分散开,而如果代表的是次高方差的方向,却可以分散开。很明显,PCA犯了错误。由于我们并没有提供给它任何关于类别标签的信息,它无法做得更好。
线性判别式分析 (Linear Discriminant Analyisis,LDA)出场了。这个方法试图让不同类别样本之间的距离最大,同时让相同类别样本之间的距离最小。在这里,我们就不深入探讨其背后理论细节了,仅给出一个帮你快速入门的使用方法:
>>> from sklearn import lda >>> lda_inst = lda.LDA(n_components=1) >>> Xtrans = lda_inst.fit_transform(X, good)
仅此而已。注意,与之前的PCA例子相比,我们为fit_transform() 方法提供了类别标签。所以,PCA是一个无监督的特征抽取方法,而LDA是一个有监督的方法。其结果看起来符合预期:
那么,为什么首先考虑PCA而不是LDA呢?好吧,事情并不是那样简单。随着类别数量的增多,每个类别中的样本就会变得稀少,LDA的效果也就不再那么好。同时,对于不同训练集,PCA并不像LDA那样敏感。所以当我们需要考虑选用哪个方法时,只能说“看情况”。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论