EqualWidthDiscretiser#

等宽离散化包括将连续变量划分为宽度相等的区间,使用以下公式计算:

\[bin_{width} = ( max(X) - min(X) ) / bins\]

这里,bins 是用户指定的区间数量,max(X)min(X) 分别是需要离散化的变量的最大值和最小值。

离散化是数据科学中常用的数据预处理技术。它也被称为数据分箱(或简称“分箱”)。

优点和局限性#

等宽分箱离散化有一些优点,同时也存在不足。

优势#

等宽分箱的一些优点:

  • 算法效率: 通过提供数据集的简化表示,增强了数据挖掘和机器学习算法的性能。

  • 异常值管理: 通过将异常值分组到极端区间,有效地减轻了异常值的影响,从而保持了主要数据分布的完整性。

  • 数据平滑: 有助于平滑数据,减少噪声,并提高模型的泛化能力。

限制#

另一方面,等宽离散化可能会通过将数据聚合到更广泛的类别中而导致信息丢失。如果同一区间内的数据对目标有预测信息,这一点尤其令人担忧。

让我们考虑使用决策树模型的二分类任务。一个包含高比例目标类别样本的箱子可能会在此场景中影响模型的性能。

EqualWidthDiscretiser#

Feture-engine 的 EqualWidthDiscretiser() 对数值变量应用等宽离散化。它在底层使用 pandas.cut() 函数来查找区间限制,然后将连续变量排序到各个区间中。

你可以通过在设置转换器时传递变量名称的列表来指定要离散化的变量。或者,EqualWidthDiscretiser() 将自动推断数据类型以计算所有数值变量的区间限制。

最佳区间数: 使用 EqualWidthDiscretiser() 时,用户定义了箱的数量。如果变量高度偏斜或不连续,可能需要更小的区间。

与 scikit-learn 的集成: EqualWidthDiscretiser() 以及所有其他 Feature-engine 转换器都能与 scikit-learn 管道 无缝集成。

Python 代码示例#

在本节中,我们将展示 EqualWidthDiscretiser() 的主要功能。

加载数据集#

在这个例子中,我们将使用 Ames House Prices 数据集。首先,让我们加载数据集并将其分割为训练集和测试集:

import matplotlib.pyplot as plt
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split

from feature_engine.discretisation import EqualFrequencyDiscretiser

# Load dataset
X, y = fetch_openml(name='house_prices', version=1, return_X_y=True, as_frame=True)
X.set_index('Id', inplace=True)

# Separate into train and test sets
X_train, X_test, y_train, y_test =  train_test_split(X, y, test_size=0.3, random_state=42)

等宽离散化#

在这个例子中,让我们将两个变量 LotArea 和 GrLivArea 离散化为宽度相等的 10 个区间:

# List the target numeric variables for equal-width discretization
TARGET_NUMERIC_FEATURES= ['LotArea','GrLivArea']

# Set up the discretization transformer
disc = EqualWidthDiscretiser(bins=10, variables=TARGET_NUMERIC_FEATURES)

# Fit the transformer
disc.fit(X_train)

请注意,如果我们不指定变量(默认=`None`),EqualWidthDiscretiser 将自动推断数据类型以计算所有数值变量的区间限制。

通过 fit() 方法,离散器学习了分箱边界并将它们保存到一个字典中,这样我们就可以使用它们来转换未见过的数据:

# Learned limits for each variable
disc.binner_dict_
{'LotArea': [-inf,
  22694.5,
  44089.0,
  65483.5,
  86878.0,
  108272.5,
  129667.0,
  151061.5,
  172456.0,
  193850.5,
  inf],
 'GrLivArea': [-inf,
  864.8,
  1395.6,
  1926.3999999999999,
  2457.2,
  2988.0,
  3518.7999999999997,
  4049.5999999999995,
  4580.4,
  5111.2,
  inf]}

请注意,下限和上限分别设置为 -inf 和 inf。这种行为确保了转换器能够将小于训练集中的最小值或大于训练集中的最大值的极端值分配到相应的区间。

EqualWidthDiscretiser 在存在缺失值的情况下将无法工作。因此,我们应该在拟合转换器之前移除或填补缺失值。

# Transform the data (data discretization)
train_t = disc.transform(X_train)
test_t = disc.transform(X_test)

让我们可视化原始数据和转换后的数据的前几行:

# Raw data
print(X_train[TARGET_NUMERIC_FEATURES].head())

这里我们看到原始变量:

          LotArea  GrLivArea
Id
136     10400       1682
1453     3675       1072
763      8640       1547
933     11670       1905
436     10667       1661
# Transformed data
print(train_t[TARGET_NUMERIC_FEATURES].head())

在这里我们观察离散化后的变量:

          LotArea  GrLivArea
Id
136         0          2
1453        0          1
763         0          2
933         0          2
436         0          2

转换后的数据现在包含对应于有序计算桶的离散值(0 为第一个,bins-1 为最后一个)。

现在,让我们通过创建条形图来检查每个箱的观察次数:

train_t['GrLivArea'].value_counts().sort_index().plot.bar()
plt.ylabel('Number of houses')
plt.show()

正如我们在下图中看到的,区间包含不同数量的观测值。这与直方图的输出类似:

../../_images/equalwidthdiscretisation.png

等宽离散化不会改善值在值范围内的分布。如果变量是偏斜的,离散化后它仍然会是偏斜的。

最后,由于 return_object 参数的默认值为 False,转换器输出整数变量:

train_t[TARGET_NUMERIC_FEATURES].dtypes
LotArea      int64
GrLivArea    int64
dtype: object

返回变量作为对象#

Feature-engine 中的分类编码器默认设计为处理类型为对象的变量。因此,为了进一步使用 Feature-engine 的编码器对离散化输出进行编码,我们可以设置 return_object=True。这将返回转换后的变量为对象类型。

假设我们想要获得变量与目标之间的单调关系。我们可以通过将 return_object 设置为 True 来无缝实现这一点。关于如何使用此功能的教程可以在 这里 找到。

返回 bin 边界#

如果我们想输出区间的边界而不是整数,我们可以将 return_boundaries 设置为 True

# Set up the discretization transformer
disc = EqualFrequencyDiscretiser(
    bins=10,
    variables=TARGET_NUMERIC_FEATURES,
    return_boundaries=True)

# Fit the transformer
disc.fit(X_train)

# Transform test set & visualize limit
test_t = disc.transform(X_test)

# Visualize output (boundaries)
print(test_t[TARGET_NUMERIC_FEATURES].head())

在以下输出中,我们可以看到转换后的变量现在显示了区间限制。虽然我们不能使用这些变量来训练机器学习模型,与被离散化为整数的变量相反,但它们在这种格式下对数据分析非常有用,并且它们也可以传递给任何 Feature-engine 编码器进行进一步处理。

             LotArea         GrLivArea
Id
893   (-inf, 22694.5]   (864.8, 1395.6]
1106  (-inf, 22694.5]  (2457.2, 2988.0]
414   (-inf, 22694.5]   (864.8, 1395.6]
523   (-inf, 22694.5]  (1395.6, 1926.4]
1037  (-inf, 22694.5]  (1395.6, 1926.4]

另见#

对于其他分箱技术,请查看以下资源:

也请查看:

附加资源#

有关如何使用此转换器的更多详细信息,请查看:

有关此方法和其他特征工程方法的更多详细信息,请查看以下资源:

../../_images/feml.png

机器学习的特征工程#











或者阅读我们的书:

../../_images/cookbook.png

Python 特征工程手册#














我们的书籍和课程都适合初学者和更高级的数据科学家。通过购买它们,您正在支持 Feature-engine 的主要开发者 Sole。