如何在 Python 中从头开始缩放机器学习数据

许多机器学习算法都期望数据能够保持一致的缩放。

在对机器学习数据进行缩放时,您应该考虑两种流行的方法。

在本教程中,您将学习如何重新缩放您的机器学习数据。阅读本教程后,您将了解:

  • 如何从头开始归一化数据。
  • 如何从头开始标准化数据。
  • 何时使用归一化而不是标准化数据。

使用我的新书《从头开始的机器学习算法》启动您的项目,其中包括所有示例的分步教程Python 源代码文件。

让我们开始吧。

  • 2018年2月更新:修正了最小/最大代码示例中的小错字。
  • **2018 年 3 月更新**:添加了下载数据集的备用链接,因为原始链接似乎已被删除。
  • 2018 年 8 月更新:测试并更新以与 Python 3.6 配合使用。
How To Prepare Machine Learning Data From Scratch With Python

如何使用 Python 从头开始准备机器学习数据
图片由 Ondra Chotovinsky 提供,保留部分权利。

描述

许多机器学习算法期望输入甚至输出数据的规模是等价的。

这有助于在通过加权输入进行预测的方法中,例如线性回归和逻辑回归。

在以复杂方式组合加权输入的方法中,例如人工神经网络和深度学习,这几乎是必需的。

在本教程中,我们将练习重新缩放一个标准机器学习数据集(CSV 格式)。

具体来说,是Pima Indians数据集。它包含768行和9列。文件中的所有值都是数字,特别是浮点值。我们将首先学习如何加载文件,然后学习如何将加载的字符串转换为数值。

教程

本教程分为3个部分:

  1. 数据归一化。
  2. 数据标准化。
  3. 何时进行归一化和标准化。

这些步骤将为您处理数据缩放提供必要的基础。

1. 归一化数据

归一化可以指代不同的技术,具体取决于上下文。

在这里,我们使用归一化来指将输入变量重新缩放到 0 到 1 的范围之间。

归一化要求您了解每个属性的最小值和最大值。

这可以从训练数据中估计,或者如果您对问题领域有深入了解,也可以直接指定。

您可以通过枚举值轻松估计数据集中每个属性的最小值和最大值。

以下代码片段定义了 **dataset_minmax()** 函数,该函数计算数据集中每个属性的最小值和最大值,然后返回这些最小值和最大值的数组。

我们可以构造一个用于测试的小型数据集,如下所示:

使用这个构造的数据集,我们可以测试我们计算每列最小和最大值的函数。

运行示例会产生以下输出。

首先,数据集以列表的列表格式打印,然后以 **column1: min,max and column2: min,max** 的格式打印每列的最小值和最大值。

例如:

一旦我们估算了每列允许的最大值和最小值,我们现在就可以将原始数据归一化到0到1的范围。

归一化列单个值的计算公式为

下面是一个名为 **normalize_dataset()** 的函数实现,该函数归一化给定数据集中每列的值。

我们可以将此函数与 **dataset_minmax()** 函数结合起来,归一化构造的数据集。

运行此示例将打印以下输出,包括归一化的数据集。

我们可以将此代码与加载CSV数据集的代码结合起来,加载并归一化Pima Indians糖尿病数据集。

下载Pima Indians数据集并将其以 **pima-indians-diabetes.csv** 的名称放置在当前目录中。

打开文件并删除底部的任何空行。

该示例首先加载数据集,并将每列的值从字符串转换为浮点值。然后从数据集中估计每列的最小值和最大值,最后对数据集中的值进行归一化。

运行示例会产生以下输出。

数据集的第一条记录在归一化前后分别打印,展示了缩放的效果。

2. 数据标准化

标准化是一种重新缩放技术,指的是将数据分布的中心置于值0,并将标准差置于值1。

均值和标准差共同用于概括正态分布,也称为高斯分布或钟形曲线。

它要求在缩放之前,已知每列值的均值和标准差。与上述归一化一样,我们可以从训练数据中估计这些值,或者利用领域知识来指定它们的值。

让我们首先创建函数,从数据集中估计每列的均值和标准差统计量。

均值描述了一组数字的中间或中心趋势。列的均值计算为该列所有值的总和除以值的总数。

下面名为 **column_means()** 的函数计算数据集中每列的平均值。

标准差描述了值与均值的平均离散程度。它可以计算为每个值与均值之间平方差之和除以值数量减1的平方根。

下面名为 **column_stdevs()** 的函数计算数据集中每列值的标准差,并假设均值已经计算出来。

同样,我们可以构造一个小型数据集来演示从数据集中估计均值和标准差。

使用Excel电子表格,我们可以估计每列的均值和标准差,如下所示:

使用构造的数据集,我们可以估计汇总统计量。

执行该示例会提供以下输出,与电子表格中计算的数字相符。

一旦计算出汇总统计量,我们就可以轻松地标准化每列中的值。

标准化给定值的计算方法如下:

下面是一个名为 **standardize_dataset()** 的函数,实现了这个方程

结合计算均值和标准差统计量的函数,我们可以标准化我们构造的数据集。

执行此示例会产生以下输出,显示了构造数据集的标准化值。

再次,我们可以演示机器学习数据集的标准化。

下面的例子演示了如何加载和标准化Pima Indians糖尿病数据集,假设它在当前工作目录中,就像之前的归一化例子一样。

运行示例会打印数据集的第一行,首先以原始加载格式打印,然后是标准化后的格式,这使我们能够看到差异以进行比较。

3. 何时进行归一化和标准化

标准化是一种假设您的数据符合正态分布的缩放技术。

如果给定的数据属性是正态的或接近正态的,这可能是要使用的缩放方法。

记录标准化过程中使用的汇总统计数据是一种良好的做法,这样您就可以在将来对要与模型一起使用的数据进行标准化时应用它们。

归一化是一种不假设任何特定分布的缩放技术。

如果您的数据不是正态分布的,请考虑在应用机器学习算法之前对其进行归一化。

记录归一化过程中使用的每列的最小值和最大值是一种良好的做法,同样,以防将来需要归一化新数据以与模型一起使用。

扩展

还有许多其他数据转换可以应用。

数据转换的目的是为了更好地将您问题中的数据结构暴露给学习算法。

可能不清楚需要预先进行哪些转换。结合试错法和探索性数据分析(图表和统计数据)可以帮助找出可能有效的方法。

以下是您可能希望研究和实现的一些额外转换:

  • 允许可配置范围的归一化,例如 -1 到 1 等。
  • 允许可配置扩散的标准化,例如距离平均值 1、2 或更多标准差。
  • 指数变换,如对数、平方根和指数。
  • 幂变换,如 Box-Cox 变换,用于修正正态分布数据中的偏度。

回顾

在本教程中,您学习了如何从头开始重新缩放机器学习数据。

具体来说,你学到了:

  • 如何从头开始归一化数据。
  • 如何从头开始标准化数据。
  • 何时对数据使用归一化或标准化。

您对数据缩放或此帖子有任何疑问吗?
在下面的评论中提出您的问题,我将尽力回答。

了解如何从零开始编写算法!

Machine Learning Algorithms From Scratch

没有库,只有 Python 代码。

...附带真实世界数据集的逐步教程

在我的新电子书中探索如何实现
从零开始实现机器学习算法

它涵盖了 18 个教程,包含 12 种顶级算法的所有代码,例如
线性回归、k-近邻、随机梯度下降等等……

最后,揭开
机器学习算法的神秘面纱

跳过学术理论。只看结果。

查看内容

对《如何使用 Python 从头开始缩放机器学习数据》的 32 条回复

  1. Daniel Armstrong 2016年10月14日 下午1:18 #

    我希望将按月交易总额用作特征。我计划使用Xgboost,从我读到的内容来看,最好使用二进制变量。归一化是否有效,或者我应该将总额分箱到十分位数,以便将其转换为二进制?

    • Jason Brownlee 2016年10月15日 上午10:15 #

      嗨,丹尼尔,

      我想你可以尝试一个模型,其中交易总额保持不变,也可以使用分箱值,还可以使用二进制值(例如高于某个阈值)。

      我不知道你正在处理的问题,但通常情况下,尝试几种不同的问题表述方式并查看哪种效果最好是个好做法。

      • Daniel Armstrong 2016年10月17日 晚上9:47 #

        感谢您的时间。

  2. Logan 2017年4月6日 晚上11:14 #

    您好,这是一个非常好的教程。但我仍然有一个疑问。如果我想使用scikit函数来归一化我的数据,然后打印它以验证它是否真的有效,我应该如何操作?
    我尝试了一些类似的操作

    scaler = MinMaxScaler(feature_range=(0, 1))
    数据集 = scaler.fit_transform(数据集)
    plt.plot(数据集)
    plt.show()

    但它不起作用。它根本不影响数据

    • Jason Brownlee 2017年4月9日 下午2:41 #

      代码看起来不错。

      尝试打印转换后的数组而不是绘制它。

  3. Jeremy 2018年4月3日 凌晨1:09 #

    嗨,Jason,

    如果我有两个模型(分类和回归),并且每个模型都输出对数损失和绝对误差。

    那么,如果我想结合输出误差,是否必须先对两个误差进行归一化,然后再进行加法?如果是,上面的归一化公式是否可以用于对两个误差进行归一化?

    • Jason Brownlee 2018年4月3日 早上6:37 #

      回归问题上的对数损失没有意义。

      • Jeremy 2018年4月3日 下午3:27 #

        抱歉,我之前的帖子可能会让你感到困惑。实际上,在我的情况下,分类问题输出对数损失误差函数,而回归问题输出绝对误差函数(MSE、MAE、R2等)。

        所以我想把这两种误差(来自分类和回归问题)加起来,并且需要先对它们进行归一化。scikit-learn 在对数损失函数中提供了归一化参数,它将返回每个样本的平均损失。但是回归损失函数,如RMSE,没有归一化参数,其平均损失输出需要手动归一化。

        您能建议我如何归一化回归问题中损失误差的最终输出吗?

        非常感谢您对此事的意见。

        • Jason Brownlee 2018年4月4日 早上6:06 #

          你为什么要规范化错误?

          最好解释误差分数而不是对其进行转换。例如,RMSE直接以输出变量的单位表示。

  4. KS 2018年10月12日 早上9:28 #

    缩放公式为 -1 -> 1 是什么?

    • Jason Brownlee 2018年10月12日 早上11:28 #

      好问题,你可以使用

      这是一个演示该函数的代码片段

  5. Michael 2019年1月12日 凌晨2:05 #

    你好 Jason,

    在您的文章中,您建议当数据呈正态分布时使用标准化,当数据不呈正态分布时使用归一化。您知道为什么会这样吗?我想我曾在其他地方看到标准化被描述为 Z 分数,但我不明白为什么不建议将计算出的非正态分布数据值作为机器学习算法的输入。即使数据是非正态分布的,机器学习算法是否仍然可以从这些输入中获取价值?

    • Jason Brownlee 2019年1月12日 早上5:42 #

      标准化将数据转换为零均值和单位标准差。对于非高斯数据,这种转换没有意义——数据不会居中,并且非高斯数据没有标准差。

  6. Grzegorz Kępisty 2019年7月23日 下午4:25 #

    早上好,Jason,

    在数据转换的背景下,我想知道如何快速检查哪种方法适用于哪种机器学习算法。有些算法要求输入范围在[0.0,1.0],有些是[-1.0, 1.0]或标准化。当我阅读sklearn算法的描述时:https://scikit-learn.cn/stable/supervised_learning.html#supervised-learning,我发现缺少这些信息。

    您推荐有关此主题的任何汇编资源吗?或者,每当遇到新的数据/问题时,都应该在研究文章中查找数据转换方法或进行抽样检查?
    此致!

    • Jason Brownlee 2019年7月24日 早上7:49 #

      更糟糕的是,有时您会通过违反规则/假设/期望而获得最佳结果。

      最好的方法是针对某种算法测试不同的转换。这是我的建议。

  7. harry 2019年10月7日 下午1:16 #

    你好 Jason,如果我想获得真实值,如何反归一化?

  8. Deependra 2019年11月19日 下午4:15 #

    您好,Jason,感谢您提供如此出色的教程。我从中学到了很多。
    目前我正在使用LSTM网络进行能源消耗的时间序列预测。我遇到了一个问题。当我开始训练时,有时会得到正确的结果,并且可以看到我的损失逐个epoch降低。但当我再次运行相同的模型时,有时训练一开始就会得到nan损失,或者有时nan损失会在代码运行几个epoch后出现。奇怪的是,即使我的损失开始收敛到一个非常低的值之后,也曾突然出现nan损失。请给我一些建议,我该怎么做。
    谢谢。

  9. Deependra 2019年11月20日 下午3:57 #

    谢谢。请建议我应该怎么做才能在训练我的 LSTM 模型时摆脱 nan 损失。

    • Jason Brownlee 2019年11月21日 早上6:02 #

      也许试试 ReLU?
      也许在拟合模型之前尝试缩放数据?

  10. Qinqing Zhang 2020年2月25日 晚上6:51 #

    你好 Jason,

    我想向您请教一个关于标准化的问题。您可以在下面的链接中看到这个问题:我们是否有必要使用训练集的均值和标准差来缩放我们的验证/测试集?
    https://stats.stackexchange.com/questions/202287/why-standardization-of-the-testing-set-has-to-be-performed-with-the-mean-and-sd

    在此先感谢您

    • Jason Brownlee 2020年2月26日 早上8:16 #

      抱歉,我没有能力为您阅读/回答链接。也许您可以用一两句话总结您的问题?

  11. Dennis Lam 2020年3月18日 晚上10:04 #

    嗨,Jason,

    我见过一个学生评论说我们必须先进行训练测试分割,然后对 X_train 和 X_test 应用归一化/标准化。这是正确的做法,而不是对整个数据集应用转换吗?

    期待您的回复。谢谢。

    • Jason Brownlee 2020年3月19日 早上6:25 #

      是的,数据准备系数是在训练集上计算的,然后将转换应用于训练集、测试集和任何其他数据集(验证集、新数据等)。

      原因是避免数据泄漏,这会导致模型性能估计出现偏差。

  12. Chinmay 2020年3月29日 凌晨2:40 #

    零均值归一化和 Z-score 归一化之间有区别吗?

  13. Adel Say 2020年4月25日 上午11:54 #

    你好 Jason,
    感谢您的教程。我有一个关于包含近40个特征的数据集的缩放方法的问题。有些特征的范围从0到1e+10,有些从0到10甚至更小,并且具有不同的分布。每个特征的最小值和最大值通过研究问题领域直接指定(而不是使用训练数据的最小值和最大值)。因此,这个缩放器专门用于这个问题。
    问题是,我是否可以使用不同的缩放函数处理某些特征,而使用另一个缩放函数处理其余特征?例如,对范围极大的特征使用幂变换器,对其他特征使用MinMaxScaler?

    如果我只使用 MinMaxScaler 进行范围 (0,1) 缩放,我认为范围较大的特征会缩放到非常接近零的小值。
    我想知道是否有某种有效的方法可以进行缩放,以便所有特征都能得到适当的缩放。
    感谢您的宝贵时间

    • Jason Brownlee 2020年4月25日 下午1:23 #

      MinMaxScaler 类允许您指定首选范围,但它适用于所有输入变量。

      如果需要其他功能,您可能需要编写一些自定义代码。

  14. Nosiba 2024年7月11日 凌晨5:02 #

    你好 Jason,
    感谢这个教程。我加载数据时遇到了这个错误,我该如何解决呢?

    错误:迭代器应该返回字符串,而不是字节(您是否以文本模式打开文件?)

发表评论

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