类别变量数量多且类别数量多

数据挖掘 分类 随机森林 预处理 分类数据 阶级失衡
2021-09-26 12:59:55

我正在研究一个二进制分类问题,其中数据集略微不平衡(30% 0 类 | 70% 1 类)。

我的大部分特征都是分类的,有大量的类别。例如:其中一个有 310 个类别,但前 10 个最常出现的变量占训练和测试数据的约 50%。我正在考虑保留这些经常出现的前 k 个值并将所有其他值编码为另一个类别“其他”。

这样做可以吗?

此外,什么样的分类器最适合这样的任务?我在看随机森林。然而,由于嘈杂的数据(太多的类别,太多的特征)我的模型不能很好地概括(低召回率和精度)。

感谢您的时间。

PS:数据不是时间序列

4个回答

过去,我经常处理此类数据。
当您有许多具有高基数的分类特征时,您必须避免对它们进行 one-hot 编码,因为它会消耗过多的内存,而且最重要的是,从它们构建的树将太深并且比没有 one-hot 编码构建的树更糟糕。
您需要一个基于树的模型库,该模型库实现了原生分类特征支持(即不需要对分类特征进行一次性编码)。
我建议您使用以下 4 种实现之一:
- CatBoost
- LightGBM
- H2O GBM
- H2O 随机森林
Scikit learn 和 XGBoost 实现仍然需要 one-hot 编码的分类变量,因此如果您的数据集具有高基数分类变量(即超过 10 个级别/类别),我不建议使用这些库之一。
看到这个

LightGBM 通过整数编码的分类特征提供了良好的准确性。LightGBM 应用 Fisher (1958) 来找到此处描述的类别的最佳分割。这通常比 one-hot 编码执行得更好。

“我正在考虑保留这些经常出现的前 k 个值并将所有其他值编码为另一个类别“其他”。这样做可以吗?”,对我来说也应该没问题。

我还有一些评论:

  1. 您也可以尝试使用新功能。那就是结合多个分类特征,而不是独立使用所有这些特征。
  2. 由于您有许多分类特征,每个分类特征的一个热编码将生成一个巨大的特征列表,这可能会过度拟合您的模型。您也可以尝试不使用 One Hot Encoding,因为决策树并不总是强制要求。

您好,欢迎到论坛。就像一个想法:

您建议的策略(提取 X 中的重要类并将其余类保留为“其他”)可能有效,值得一试。确保您不会通过将级别保持在“其他”类别中来丢弃信息。

另一种选择是(当然)对所有类进行一次热编码。

无论如何,我会检查监管(通过 L2 或 L1 规范)是否有用。

一些背景:L1调节可以将特征缩小到零,L2调节可以缩小特征但它们永远不会变为零。

所以说你有很多 one-hot 编码的特性,但你不知道哪一个是真正重要的。只需让计算机通过 L1 规则来完成选择特征的工作。

从方法上讲,这个问题听起来像是提升的候选者。Boosting 类似于随机森林,但除此之外,该算法试图专注于特别难以预测的行/观察。这是通过种植许多非常小的树木来完成的。

著名的算法有 LightGBM、Catboost、XGboost。他们都为监管提供支持。

所以我会从“很多”单热编码特征开始,并通过 L1 调节来提升以摆脱不相关的特征。

对分类变量进行编码以便您不会丢失信息并且不会在类别之间添加不存在的关系,这是从模型中获得良好性能的基础。

您不能简单地对您的类别进行 LabelEncode,因为它们添加了不存在的关系。例如,如果您有一个名为“颜色”的特征,它采用三个值 - 红色、蓝色和绿色,并且您将红色编码为 1,蓝色编码为 2,绿色编码为 3,这将暗示诸如此类的关系

Red<le<Green
le=(Red+Green)/2

由于维度的诅咒,您不能使用 OneHotEncoder,因为数据集相对较小,这会使您的特征空间膨胀超出模型的理解范围。

当您丢失信息时,仅采用前 k 个频繁出现的类别的方法将不是最理想的。更好的方法是使用FrequencyEncoder将类别替换为其出现频率(或计数)。

更复杂的方法,如目标编码和对比编码方案,当已知编码类别在高基数类别的情况下表现更好时,它们会考虑目标变量。

如果您的某些类别具有非特定域的字符串值,您可以使用预训练的Word2Vec将它们转换为有意义的向量。如果您的任何类别包含长文本(例如事件描述),您可以根据此类类别的值构建的句子训练您自己的 Word2Vec通过对句子中的向量进行加权平均,您可以对句子进行编码。

就模型而言,使用正确的编码方式,随机森林和梯度提升机可以正常工作SVM 和 Vanilla 神经网络也值得考虑。为了提高准确性,您绝对可以使用XGBoost