一键编码高cardinality特征值的简便函数

614 阅读5分钟

我用来处理具有许多独特值的分类特征的一个简单工具

照片:George Pagan IIIonUnsplash

什么是高cardinality?

现在几乎所有的数据集都有分类变量。每个分类变量都由独特的值组成。 _当这些独特的值太多时,一个分类特征就被说成是拥有高cardinality。在_这种情况下,一热编码就成了一个大问题,因为我们要为分类变量中的每一个独特的值(表示它的存在或不存在)单独设置一列。这导致了两个问题,一个是明显的空间消耗,但这个问题没有第二个问题大,即维度的诅咒。 我将更详细地讨论维度诅咒,但首先,让我们看一下一键编码前后的数据。

窥视一下我们的分类特征在一键编码之前和之后的情况

我们要看的是资格特征。由于这些数据是从一个由许多人填写的表格中收集的,所以这一栏包含了许多不同的资格。下面是这一列的样子,以及它的所有独特的值。

medium.com/media/beb16…medium.com/media/332c6…

我们可以看到,该特征中有15个独特的值,它消耗了316KB的空间。让我们用pandas对这个特征进行one_hot编码。

medium.com/media/c725c…medium.com/media/ab507…

我们现在看到我们的原始特征已经变得如此之大,自然,存储它所需要的空间已经增加到**592KB。**这只是一个特征,如果在训练过程中,我们拥有成百上千的分类变量,我们最终会有数百个特征,这在某些情况下不利于模型训练。简单的模型无法处理这么多的变量。但现在让我们来看看另一个主要问题,维度的诅咒。

维度的诅咒

这里有一个简单的总结。

随着特征数量的增长,我们需要准确地能够区分这些特征(为了给我们一个预测)和概括我们的模型(学到的功能)的数据量呈指数增长。

如果你不想看下面的技术问题,请随意跳到下一节。

我想用Yoshua Bengio(是的,传说中的Yoshua Bengio!)的quora答案来更详细地解释这个。我强烈建议在这里阅读整个答案。根据该答案,增加一个特征中的不同值的数量只是增加了使用输入行**(包含n个这样的特征**)的可能组合的总数。假设我们有两个特征,每个都有两个不同的值,这就给了我们总共4种可能的方式来组合这两个特征。现在,如果其中一个有三个不同的值,我们将有3X2=6种可能的方式来组合它们。

在经典的非参数学习算法中(例如最近邻、高斯核SVM、高斯核高斯过程等),模型需要看到这些组合中的每一个例子(或者至少有必要涵盖所有感兴趣的配置变化),以便产生一个正确的答案,一个与其他附近配置所需的目标值不同的答案。

对此有一个变通办法,即即使没有大量的训练数据,只要这些组合中存在某种结构(模式),该模型也可以在配置(不在训练集中)之间进行辨别,以便将来进行预测。在大多数情况下,高cardinality使模型难以识别这种模式,因此模型对训练集以外的例子不能很好地概括。

通过使用一个简单的聚合函数来减少cardinality

下面是一个简单的函数,我用来减少一个特征的cardinality。这个想法非常简单。把属于高频率值的实例保留下来,用一个新的类别来代替其他的实例,我们称之为 "高频率"。 其他。

  1. 选择一个阈值
  2. 将列中的唯一值按其频率降序排序
  3. 不断增加这些排序后(降序)的唯一值的频率,直到达到一个阈值。
  4. 这些是我们将保留的唯一类别,所有其他类别的实例将被**"其他 "取代。**

在阅读代码之前,让我们先看一个简单的例子。假设我们的颜色列有100个值,我们的阈值是90%(也就是90)。我们有5个不同类别的颜色。 **红色(50),蓝色(40),黄色(5),绿色(3)和橙色(2)。**括号内的数字表示该列中存在多少个该类别的实例。

我们看到,红色(50)+蓝色(40)达到了我们的阈值90。在这种情况下,我们只保留2个类别(红色、蓝色),并将所有其他颜色的实例标记为 "其他"。

因此,我们将cardinality从5个减少到3个(红、蓝、其他)。

这是我写的一个实用函数,以方便我们的工作。它有很好的注释,并且完全遵循我上面描述的内容,所以你跟着做不会有问题。我们可以设置一个自定义的阈值return_categories选项可以让我们看到降低cardinality后的所有唯一值列表。

medium.com/media/290c5…medium.com/media/adee6…

正如你所看到的,使用这个函数,我们把qualification列的cardinality从15个减少到6个!

总结

我们看到了如何通过使用一个简单的函数来减少cardinality,更重要的是为什么这是必要的(维度的诅咒)。但是请记住,我们很幸运,我们列中的数值分布允许我们使用这种方法。如果所有的15个类别都是平均分布的,我们就不能使用这个方法,在这种情况下,可能需要结合数据集的其他特征来应用PCA,但在其他时候会有更多的说法。