分类编码#
分类编码是将分类变量转换为数值特征的过程。这是大多数数据科学项目中的一个重要特征工程步骤,因为它确保机器学习算法能够适当地处理和解释分类数据。
有多种分类编码方法可以用来编码分类特征。独热编码和序数编码是最为人熟知的,但在训练机器学习模型前后,其他编码技术可以帮助处理高基数和稀有类别。
Feature-engine 的分类编码器通过各种编码方法,将变量的分类值替换为估计的或任意的数值。在本页中,我们将更详细地讨论分类特征以及分类编码的重要性,然后介绍 Feature-engine 支持的各种编码技术。
分类特征#
分类变量是指其值从一组类别或标签中选择的变量。它们的值可以是字符串或数字。
颜色 是一个分类特征,可以取值如 红色、黄色 或 橙色 等。同样,尺寸 是另一个分类特征,取值为 小、中 和 大。
名义数据 vs 顺序数据#
分类特征可以是 名义 或 有序。
名义特征 是分类特征,其类别没有定义的排序或固有顺序。颜色 是一个名义特征的例子,因为每种颜色都是一个独立的实体,没有逻辑的排序或等级。
序数特征 是类别特征,其类别显示固有的顺序或排名。尺寸 是序数特征的一个例子,因为不同的尺寸可以从最小到最大排序。
理解分类特征是 名义 还是 有序 可以帮助我们选择最合适的编码方法,将它们的值转换为数字。
识别分类特征#
我们可以通过检查它们的数据类型来识别分类特征。使用 pandas 的 dtypes
,我们可以获取数据框中所有变量的数据类型;通常,非数值数据类型的特征,如 字符串、对象 或 分类,都是分类特征。
分类特征也可以是数值型的,例如 商店ID、SKU ID 或 邮政编码 等特征。尽管这些变量具有数值,但它们是分类的。
基数#
基数 指的是分类变量的唯一类别数量。例如,变量 ‘size’ 的基数为 3,因为它取值为 ‘small’、’medium’ 和 ‘large’。
当一个分类变量的不同值数量相对较少时,我们称其具有 低基数。相反,当一个分类特征的不同类别数量较多时,我们称其具有 高基数。
高度重要的特征可能会带来挑战。它可能导致基于树的模型过拟合,也可能导致测试或实时数据中出现未见类别。正如我们稍后将看到的,如果在设计机器学习管道时没有考虑到未见类别,机器学习模型将不知道如何处理它们,并会返回错误或不准确的预测。
未见类别#
未见类别 是指在测试或验证数据集中,甚至在模型部署后的实时数据中出现的分类值,这些值在训练数据中不存在,因此机器学习模型**未曾见过**。
未见类别因多种原因而具有挑战性。首先,当我们通过使用编码技术从类别值创建到数字的映射时,我们只为训练集中 存在 的类别生成映射。因此,我们将缺乏对新出现的、未见值的映射。
我们可能会倾向于用0或任意值替换未见类别,或者在使用独热编码时在所有虚拟变量中使用0,但这可能会导致机器学习模型的行为异常,从而导致预测不准确。
理想情况下,我们希望在模型训练期间考虑到未见类别的潜在存在,更广泛地说,在整个机器学习管道的训练期间,即包括特征工程和分类编码步骤。正如我们稍后将看到的,一些分类编码方法可以处理未见类别。
类别编码的重要性#
大多数机器学习算法,如 线性回归、支持向量机 和 逻辑回归,要求输入数据为数值型,因为它们使用数值计算来学习预测特征与目标变量之间的关系。这些算法本身不具备解释分类数据的能力。因此,分类编码是一个关键步骤,确保输入数据符合机器学习模型的预期。
一些基于 决策树 算法的实现可以直接处理分类数据。我们仍然建议对分类特征进行编码,例如,以减少基数并考虑未见过的类别。
过拟合#
过拟合发生在机器学习模型除了学习训练数据中的潜在关系外,还学习了数据中的噪声和随机波动。这导致模型在训练数据上表现异常出色,但在未见过的数据上无法泛化(即,模型在验证数据集上表现不佳)。
高基数特征可能导致过拟合,特别是在基于树的模型中,如决策树或随机森林。过拟合发生的原因是基于树的模型会尝试在高基数特征上进行广泛的分割,使得最终的树过于复杂。这通常导致泛化能力差。减少基数通常有助于缓解这个问题。
编码管道#
许多分类编码方法从数据中学习参数。这些参数用于替换原始的分类值。为了防止过拟合并准确评估机器学习管道,在拟合编码器之前将数据集划分为训练集和测试集是关键。换句话说,编码器应该仅从 训练数据 中学习编码参数。
编码方法#
有多种方法可以将分类变量转换为数值特征。独热编码和序数编码是最常用的,但其他方法可以缓解高基数问题并考虑未见过的类别。
在本页的其余部分,我们将介绍编码分类数据的各种方法,并重点介绍可以执行此转换的 Feature-engine 转换器。
独热编码#
独热编码(OHE)包括将分类变量替换为一组二进制变量,每个变量代表变量中的一个唯一类别。如果观察结果显示该类别,则二进制变量取值为1,否则取值为0。
独热编码特别适合线性模型,因为它将每个类别独立处理,而线性模型能够有效地处理二进制变量。
然而,独热编码增加了数据集的维度,因为它为每个类别添加了一个新变量。因此,OHE 可能不适合编码高基数的特征,因为它可以显著增加数据集的维度,通常会导致一组高度相关甚至相同的变量。
Feature-engine 的 OneHotEncoder
实现了独热编码。
频繁类别的独热编码#
为了避免特征空间的巨大增加,一些数据科学家通过对变量中的**最频繁类别**进行独热编码来创建二进制变量。较少出现的值被集体处理,并在为频繁类别创建的所有二进制变量中表示为0。
频繁类别的独热编码可以帮助解决高基数问题以及未见类别的问题,因为未见类别也将被编码为不频繁的值。
Feature-engine 的 OneHotEncoder
可以实现频繁类别的一热编码。
序数编码#
在序数编码中,每个类别被替换为一个整数值。这些数字通常是任意分配的。使用 Feature-engine 的 OrdinalEncoder
,我们可以选择任意分配整数,或者根据每个类别的平均目标值进行排序。
序数编码是在分类变量具有固有顺序时的一个首选选项。例如,变量 size ,其值为 ‘small’, ‘medium’ 和 ‘large’,以及变量 education level ,其值如 ‘high school’, ‘bachelors’, ‘masters’ 和 ‘PhD’ 等。
序数编码适用于基于决策树的模型,因为这些模型有能力解释编码变量与目标之间的非线性关系,并且偏好低特征空间。
然而,序数编码缺乏处理未见类别的能力。如果在后续阶段出现新的类别,编码器将不知道应该为其分配什么数字,因为类别到整数的映射是基于训练集生成的。这可能导致错误并扰乱机器学习流程。因此,在类别数量固定且不会随时间变化的情况下,使用序数编码最为有效。
Feature-engine 的 OrdinalEncoder
实现了序数编码。
计数和频率编码#
计数和频率编码包括将类别映射到训练数据集中每个类别观察到的计数或百分比。当类别的出现频率具有意义且具有一定的预测能力时,计数和频率编码是合适的。
计数和频率编码在高基数情况下表现良好,并且不会增加数据集的维度,这与独热编码相反。然而,当两个或更多类别具有相同的计数时,这种编码方法会为它们分配相同的值,模型可能无法仅基于该特征区分两个观察结果。
计数和频率编码无法自行处理未见过的类别。为了管理未见过的类别,我们可以显式地为它们分配一个频率或计数为’0’,这代表了该类别在训练集中的频率,以防止在推理时间(即在进行预测时)或在对实时数据进行编码时失败。
Feature-engine 的 CountFrequencyEncoder
实现了计数和频率编码。
均值编码#
均值编码,或目标编码,包括用目标变量在该类别内观测值的均值与总体目标均值的混合来替换每个类别。
此编码过程是专门为处理高基数的特征而设计的。当存在高基数时,数据中会有高度代表性的类别,以及稀有的类别。使用均值编码,我们将高度代表性的类别替换为更接近每个类别目标均值的值,而稀有类别将被替换为更接近总体目标均值的值。这样,未见过的类别将自动被考虑,并被替换为训练数据集中的目标均值。
均值编码方法直接将分类特征与目标变量联系起来,因此容易导致过拟合。在用目标均值编码类别时,务必确保有适当的验证策略。
Feature-engine 的 MeanEncoder
实现了均值编码。
WoE 编码#
WoE 编码通过证据权重替换类别,证据权重由以下公式给出:
这种编码主要用于金融行业。
WoE 是衡量一个类别在预测目标结果为 ‘1’ 或 ‘正’ 时的 ‘好坏’ 或 ‘强度’ 的指标。这意味着 WoE 值高的类别是正类的强预测因子。
WoE 编码只能用于 二分类 ,其中目标变量有两个可能的结果,如 ‘1’ 和 ‘0’。WoE 编码的这一特性使其与逻辑回归高度兼容,因为逻辑回归的基础也是基于对数几率的概念。
Feature-engine 的 WoEEncoder
实现了 WoE 编码。
决策树编码#
决策树编码包括用决策树模型的输出来替换每个类别。
在决策树编码中,使用分类特征训练决策树来预测目标变量。决策树根据每个类别分割数据,最终将观测值引导至最终的叶子节点。然后,每个类别被替换为树的预测值,该预测值由在该叶子节点结束的观测值计算出的平均目标值组成。
Feature-engine 的 DecisionTreeEncoder
实现了决策树编码。
稀有标签编码#
我们之前提到,高基数可能导致不常见和未见的类别。这反过来可能导致在新数据编码过程中失败。处理不常见类别的一种常见方法是将它们集体视为一个额外的组。我们称这个过程为罕见标签编码。
稀有标签编码有助于减少特征的基数。这对模型和人类都有好处,因为它简化了输入特征。
稀有标签编码可以与其他编码方法结合使用,如独热编码、序数编码和证据权重,以防止特征空间的爆炸,或防止对不常见值的映射缺失。
Feature-engine 的 RareLabelEncoder
实现了罕见标签编码。
字符串相似度编码#
字符串相似性编码包括用一组浮点变量替换分类变量,这些浮点变量捕捉类别名称之间的相似性。新变量的值介于 0
和 1
之间,其中 0
表示没有相似性,而 1
表示类别名称之间的完全匹配。
字符串相似性编码非常适合用于“脏”分类特征。当分类数据中存在拼写错误(如 bachelors 与 bachlors)、某些实例使用缩写而其他实例使用全称(如 U.S. 与 United States)等情况时,我们称这些分类数据为“脏”数据。大多数编码方法会将这些类别视为不同的类别,即使它们指的是同一类别。为了避免这种情况,我们可以使用字符串相似性首先计算每个唯一类别之间的“距离”,然后将高度相似的类别分组在一起。
字符串相似性编码通过将相似类别合并在一起,降低了基数,同时也提升了模型性能。
Feature-engine 的 StringSimilarityEncoder
实现了字符串相似性编码。
Feature-engine 编码器特性概述
Transformer |
回归 |
分类 |
多类 |
描述 |
---|---|---|---|---|
√ |
√ |
√ |
添加虚拟变量以表示每个类别 |
|
√ |
√ |
√ |
用整数替换类别 |
|
√ |
√ |
√ |
用它们的数量或频率替换类别 |
|
√ |
√ |
x |
用目标均值替换类别 |
|
x |
√ |
x |
用证据的权重替换类别 |
|
√ |
√ |
√ |
用决策树的预测结果替换类别 |
|
√ |
√ |
√ |
将不频繁的类别归入一个类别 |
|
√ |
√ |
√ |
用距离值替换类别 |
Feature-engine 的分类编码器默认情况下仅适用于分类变量。从版本 1.1.0 开始,您可以选择将参数 ignore_format
设置为 False
,并使转换器也接受数值变量作为输入。
单调性
大多数 Feature-engine 的编码器将返回,或尝试返回编码变量与目标之间的单调关系。单调关系是指一个变量的值随着另一个变量的值增加或减少而增加或减少。请参见以下示例图:
单调关系往往有助于提高线性模型的性能并构建更浅的决策树。
回归 vs 分类
大多数 Feature-engine 的编码器都适用于回归和分类,但 WoEEncoder()
仅设计用于 二元 分类。
多类分类
最后,Feature-engine 的一些编码器可以开箱即用地处理多类目标,例如 OneHotEncoder()
、CountFrequencyEncoder()
和 DecisionTreeEncoder()
。
需要注意的是,虽然 MeanEncoder()
和 OrdinalEncoder()
可以处理多类目标,但类别的平均值可能不具有显著意义,这将违背这些编码技术的目的。
替代编码技术#
除了 Feature-engine 支持的分类编码方法外,还有其他方法,如特征哈希或二进制编码。这些方法由 Python 库 category encoders 支持。目前,我们决定不支持这些转换,因为它们返回的特征不容易解释。因此,很难理解使用这些方法编码的分类变量训练的机器学习模型的输出。
其他资源#
有关此功能和其他特征工程方法的教程,请查看以下资源:
或者阅读我们的书:
我们的书籍和课程都适合初学者和更高级的数据科学家。通过购买它们,您正在支持 Feature-engine 的主要开发者 Sole。