有多种技术可以将分类特征转换为适用于机器学习算法的数值表示。每种方法都有其自身的优点和缺点。选择最适合的编码策略并非总是简单明了,通常取决于您数据的具体特点、计划使用的机器学习模型以及您的计算资源。以下将对多种编码方法进行比较,其中包括:独热编码(One-Hot Encoding)、序数编码(Ordinal Encoding)、目标编码(Target Encoding)、二元编码(Binary Encoding)和哈希编码(Hashing Encoding)。
我们可以根据几个重要因素评估这些技术:
- 输出维度:会创建多少新特征?高维度可能会增加计算成本和内存使用,并可能导致某些模型的维度灾难问题。
- 信息保留:编码是否保留了原始信息?它是否引入了可能误导的信息(例如人为的顺序)?
- 基数处理:该方法如何应对具有许多独特类别的特征?
- 新类别处理:当遇到在训练期间未曾出现过的测试集类别时,该方法如何表现?
- 计算成本:需要多少处理能力和内存?
- 模型兼容性:该编码是否适合特定类型的模型(例如,线性模型与基于树的模型)?
- 可解释性:理解编码后特征的含义有多容易?
独热编码
- 维度:高。创建 k 个新的二元特征,其中 k 是唯一类别的数量。对于高基数特征可能会出现问题。
- 信息:保留名义信息,不假设顺序。每个类别都有其自己的表示。
- 基数:由于产生的特征数量庞大,不适合处理非常高基数的情况。
- 新类别:标准实现通常会报错或需要明确处理(例如,忽略、映射到默认类别)。在Scikit-learn的
OneHotEncoder中设置handle_unknown='ignore'会为未知类别创建全零行。
- 计算:对于高基数情况可能消耗大量内存。训练/推理成本随特征增加而升高。
- 模型兼容性:适用于大多数模型,尤其是线性模型,它们能从每个类别的明确表示中受益。
- 可解释性:高。与独热编码特征关联的系数直接反映了该特定类别的影响(如果使用
drop='first',则相对于一个参考类别)。
序数编码
- 维度:低。只创建一个新特征。
- 信息:如果类别具有有意义的顺序,则保留序数信息。如果应用于名义数据,则会引入人为的、可能误导的顺序。
- 基数:在维度方面很容易处理高基数,但结果整数范围可能变大。
- 新类别:需要明确处理。未知类别可能被映射到特定值(例如-1或
NaN)或导致错误。Scikit-learn的OrdinalEncoder具有handle_unknown参数。
- 计算:非常高效。
- 模型兼容性:非常适合基于树的模型(如决策树、随机森林、梯度提升),它们可以通过找到最佳分割点自然地处理有序的离散特征。如果引入的顺序没有意义,则可能与线性模型或基于距离的算法(如KNN或SVM)表现不佳,因为这些模型会数值地解释整数值。
- 可解释性:如果顺序有意义,则中等。否则,低,因为整数映射是任意的。
目标编码(均值编码)
- 维度:低。通常创建一个新特征,表示每个类别的平滑平均目标值。
- 信息:捕获类别与目标变量之间关系的信息。这可能非常具有预测性,但如果实施不当(例如,在编码期间未使用适当的交叉验证策略),则存在数据泄露和过拟合的明显风险。
- 基数:很好地处理高基数,因为维度保持较低。
- 新类别:需要仔细处理。常见的策略包括使用目标的全局平均值或应用带有先验的平滑。
- 计算:中等。需要根据目标变量计算统计数据。需要在交叉验证循环中仔细实施。
- 模型兼容性:可以很好地与各种模型配合使用,通常能提升基于树的算法的性能。由于编码可能存在的非线性,对线性模型使用时需谨慎。
- 可解释性:低。编码值表示平滑的目标平均值,而非类别本身,这使得直接解释变得困难。
二元编码
- 维度:中等。创建 log2(k) 个新特征,其中 k 是唯一类别的数量。对于高 k 值,维度明显低于独热编码。
- 信息:一种折衷方案。它不像序数编码那样假设顺序,但也不像独热编码那样将类别完全分离。在抽象过程中会丢失一些信息。
- 基数:对于独热编码不可行的中等高基数特征来说,这是一个不错的选择。
- 新类别:面临与独热编码和序数编码相似的挑战。需要明确处理。
- 计算:相对高效。涉及序数映射,然后是二元转换和二元数字的独热编码。
- 模型兼容性:通常与大多数模型兼容。对于对高维度敏感的模型,其表现可能优于独热编码。
- 可解释性:低。结果二元特征缺乏与原始类别相关的直接、直观的含义。
哈希编码器
- 维度:低且固定。输出特征的数量由用户定义,并且独立于类别的数量。
- 信息:由于哈希冲突,可能存在信息丢失,即不同类别映射到相同的输出特征。严重程度取决于哈希空间的大小(输出特征的数量)。
- 基数:非常适合极高基数的特征以及事先未知全部类别集的情况(例如在线学习)。
- 新类别:自动处理。新类别被哈希到现有的输出特征空间中。
- 计算:非常高效,特别适用于大型数据集和流数据。不需要维护类别映射。
- 模型兼容性:适用于大多数模型。性能可能因冲突而降低,特别是对于线性模型。基于树的模型可能更能有效应对冲突。
- 可解释性:非常低。哈希特征没有内在含义。不可能将一个特征映射回生成它的原始类别。
总结表格
这是一个比较编码方法的总结:
| 特点 |
独热编码 |
序数编码 |
目标编码 |
二元编码 |
哈希编码 |
| 维度 |
高(k 个特征) |
低(1 个特征) |
低(1 个特征) |
中等(log2(k) 个特征) |
低(固定 n 个特征) |
| 假设顺序 |
否 |
是 |
否 |
否 |
否 |
| 信息损失 |
极小(名义) |
高(如果无序) |
潜在(平滑) |
中等 |
潜在(冲突) |
| 基数 |
差 |
好(维度方面) |
好 |
好 |
极好 |
| 新类别 |
需要处理 |
需要处理 |
需要处理 |
需要处理 |
自动处理 |
| 泄露风险 |
否 |
否 |
高(需要交叉验证) |
否 |
否 |
| 可解释性 |
高 |
中等(如果有序) |
低 |
低 |
非常低 |
| 计算 |
可能高 |
非常低 |
中等 |
低 |
非常低 |
| 最适合 |
低基数,线性模型 |
有序数据,树模型 |
预测能力,树模型 |
中等基数 |
高基数,在线学习 |
如何选择
- 从简单开始:如果基数较低(例如,少于15个类别),独热编码通常是一个不错的默认选择,因为它具有可解释性和兼容性,特别是对于线性模型。
- 有序数据:如果您的类别具有清晰、有意义的顺序(例如,“低”、“中”、“高”),序数编码是高效且适合的,特别是对于基于树的模型。避免将其用于名义数据。
- 高基数:
- 如果希望保留与目标的一些关系,并且您能够管理泄露风险(使用适当的验证),则目标编码可能很有用。
- 如果可解释性不是主要考虑因素,并且您需要与独热编码相比的维度降低,可以考虑二元编码。
- 如果基数极高,内存受限,或者您处于在线学习环境,那么哈希编码是一个非常实用的选择,尽管存在冲突风险且缺乏可解释性。
- 模型选择:基于树的模型通常更灵活,可以有效地处理序数编码(即使有点随意)或目标编码。线性模型或基于距离的模型对数值表示更敏感;对于名义数据,通常首选独热编码,而序数编码应仅在顺序确实有意义且呈线性关系时使用。
通常需要进行实验。尝试不同的编码方法(特别是独热编码、如果适用的话是序数编码,以及对于高基数数据可能是目标编码或哈希编码),并使用交叉验证评估它们对模型性能的影响。使用像Scikit-learn这样的库构建数据处理流程,可以帮助您系统地测试和比较这些策略。