如何在Spark ML中处理决策树和随机森林的分类特征?

5
我正在尝试在UCI银行营销数据上构建决策树和随机森林分类器-> https://archive.ics.uci.edu/ml/datasets/bank+marketing。该数据集中有许多分类特征(具有字符串值)。在Spark ML文档中,提到可以使用StringIndexer或VectorIndexer对分类变量进行索引以将其转换为数字。我选择使用StringIndexer(向量索引需要向量特征和向量装配器,将特征转换为向量特征只接受数字类型)。使用此方法,每个分类特征的级别将基于其频率分配数字值(类别特征的最常见标签的0)。
我的问题是,随机森林或决策树算法如何理解新特征(源自分类特征)与连续变量不同。索引特征是否在算法中被视为连续的?这是正确的方法吗?还是应该继续使用独热编码来处理分类特征。
我阅读了一些来自论坛的答案,但对最后一部分没有明确的理解。
3个回答

7

对于类别变量中的类别 > 2,应进行 One Hot 编码。

为了理解为什么需要这样做,您需要知道分类数据的子类别之间的区别: 有序数据无序数据

有序数据:值之间具有某种排序关系。例如:客户反馈(优秀、良好、中等、差和非常差)。可以看到它们之间存在明确的排序关系(优秀 > 良好 > 中等 > 差 > 非常差)。在这种情况下,只需要使用StringIndexer进行建模处理。

无序数据:值之间没有定义的顺序关系。例如:颜色(黑色、蓝色、白色…)。在这种情况下,仅使用StringIndexer不足够的,需要在String Indexing后进行 One Hot Encoding

String Indexing 后假设输出为:

 id | colour   | categoryIndex
----|----------|---------------
 0  | black    | 0.0
 1  | white    | 1.0
 2  | yellow   | 2.0
 3  | red      | 3.0

如果不使用One Hot Encoding,机器学习算法会认为:红色 > 黄色 > 白色 > 黑色,但我们知道这是不正确的。使用OneHotEncoder()可以避免这种情况。

所以回答你的问题:

算法中,索引特征会被视为连续变量吗?

它将被视为连续变量。

这是正确的方法吗?还是我应该使用 One-Hot-Encoding 处理分类特征?

这取决于您对数据的理解。虽然随机森林和一些提升方法不需要OneHot Encoding,但大多数机器学习算法需要它。

参考:https://spark.apache.org/docs/latest/ml-features.html#onehotencoder


感谢您详细的回复。我更关心名义数据。在Spark ML中,我不能直接将字符串值用于随机森林模型训练。我需要将其转换为数字值。当我将其转换为数字时,这些值的顺序就没有意义了,因此看起来我也需要对随机森林的名义分类特征执行独热编码。因此,您的回复“取决于您对数据的理解。尽管随机森林和一些提升方法不需要独热编码,但大多数机器学习算法都需要它”,不适用于名义数据。如果您有异议,请告诉我。 - user6200992
是的,如果您知道特定列包含名义数据,则进行独热编码。如果它是有序数据,则可以进行字符串索引。 (尽管对于有序数据进行独热编码也不是错误的) - vdep
据我理解,基于树的算法(如随机森林、XGBoost等)不需要对分类变量进行独热编码。然而,基于距离的算法,例如逻辑回归(或任何使用最小二乘法的回归方法)和支持向量机,则需要进行独热编码。这一点已经由@vdep在上面解释过了。如果我有误,请指正。谢谢。 - Alain Michael Janith Schroter

4
简单来说,Spark的随机森林不需要使用OneHotEncoder对由StringIndexer或VectorIndexer创建的类别特征进行编码。
更详细的解释。一般来说,决策树可以处理有序和名义类型的数据。然而,在实现时,可能需要使用OneHotEncoder(例如Python的scikit-learn)。幸运的是,如果正确处理,Spark的随机森林实现将识别分类特征,并且不需要使用OneHotEncoder!正确处理意味着分类特征包含相应的元数据,以便RF知道正在处理什么。由StringIndexer或VectorIndexer创建的特征在DataFrame中包含有关由Indexer生成和分类的元数据。

这是有道理的,但如果下一步使用StringIndexer和VectorAssembler(用于数字特征)创建特征,然后在另一个VectorAssembler中从这两个特征创建向量列,这种方法仍然有效吗?我的担忧是,在从分类+数字创建完整向量列时,分类元数据会丢失。 - Luis Leal

1
根据vdep的回答,StringIndexer足以处理有序数据。但是,StringIndexer按标签频率对数据进行排序,例如“excellent>good>neutral>bad>very bad”可能变成“good,excellent,neutral”。因此,对于有序数据,StringIndexer不适用。
其次,对于名义数据,文档告诉我们,在具有三个类别A、B和C的一个分类问题中,其相应标签1的比例为0.2、0.6和0.4的一个分类特征中,这些分类特征被排序为A、C、B。两个分割候选者是A | C,B和A,C | B其中|表示分割。
“相应标签1的比例”与标签频率相同吗?因此,我对在Spark中使用StringInder到DecisionTree的可行性感到困惑。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接