如何在 spark ml 中处理决策树、随机森林的分类特征?

Posted

技术标签:

【中文标题】如何在 spark ml 中处理决策树、随机森林的分类特征?【英文标题】:How to handle categorical features for Decision Tree, Random Forest in spark ml? 【发布时间】:2017-12-11 01:32:10 【问题描述】:

我正在尝试在 UCI 银行营销数据上构建决策树和随机森林分类器 -> https://archive.ics.uci.edu/ml/datasets/bank+marketing。数据集中有许多分类特征(具有字符串值)。

在 spark ml 文档中,提到可以通过使用 StringIndexer 或 VectorIndexer 进行索引将分类变量转换为数字。我选择使用 StringIndexer(向量索引需要向量特征和将特征转换为向量特征的向量汇编器只接受数字类型)。使用这种方法,分类特征的每个级别都将根据其频率分配数值(0 表示类别特征的最频繁标签)。

我的问题是随机森林或决策树的算法如何理解新特征(源自分类特征)与连续变量不同。索引特征在算法中是否会被认为是连续的?这是正确的方法吗?或者我应该继续对分类特征使用 One-Hot-Encoding。

我从这个论坛上阅读了一些答案,但我没有弄清楚最后一部分。

【问题讨论】:

【参考方案1】:

根据 vdep 的回答,StringIndexer 对于 Ordinal Data 来说已经足够了。然而,StringIndexer 按标签频率对数据进行排序,例如“优秀 > 好 > 中性 > 差 > 非常差”可能会变成“好、优秀、中性”。所以对于 Oridinal 数据,StringIndexer 不适合它。

其次,对于 Nominal Data,文档告诉我们

对于一个二分类问题,一个分类特征具有三个类别 A、B 和 C,其标签 1 的对应比例分别为 0.2、0.6 和 0.4,分类特征排序为 A、C、B。两个分割候选为一个 | C、B 和 A、C | B 哪里 |表示分裂。

“标签1的对应比例”和标签频率一样吗?所以我对在 Spark 中使用 StringInder 到 DecisionTree 的可行性感到困惑。

【讨论】:

【参考方案2】:

简而言之,Spark 的 RandomForest 不需要 OneHotEncoder 来处理由 StringIndexer 或 VectorIndexer 创建的分类特征。

更长的解释。一般来说,DecisionTrees 可以处理 Ordinal 和 Nominal 类型的数据。但是,在实现方面,可能需要 OneHotEncoder(就像在 Python 的 scikit-learn 中一样)。 幸运的是,如果处理得当,Spark 的 RandomForest 实现会尊重分类特征,并且不需要 OneHotEncoder! 正确处理意味着分类特征包含相应的元数据,以便 RF 知道它在做什么。由 StringIndexer 或 VectorIndexer 创建的特征在 DataFrame 中包含关于由 Indexer 生成和分类的元数据。

【讨论】:

【参考方案3】:

应该对类别 > 2 的分类变量进行一次热编码。

要了解原因,您应该知道分类数据的子类别之间的区别:Ordinal dataNominal data

Ordinal Data:这些值之间有某种排序。例子: 客户反馈(优秀、好、中性、差、非常差)。正如你所看到的,它们之间有一个明确的顺序(优秀 > 好 > 中性 > 差 > 非常差)。在这种情况下,仅StringIndexer 就足以用于建模目的。

名义数据:这些值之间没有定义的顺序。 例如:颜色(黑色、蓝色、白色、...)。在这种情况下,仅StringIndexer足够的。并且One Hot Encoding 必须在String Indexing 之后。

String Indexing 之后假设输出为:

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

如果没有One Hot Encoding,机器学习算法将假定:red > yellow > white > black,我们知道这不是真的。 OneHotEncoder() 将帮助我们避免这种情况。

所以回答你的问题

在算法中是否会认为索引特征是连续的?

它将被视为连续变量。

这是正确的方法吗?或者我应该继续使用 One-Hot-Encoding 分类特征

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

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

【讨论】:

感谢您的详细回复。我更关心名义数据。在 spark ml 中,我不能像随机森林那样提供字符串值。我需要将其转换为数值。当我将它转换为数字时,值的顺序将没有意义,所以看起来我也必须对随机森林的名义分类特征进行一次热编码。因此,您的回答“取决于您对数据的理解。尽管随机森林和一些增强方法不需要 OneHot 编码,但大多数 ML 算法都需要它”不适用于名义数据。如果您不同意,请告诉我。 是的,如果您知道特定列包含标称数据,则执行一次热编码。如果它是一个序数数据,你可以做 StringIndexing。 (虽然对序数数据做一次热编码并没有错) 据我所知,基于树的算法(即随机森林、XGBoost 等)不需要对分类变量进行一次热编码。然而,诸如logistic regression(或任何使用最小二乘法的回归方法)和support vector machines 等基于距离的算法需要进行一次热编码。 @vdep 在上面解释了这一点。如果错了请指正。谢谢

以上是关于如何在 spark ml 中处理决策树、随机森林的分类特征?的主要内容,如果未能解决你的问题,请参考以下文章

[ML]随机森林

Spark Random Forest classifier 随机森林分类

集成学习 - 决策树-随机森林

Spark DecisionTreeClassifier

spark 随机森林算法案例实战

随机森林算法demo python spark