具有高基数的分类变量的编码

机器算法验证 机器学习 分类数据 分类编码 异常检测 多类
2022-01-27 04:22:58

对于信用卡数据的无监督异常检测/欺诈分析(我没有标记欺诈案例),有很多变量需要考虑。数据是混合类型的,包含连续/数值变量(例如花费的美元金额)以及分类变量(例如帐号)。

包含具有大量唯一类的分类变量的最合适方法是什么?到目前为止我的想法:

  • 标签编码scikit-learn):即将整数映射到类。虽然它返回了一个很好的单个编码特征列,但它强加了一种错误的序数关系感(例如 135 > 72)。
  • 一种热/虚拟编码scikit-learn):即将分类特征扩展为许多取值在 {0,1} 中的虚拟列。这对于具有例如 >10,000 个唯一值的分类特征是不可行的。我知道模型会在稀疏和大数据方面遇到困难。

还有哪些其他(更高级?)合适的方法可以包含大型分类特征列?是否仍然可以通过一些技巧使用 One Hot Encoding?尽管我没有找到任何与入侵检测/欺诈分析相关的应用程序,但我阅读了有关 bin 计数的信息(Microsoft 博客)。

PS:在我看来,在处理无监督入侵检测时,这个问题似乎与编码 IP 地址特征列非常相似。

3个回答

这个链接提供了一个很好的总结,应该会有所帮助。正如您所提到的,标签编码不应用于名义变量,因为它引入了人为的序数。散列是一种潜在的替代方案,特别适用于具有高基数的特征。

您还可以使用在深度学习社区中非常流行的分布式表示。分布式表示最常见的例子是 NLP 中的词嵌入。这并不是说您不能在编码其他分类特征时使用它们。是一个例子。

最后,帐号不是一个明智的输入,因为它更像是一个唯一的标识符,而不是一个通用的(帐户)特征。

这可能有助于分位数编码器:解决回归问题中的高基数分类特征:https ://link.springer.com/chapter/10.1007%2F978-3-030-85529-1_14

对于具有低基数的分类特征,最著名的编码是 One Hot Encoding [1]。这会为每个类别生成正交和等距向量。然而,在处理高基数分类特征时,一种热编码存在几个缺点[20]:(a)输入空间的维度随着编码变量的基数增加,(b)创建的特征是稀疏的——在许多在这种情况下,大多数编码向量几乎不会出现在数据中,并且 (c) One Hot Encoding 不处理新的和看不见的类别。

另一种编码技术是标签/序数编码[3],它使用单列整数来表示不同的分类值。假设这些没有真正的顺序,并且整数是随机选择的。这种编码处理了 One Hot Encoding 中的高维编码问题,但对类别进行了人为的排序。这使得模型更难提取有意义的信息。例如,当使用线性模型时,这种效应会阻止算法为该特征分配高系数。

或者,目标编码(或平均编码)[15] 是克服高基数问题的有效解决方案。在目标编码中,类别特征被替换为每个类别的平均目标值。使用这种技术,可以处理高基数问题并对类别进行排序,以便轻松提取信息和简化模型。当样本很少(甚至只有一个)的类别被接近所需目标的值替换时,目标编码的主要缺点就出现了。这使模型偏向于过度信任目标编码特征并使其容易过度拟合。

这不是您的确切情况,但介绍中有一些可能会有所帮助的点燃评论以及其中一些技术的陷阱。

此外,在 arxiv https://arxiv.org/abs/2105.13783

朱巴布的回答非常好。我只想提供有关嵌入和散列的更多详细信息,并添加一种常见的方法分箱。

binning开始,这是在许多领域中使用的一种非常常用的方法,其关键思想是许多数据遵循 80-20 规则,即使我们有一个具有许多值的特征,但大多数数据将集中在几个值中。一个简单的例子是国籍。世界上有很多国家,但是如果我们要建立一个使用国籍的统计模型,我们不会全部使用/编码(这背后有很多原因,但一般情况下,如果我们全部使用它们可能会过拟合)。相反,我们将选择顶级国籍,并将其他人放入其他类别。请注意,这种方法在深度学习中也被广泛使用,其中一个词在属于其他类别时将具有 OOV(词汇表外)标签。这是一篇有趣的论文:文本分类需要多大的词汇量?,在本文中,最大的词汇量是60K。

嵌入是来自深度学习和 NLP 的一个非常好的想法。假设我们正在构建一个词汇量为 60K 的模型,我们不想做一次热嵌入,因为向量非常稀疏向量之间的距离没有意义例如,如果我们将单词 cat 编码为 [0,0,....,1,0,0],则会浪费大量空间(实际上,如果我们使用稀疏向量而不是密集向量来存储数据,它仍然可以,但稀疏向量有其自身的计算挑战。)。并且单词“cat”和说“dog”之间的距离,将与cat 和说“keyboard”之间的距离相同。

Embedding使用dense vector进行编码,一般的思路是dense vector之间的距离会有意义。例如,“猫”和“狗”之间的距离,将远小于“猫”和“键盘”之间的距离。

散列是另一个有趣的想法,可以在此处的 sklearn 文档中找到一个示例。这个想法是我们使用哈希函数来产生固定数量的特征。这种方法将对特征应用哈希函数,以直接确定它们在数据/设计矩阵中的列索引。结果是提高了速度并减少了内存使用量,但以可检查性为代价;哈希器不记得输入特征是什么样的,也没有 inverse_transform 方法。此外,如果我们将输出特征的数量设置得很小,则会出现冲突。(例如,这个技巧使得无法区分单词“cat”和“keyboard”,因为它们都映射到相同的列索引。)