如何在机器学习中使用离散化变换

数值输入变量可能具有高度偏斜或非标准分布。

这可能是由数据中的异常值、多峰分布、高度指数分布等引起的。

许多机器学习算法在数值输入变量具有标准概率分布时更喜欢或表现更好。

离散化变换提供了一种自动更改数值输入变量以具有不同数据分布的方法,这反过来又可用作预测模型的输入。

在本教程中,您将了解如何使用离散化变换将数值映射到离散类别,以进行机器学习。

完成本教程后,您将了解:

  • 许多机器学习算法在将具有非标准概率分布的数值离散化时更喜欢或表现更好。
  • 离散化变换是一种将数值输入或输出变量转换为具有离散顺序标签的技术。
  • 如何使用 KBinsDiscretizer 更改数值变量的结构和分布,以提高预测模型的性能。

启动您的项目,阅读我的新书《机器学习数据准备》,其中包含分步教程和所有示例的Python源代码文件。

让我们开始吧。

How to Use Discretization Transforms for Machine Learning

如何在机器学习中使用离散化变换
照片来自 Kate Russell,部分权利保留。

教程概述

本教程分为六个部分;它们是:

  1. 更改数据分布
  2. 离散化变换
  3. 声纳数据集
  4. 均匀离散化变换
  5. K-means 离散化变换
  6. 分位数离散化变换

更改数据分布

某些机器学习算法可能偏好或需要分类或顺序输入变量,例如某些决策树和基于规则的算法。

一些分类和聚类算法仅处理标称属性,无法处理在数值尺度上测量的属性。

— 第 296 页,《数据挖掘:实际机器学习工具和技术》,第四版,2016 年。

此外,许多机器学习算法的性能会因具有非标准概率分布的变量而下降。

这适用于分类和回归任务中的实值输入变量,以及回归任务中的实值目标变量。

某些输入变量可能具有高度偏斜的分布,例如指数分布,其中最常见的观测值聚集在一起。某些输入变量可能有异常值,导致分布高度分散。

这些和其他问题,例如非标准分布和多模态分布,可能会使数据集难以使用各种机器学习模型进行建模。

因此,通常需要将每个输入变量转换为标准概率分布。

一种方法是使用数值变量的变换来获得离散概率分布,其中每个数值都被分配一个标签,并且标签具有有序(顺序)关系。

这被称为分箱离散化变换,可以通过使数值输入变量的概率分布离散化来提高某些机器学习模型在数据集上的性能。

想开始学习数据准备吗?

立即参加我为期7天的免费电子邮件速成课程(附示例代码)。

点击注册,同时获得该课程的免费PDF电子书版本。

离散化变换

离散化变换会将数值变量映射到离散值。

分箱,也称为分类或离散化,是将定量变量转换为一组两个或多个定性桶(即类别)的过程。

— 第 129 页,《特征工程与选择》,2019 年。

变量的值被分组到离散的箱中,每个箱都分配一个唯一的整数,从而保留了箱之间的顺序关系。

箱的使用通常被称为分箱或k-分箱,其中k表示将数值变量映射到的组数。

该映射提供了值的排序,可以平滑观测值之间的关系。该变换可以应用于训练数据集中的每个数值输入变量,然后作为输入提供给机器学习模型来学习预测建模任务。

箱的确定必须包含在重采样过程中。

— 第 132 页,《特征工程与选择》,2019 年。

可以使用不同的方法将值分组为 k 个离散箱;常见技术包括:

  • 均匀:每个箱在变量的可能值范围内具有相同的宽度。
  • 分位数:每个箱具有相同数量的值,根据百分位数进行划分。
  • 聚类:识别聚类并将示例分配给每个组。

离散化变换可在 scikit-learn Python 机器学习库中通过 KBinsDiscretizer 类获得。

strategy”参数控制输入变量的划分方式,可以是“uniform”、“quantile”或“kmeans”。

n_bins”参数控制将创建的箱的数量,必须根据策略的选择来设置。例如,“uniform”是灵活的,“quantile”必须有一个“n_bins”小于观测值的数量或合理的百分位数,而“kmeans”必须使用一个可以合理找到的簇数量。

encode”参数控制变换是将每个值映射到整数值(通过设置“ordinal”或独热编码“onehot”)。顺序编码几乎总是首选,尽管独热编码可能允许模型学习组之间的非顺序关系,例如在k-means 聚类策略的情况下。

我们可以通过一个小型实际示例来演示 KBinsDiscretizer。我们可以生成一个样本 高斯随机数。然后可以使用 KBinsDiscretizer 将浮点值转换为固定数量的离散类别,并具有排序的顺序关系。

完整的示例如下所示。

运行该示例,首先创建 1,000 个高斯随机浮点值样本,并将数据绘制成直方图。

Histogram of Data With a Gaussian Distribution

具有高斯分布的数据直方图

接下来,使用 KBinsDiscretizer 将数值映射到分类值。我们将变换配置为创建 10 个类别(0 到 9),以顺序格式(整数)输出结果,并均匀划分输入数据的范围。

将打印转换后的数据样本,清楚地显示了数据预期的整数格式。

最后,创建直方图,显示 10 个离散类别以及观测值在这些组中的分布情况,遵循与具有高斯形状的原始数据相同的模式。

Histogram of Transformed Data With Discrete Categories

离散类别转换后的数据直方图

在接下来的部分,我们将仔细研究如何在实际数据集上使用离散化变换。

接下来,我们介绍数据集。

声纳数据集

声纳数据集是用于二元分类的标准机器学习数据集。

它涉及 60 个实值输入和一个二类目标变量。数据集中有 208 个示例,并且类别相当平衡。

使用重复分层的 10 折交叉验证,基线分类算法可以达到大约 53.4% 的分类准确率。最高性能数据集使用重复分层的 10 折交叉验证,大约为 88%。

数据集描述了岩石或模拟地雷的雷达回波。

您可以从这里了解更多关于数据集的信息

无需下载数据集;我们将从我们的示例中自动下载它。

首先,让我们加载并总结数据集。完整的示例列在下面。

运行示例首先总结加载数据集的形状。

这证实了 60 个输入变量、一个输出变量和 208 行数据。

提供了输入变量的统计摘要,显示值是数值,大约在 0 到 1 之间。

最后,为每个输入变量创建了一个直方图。

如果我们忽略图表的杂乱,只关注直方图本身,我们可以看到许多变量具有偏斜分布。

Histogram Plots of Input Variables for the Sonar Binary Classification Dataset

声纳二元分类数据集输入变量的直方图图

接下来,让我们在原始数据集上拟合和评估一个机器学习模型。

我们将使用 k-近邻算法,并使用默认超参数,通过 重复分层 k 折交叉验证进行评估。

完整的示例如下所示。

运行示例评估 KNN 模型在原始声纳数据集上的性能。

注意:您的结果可能因算法或评估程序的随机性,或数值精度差异而有所不同。请尝试运行示例几次并比较平均结果。

我们可以看到,该模型实现了大约 79.7% 的平均分类准确率,这表明它具有技能(优于 53.4%),并且接近良好性能(88%)。

接下来,让我们探索对数据集进行均匀离散化变换。

均匀离散化变换

均匀离散化变换将保留每个输入变量的概率分布,但会将其离散化为指定的顺序组或标签数量。

我们可以使用 KBinsDiscretizer 类并设置“strategy”参数为“uniform”来应用均匀离散化变换。我们还必须设置“n_bins”参数指定的所需 bin 数量;在本例中,我们将使用 10。

定义后,我们可以调用 fit_transform() 函数并将我们的数据集传递给它,以创建数据集的分位数变换版本。

让我们在声纳数据集上尝试一下。

创建声纳数据集的均匀离散化变换并绘制结果直方图的完整示例如下。

运行该示例会转换数据集并绘制每个输入变量的直方图。

我们可以看到,直方图的形状通常与原始数据集的形状匹配,尽管在这种情况下,每个变量都有固定的 10 个值或顺序组。

Histogram Plots of Uniform Discretization Transformed Input Variables for the Sonar Dataset

声纳数据集均匀离散化变换输入变量的直方图

接下来,让我们评估与上一节相同的 KNN 模型,但在此情况下,是在数据集的均匀离散化变换上。

完整的示例如下所示。

注意:您的结果可能因算法或评估程序的随机性,或数值精度差异而有所不同。请尝试运行示例几次并比较平均结果。

运行示例,我们可以看到均匀离散化变换将性能从没有变换时的 79.7% 准确率提升到变换后的约 82.7%。

接下来,让我们仔细看看 k-means 离散化变换。

K-means 离散化变换

K-means 离散化变换将尝试为每个输入变量拟合 k 个簇,然后将每个观测值分配给一个簇。

除非变量的经验分布复杂,否则簇的数量可能很小,例如 3-5 个。

我们可以使用 KBinsDiscretizer 类并设置“strategy”参数为“kmeans”来应用 K-means 离散化变换。我们还必须设置“n_bins”参数指定的所需 bin 数量;在本例中,我们将使用三个。

定义后,我们可以调用 fit_transform() 函数并将其传递给我们的数据集,以创建我们数据集的量化转换版本。

让我们在声纳数据集上尝试一下。

创建声纳数据集的 K-means 离散化变换并绘制结果直方图的完整示例如下。

运行该示例会转换数据集并绘制每个输入变量的直方图。

我们可以看到,每个输入变量的观测值被组织到三个组之一中,其中一些组的观测值似乎相当均匀,而另一些则不那么均匀。

Histogram Plots of K-means Discretization Transformed Input Variables for the Sonar Dataset

声纳数据集 k-means 离散化变换输入变量的直方图

接下来,让我们评估与上一节相同的 KNN 模型,但在此情况下,是在数据集的 K-means 离散化变换上。

完整的示例如下所示。

注意:您的结果可能因算法或评估程序的随机性,或数值精度差异而有所不同。请尝试运行示例几次并比较平均结果。

运行示例,我们可以看到 K-means 离散化变换将性能从没有变换时的 79.7% 准确率提升到变换后的约 81.4%,尽管略低于上一节中的均匀分布。

接下来,让我们仔细看看分位数离散化变换。

分位数离散化变换

分位数离散化变换将尝试将每个输入变量的观测值分割为 k 个组,其中分配给每个组的观测值数量大致相等。

除非有大量观测值或复杂的经验分布,否则 bin 的数量必须保持较小,例如 5-10。

我们可以使用 KBinsDiscretizer 类并设置“strategy”参数为“quantile”来应用分位数离散化变换。我们还必须设置“n_bins”参数指定的所需 bin 数量;在本例中,我们将使用 10。

以下示例应用分位数离散化变换并为每个变换后的变量创建直方图。

运行该示例会转换数据集并绘制每个输入变量的直方图。

我们可以看到,所有直方图都显示了每个输入变量的均匀概率分布,其中 10 个组中的每个组都具有相同数量的观测值。

Histogram Plots of Quantile Discretization Transformed Input Variables for the Sonar Dataset

声纳数据集分位数离散化变换输入变量的直方图

接下来,让我们评估与上一节相同的 KNN 模型,但在此情况下,是在原始数据集的分位数离散化变换上。

完整的示例如下所示。

注意:您的结果可能因算法或评估程序的随机性,或数值精度差异而有所不同。请尝试运行示例几次并比较平均结果。

运行示例,我们可以看到均匀变换将性能从没有变换时的 79.7% 准确率提升到变换后的约 84.0%,优于上一节中的均匀和 K-means 方法。

我们将 bin 数量选择为一个任意数字,本例中为 10。

可以调整此超参数以探索变换分辨率对模型结果技能的影响。

以下示例执行了此实验,并绘制了从 2 到 10 的不同“n_bins”值的平均准确率。

运行示例会报告每个“n_bins”参数值的平均分类准确率。

注意:您的结果可能因算法或评估程序的随机性,或数值精度差异而有所不同。请尝试运行示例几次并比较平均结果。

我们可以看到,令人惊讶的是,较小的值导致了更高的准确率,例如三个值达到了约 86.7% 的准确率。

创建箱线图是为了总结数据集中每个离散分箱的数量的分类准确度分数。

我们可以看到在三个分箱时准确度有一个小幅提升,而分箱数量增加时,分数下降并保持平坦。

结果突出表明,探索所选方法中不同数量的离散分箱,以查看是否能获得更好的性能,很可能会带来一些好处。

Box Plots of Number of Discrete Bins vs. Classification Accuracy of KNN on the Sonar Dataset

离散分箱数量与 KNN 在 Sonar 数据集上的分类准确度箱线图

进一步阅读

如果您想深入了解,本节提供了更多关于该主题的资源。

教程

书籍

数据集 (Dataset)

API

文章

总结

在本教程中,您将了解如何使用离散化转换将数值映射到离散类别,以用于机器学习。

具体来说,你学到了:

  • 许多机器学习算法在将具有非标准概率分布的数值离散化时更喜欢或表现更好。
  • 离散化变换是一种将数值输入或输出变量转换为具有离散顺序标签的技术。
  • 如何使用 KBinsDiscretizer 更改数值变量的结构和分布,以提高预测模型的性能。

你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。

掌握现代数据准备!

Data Preparation for Machine Learning

在几分钟内准备好您的机器学习数据

...只需几行python代码

在我的新电子书中探索如何实现
机器学习数据准备

它提供**自学教程**,并附有关于以下内容的**完整工作代码**:
*特征选择*、*RFE*、*数据清洗*、*数据转换*、*缩放*、*降维*,以及更多...

将现代数据准备技术引入
您的机器学习项目


查看内容

如何使用离散化变换进行机器学习 的 26 条回复

  1. Juan 2020 年 5 月 22 日上午 11:59 #

    嗨,Jason,
    感谢您的本教程。
    我想使用分位数离散化变换,并为随机森林模型调整分箱数量。
    您能提供一个在 R 中使用随机森林模型的示例吗?
    您对此有什么建议吗?
    在此先感谢,
    Juan

    • Jason Brownlee 2020 年 5 月 22 日下午 1:23 #

      抱歉,我没有这方面的 R 语言示例。

  2. dominique 2020 年 5 月 23 日上午 2:28 #

    嗨,Jason,

    感谢这篇非常棒的文章。运行代码并看到进展总是一种乐趣。我通过这篇文章理解了在运行任何机器学习算法之前进行离散化的必要性。

    我将上面的图与使用“StandarScaler”进行数据预处理的 Sonar 数据集的神经网络实现进行了比较,我达到了 87% 和 88% 的准确率,或者使用 Dropout (87,95%)。(在您的书籍《Python 深度学习》中)

    我的理解是,当运行 {k-近邻算法和重复分层 k-折分层 + 离散化} 或 {神经网络模型 + StandarScaler + Dropout} 的组合时,我们处于相似的准确率范围内。

    那么我的问题是:您对这两种机器学习算法有什么推荐吗?(在基于实例的 kNN 和神经网络 MLP 之间)

    谢谢,
    诚挚的问候
    Dominique

    • Jason Brownlee 2020 年 5 月 23 日上午 6:27 #

      谢谢。

      没有,始终测试一系列算法和数据预处理方法、整个建模流程,以发现最适合您数据集的方法。

  3. Daniela 2020 年 5 月 25 日下午 1:44 #

    你好 Jason,

    非常感谢您分享您的知识。我读到了一种可以帮助我们离散化目标变量的算法。我真的很想听听您对此的看法。
    https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5148156/

    • Jason Brownlee 2020 年 5 月 26 日上午 6:11 #

      不客气。

      抱歉,我不熟悉这项工作。

  4. Alex 2020 年 5 月 27 日上午 9:24 #

    你好 Jason,

    谢谢。我有一个问题,在进行分位数离散化变换时,是否应该对整个数据集进行?

    还是应该先分割训练集和测试集,然后只在训练集上进行?

    • Jason Brownlee 2020 年 5 月 27 日下午 1:29 #

      该变换必须在训练集上拟合,然后应用于训练集和测试集。

      当使用交叉验证时,您可以通过管道自动完成此操作。

  5. Codetru 2020 年 5 月 30 日下午 12:13 #

    非常感谢您提供信息。离散化变换解释得非常好。我真的很感谢您分享了所有内容并附带了示例。

  6. Jay 2020 年 7 月 18 日晚上 9:49 #

    这是一个非常有启发性的教程!我还想知道是否有任何方法可以量化在进行离散化变换时丢失的信息。

  7. Edu 2020 年 8 月 11 日上午 3:36 #

    这非常有意思,Jason。感谢分享。

    进行离散化后,我们如何查看不同的分箱?阈值呢?

  8. Brenda 2020 年 9 月 3 日下午 6:55 #

    嗨,Jason,

    非常感谢您分享无监督离散化方法!包括管道在内的代码示例非常有帮助。使用管道可以避免数据泄露。

    这里我有一个问题。您如何看待有监督离散化方法,例如 DecisionTreeDiscretiser?

    我正在处理 Kaggle 的泰坦尼克号比赛,并计划对年龄和费用变量进行离散化。

    • Jason Brownlee 2020 年 9 月 4 日上午 6:26 #

      尝试一下,看看它是否能提高您项目的性能。

  9. Sergiu 2020 年 9 月 5 日上午 12:47 #

    为什么对所有列应用相同的策略?当数据包含数值、类别和有序列时,如何处理?

  10. Zena 2021 年 1 月 25 日晚上 11:39 #

    嗨,Jason,

    我有一个简单的问题,
    我们如何确定分箱的数量?
    也就是说,是否有任何数值方法来选择要使用的“k 个离散分箱”的数量?

    • Jason Brownlee 2021 年 1 月 26 日上午 5:56 #

      没有,对一系列值进行网格搜索,并使用适合您数据集和所选模型的值或最佳配置。

  11. Zena 2021 年 1 月 27 日上午 5:42 #

    谢谢你

  12. mike gt 2021 年 11 月 25 日下午 3:31 #

    嗨 Jason

    假设我们有“年龄”和“收入”作为特征,我们想对它们进行分组,例如
    年龄 1-12:年龄组 A
    年龄 13-30:年龄组 B
    年龄 31-40:年龄组 C,等等

    收入 1-100:收入组 A
    收入 101-150:收入组 B
    收入 151-250:收入组 C,等等

    每个组可能有不同的范围,是否有办法“搜索”每个组的年龄和收入范围,以便在使用 Y 目标(可能是情感分析)时,每个组的年龄和收入范围对 Y 目标都是最优的?

    谢谢
    Mike

    • Adrian Tam
      Adrian Tam 2021 年 11 月 26 日上午 2:15 #

      可能您想做一些启发式搜索来找到最优解。例如,模拟退火。

  13. Mehdi 2022 年 7 月 1 日晚上 10:33 #

    你好,感谢您的教程。我有一个问题,由于 KNN 使用欧氏距离技术,我们如何在该算法中使用有序变量?

    • James Carmichael 2022 年 7 月 2 日上午 9:08 #

      Mehdi 你好… 感谢你的反馈!请详细说明你对 KNN 和有序变量的目标,以便我们能更好地帮助你。

留下回复

Machine Learning Mastery 是 Guiding Tech Media 的一部分,Guiding Tech Media 是一家领先的数字媒体出版商,专注于帮助人们了解技术。访问我们的公司网站以了解更多关于我们的使命和团队的信息。