使用许多分类变量改善分类


37

我正在使用一个包含200,000多个样本和每个样本约50个特征的数据集:10个连续变量,另外约40个是类别变量(国家,语言,科学领域等)。对于这些分类变量,您有150个不同的国家/地区,50种语言,50个科学领域等。

到目前为止,我的方法是:

  1. 对于具有许多可能值的每个类别变量,仅采用具有超过10000个样本的值作为该变量。这将减少到5-10个类别,而不是150个类别。

  2. 为每个类别建立虚拟变量(如果有10个国家,则为每个样本添加大小为10的二元向量)。

  3. 用此数据输入随机森林分类器(交叉验证参数等)。

目前,使用这种方法,我只能获得65%的准确度,并且我认为可以做得更多。尤其是我对1)感到不满意,因为我觉得我不应该根据他们拥有的样本数量随意删除“最不相关的值”,因为这些表示较少的值可能更具区分性。另一方面,我的RAM无法通过保留所有可能的值向数据添加500列* 200000行。

您有什么建议要应对这么多的分类变量吗?


2
如果您仍然感兴趣,则可能需要查看关于降维的答案关于层次分类的答案
Aleksandr Blekh

1
当您说“为每个分类变量构建虚拟变量”时,听起来您正在使用Python而不是R?R randomforest可以本地处理类别,因此也可以减少内存。尝试
R。– smci

Answers:


20

1)随机森林应该能够本地处理分类值,因此可以寻找不同的实现,因此您不必对所有这些功能进行编码,也不必耗尽所有内存。

2)高基数分类特征的问题在于,很容易过度使用它们。您可能有足够的数据,这不是问题,但请当心。

3)我建议使用Brieman建议的方法或人工对比研究基于随机森林的特征选择。人工对比方法(ACE)很有趣,因为它将功能的重要性与经过改组的自身的重要性进行了比较,后者解决了一些高基数问题。有一篇新论文“模块引导随机森林”,如果您拥有更多功能,可能会很有趣,因为它使用了一种特征选择方法,该方法可以识别高度相关的特征组。

4)另一个有时使用的选项是调整算法,以便在将分割线拟合到袋装箱中之后使用袋装箱进行最终特征选择,这有时有助于防止过度拟合。

这里有一个几乎完整的ace实现并且我有一个内存效率更高/快速的rf实现,可以在这里本地处理分类变量... -evaloob选项支持选项4我正在努力添加对ACE和其他两个rf的支持基于特征的选择方法,但尚未完成。


4
所有这些建议都很有趣,我同意随机森林应该处理本地分类变量,但是scikit-learn不能...我认为这是scikit的主要缺陷之一。我将在您的数据上尝试您的代码,看看会发生什么,并且我会介绍您的其他建议!
Bertrand R

1
试用R实现。运行它是一个班轮。读取数据非常容易,并且有一种新颖的paralell实现,它实现了快速且高效的内存:r-bloggers.com/…另一方面。您的班级不平衡吗?在r实现中,您可以从平衡的引导程序样本sampsize = c(x,x)中生长每棵树。这为我提供了更好的二进制分类。您可以使用OOB混淆矩阵R输出轻松地调整大小并轻松调整分类。
JEquihua 2014年

2
R的randomForest实现允许最多包含32个级别的因子。scikit-learn的限制较少,如果您首先创建虚拟变量(请参见pandas.get_dummies函数)。H2O的随机森林实现对我来说确实表现出色(请参见0xdata.com/docs/master/model/rf)。
Alex Woolford,2015年

1
随机森林有一个更新,更快的实现,该程序包称为Ranger。真的很棒。数量级更快,并且没有32个级别的限制。
Marbel

6

为什么不简单地为每个类别使用一个数字变量呢?在随机森林的情况下,我经常想知道这样做的结果(因为我同意在分类数据中引入序数听起来很可疑,如果使用分类数据通常是没有道理的),但实际上(至少使用我一直使用的RF的scikit-learn实现),我经常观察到它对结果没有影响(我不确定为什么)。


1
这对于n <= 3的分类要素很好,因为您可以通过将要素本身视为分类来生成所有相同的分割。对于较大的n,可以实现与分类分割等效的分割集合,但是算法可能会或可能不会高效地找到它们...但是,如果将特征分割为n个数字特征,也会降低效率该算法可以找到拆分。有人需要在scikit-learn实现中添加分类变量支持,否则效果会更好。
Ryan Bressler 2014年

当您说在分类数据中引入序数听起来有点可疑时,我同意您的看法……我宁愿不必这样做,但我至少可以尝试一下,看看会发生什么!
Bertrand R

4
我在sklearn邮件列表上对此问题进行了长时间的讨论(您可以在这里阅读部分内容:mail-archive.com/scikit-learn-general@lists.sourceforge.net/…)。其中一位实现者的意见是,对于足够深的树,按序编码的分类特征可能会相当不错地工作(除了计算效率更高之外)。无论如何,如果您尝试一下,我将非常有兴趣听到您的结果/结论,因为这是我一直碰到的问题。
cjauvin 2014年

1
因此,我尝试为分类变量保留一个数字变量,它实际上出人意料地好,并且比添加大量二进制条目要好得多...我还尝试根据目标的均值wrt对值进行排序。它也可以正常工作
Bertrand R

实际上,我对此并不感到惊讶。这与我在几个不同设置中所观察到的一致,尽管从投票数量来看,这是一个违反直觉的想法。
cjauvin

5

我认为您应该考虑使用/更多可变减少技术。它摆脱了影响不大的预测因素。

我已经阅读了很多有关数据预处理的内容,这对于减少变量的n°是一个很好的解决方案。

我的建议如下:

  • 对于定性变量,请将丢失的值替换为“丢失”类别。如果不是随机丢失数据,它可能会引入偏差,但是至少您会保留所有观察结果,并且丢失可能会揭示不同的行为。
  • 消除零方差预测变量接近零方差预测变量(请注意不要消除具有高不平衡类别的虚拟变量,它们可以有效地分隔Y。请为您认为重要的变量制作一些图表)。在R中,您可以使用包中的'nzv'函数'caret'。这将大大减少您的数据量。
  • 消除相关的预测因子。使用肯德尔的相关矩阵,因为它更适合在存在分类变量的情况下进行构造。缺点是您必须将所有标称var转换为分类var。
  • 有些特征选择方法会减少数量(聚类-您为每个聚类选择一个代表,LASSO回归等)。我还没有机会进行测试,因为其他步骤将我的变量减少到100以下。

另外,我建议使用AdaBoost算法而不是RF。我个人对这两种方法所做的研究都给了我非常相似的基尼系数。关于AdaBoost的优点在于,在R中,它可以处理缺失的观测值。因此,您可以跳过此列表的第一步

我希望它能有所帮助。祝好运


4

您可能需要考虑混合效应模型。由于它们在高基数分类数据上的性能,它们在社会科学中很受欢迎,并且我使用它们来构建出色的预测模型,其性能优于诸如梯度强化树,随机森林和弹性网正则逻辑回归等流行的机器学习方法。最著名的实现是R的lme4软件包。用于分类的功能是glmer,它实现了混合效应逻辑回归。您可能在缩放数据集时遇到问题,但是我已经完成了15个要素的80k行,而没有太多困难。


2
  1. 当您说“为每个分类变量构建虚拟变量”时,听起来您正在使用Python而不是R?R randomforest可以本地处理类别,因此也可以减少内存。尝试R。

  2. 接下来,您不需要手动修剪/合并分类级别,这听起来很麻烦。即使您这样做,也不能保证人口最多的类别最具预测性。使用参数nodesize控制随机森林的复杂性:从大的nodesize开始,然后逐渐减小它(这是超参数搜索)。

  3. 变量选择将很有用。@lorelai提供了很好的建议。尝试消除无用的(低重要性或高度相关的)功能。树的构造是要素数量的平方,因此,即使您消除三分之一,它也会带来红利。


0

您应该查看H2O.ai软件包。它可以直接处理分类变量,而无需进行任何编码(确保变量是因子)。

我特别喜欢他们的梯度提升机(GBM)的实现,因为您可以在构建模型后查看变量的重要性。GBM还具有抵抗过度拟合的良好功能。

如果您想探索其他模型,它们有:GLM,随机森林,朴素贝叶斯,深度学习等。

请参阅:http : //docs.h2o.ai/h2o/latest-stable/h2o-docs/data-science/gbm.html

它也易于安装(Windows,Linux,Mac),并易于使用R,Python,Java和Scala与API一起运行。

它可以使用多个内核来加快速度。

在不久的将来,它们将支持GPU。

它也是开源和免费的(有Enterprise支持)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.