对 MNIST 数据集进行标准化和缩放的正确方法

Eul*_*ter 4 python machine-learning mnist pytorch

我到处找,但找不到我想要的。基本上,MNIST 数据集具有像素值在范围内的图像[0, 255]。人们说,一般来说,最好做到以下几点:

  • 将数据缩放到[0,1]范围。
  • 将数据标准化为具有零均值和单位标准偏差(data - mean) / std

不幸的是,没有人展示过如何做这两件事。它们都减去平均值0.1307并除以标准偏差0.3081。这些值基本上是数据集的均值和标准差除以 255:

from torchvision.datasets import MNIST        
import torchvision.transforms as transforms 

trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True)
print('Min Pixel Value: {} \nMax Pixel Value: {}'.format(trainset.data.min(), trainset.data.max()))
print('Mean Pixel Value {} \nPixel Values Std: {}'.format(trainset.data.float().mean(), trainset.data.float().std()))
print('Scaled Mean Pixel Value {} \nScaled Pixel Values Std: {}'.format(trainset.data.float().mean() / 255, trainset.data.float().std() / 255))
Run Code Online (Sandbox Code Playgroud)

这输出以下

Min Pixel Value: 0 
Max Pixel Value: 255
Mean Pixel Value 33.31002426147461 
Pixel Values Std: 78.56748962402344
Scaled Mean: 0.13062754273414612 
Scaled Std: 0.30810779333114624
Run Code Online (Sandbox Code Playgroud)

然而,显然这没有上述任何一项!结果数据 1) 不会介于两者之间[0, 1],也不会具有 mean0或 std 1。事实上,这就是我们正在做的:

[data - (mean / 255)] / (std / 255)

这是非常不同的

[(scaled_data) - (mean/255)] / (std/255)

scaled_data只是在哪里data / 255

小智 23

欧拉索尔特

我可能发现这个有点太晚了,但希望我能帮上一点忙。

假设您使用的是 torchvision.Transform,以下代码可用于规范化 MNIST 数据集。

        train_loader = torch.utils.data.DataLoader(
        datasets.MNIST('./data', train=True
        transform=transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
        ])),
Run Code Online (Sandbox Code Playgroud)

通常,'transforms.ToTensor()'用于将[0,255]范围内的输入数据转换为3维Tensor。该函数自动将输入数据缩放到[0,1]的范围。(这相当于将数据缩小到0,1)

因此,“transforms.Normalize(...)”中使用的平均值和标准差分别为 0.1307 和 0.3081 是有意义的。(这相当于标准化零均值和单位标准差。)

请参阅下面的链接以获得更好的解释。

https://pytorch.org/vision/stable/transforms.html

  • 这个答案解决了OP问题所提出的关键点。 (2认同)

Yah*_*hya 10

目的

特征缩放的两个最重要的原因是:

  1. 您可以缩放特征以使它们具有相同的大小(即重要性或权重)。

例子

具有两个特征的数据集:年龄和体重。年龄(以岁为单位)和重量(以克为单位)!现在,一个 20 多岁、体重只有 60 公斤的小伙子将转换为向量 = [20 岁,60000g],对于整个数据集依此类推。权重属性将在训练过程中占主导地位。这是怎样的,取决于您使用的算法的类型 - 有些比其他算法更敏感:例如神经网络,其中梯度下降的学习率受到神经网络 Thetas 大小(即权重)的影响,而后者在训练过程中与输入(即特征)相关的变化;特征缩放还可以提高收敛性。另一个例子是 K 均值聚类算法需要相同量级的特征,因为它在空间的所有方向上都是各向同性的。有趣的清单

  1. 您可以扩展功能以加快执行时间。

这很简单:与非常大的数字相比,所有这些矩阵乘法和参数求和在较小的数字下会更快(或者通过将特征与其他参数相乘而产生非常大的数字......等等)


类型

最流行的特征缩放器类型可总结如下:

  1. StandardScaler:通常是您的第一个选择,它非常常用。它通过标准化数据(即将它们居中)来工作,即将它们带到 aSTD=1Mean=0它受到异常值的影响,并且仅当您的数据具有类高斯分布时才应使用。

在此输入图像描述

  1. MinMaxScaler:通常在您想要将所有数据点置于特定范围内(例如 [0-1])时使用。它受到异常值的严重影响只是因为它使用Range

在此输入图像描述

  1. RobustScaler:它对异常值具有“鲁棒性”,因为它根据分位数范围缩放数据。但是,您应该知道,缩放后的数据中仍然存在异常值。

在此输入图像描述

  1. MaxAbsScaler:主要用于稀疏数据

在此输入图像描述

  1. Unit Normalization:它基本上将每个样本的向量缩放为具有单位范数,与样本的分布无关。

在此输入图像描述


哪一个和多少个

您需要首先了解您的数据集。如上所述,您之前需要考虑一些事情,例如:数据的分布异常值的存在以及所使用的算法

无论如何,每个数据集都需要一个缩放器,除非有特定要求,例如存在一种算法,该算法仅在数据在一定范围内均值为零且标准差为 1 时才有效。不过,我还没有遇到过这样的情况。


要点


Pru*_*une 8

我认为您误解了一个关键概念:这是两种不同且不一致的扩展操作。您只能拥有以下两者之一:

  • 均值 = 0,标准差 = 1
  • 数据范围 [0,1]

想想看,考虑 [0,1] 范围:如果数据都是小的正值,min=0 和 max=1,那么数据的总和必须是正的,给出一个正的非零均值。类似地,STDEV不能1没有数据都不可能多达从平均1.0不同。

相反,如果您的均值 = 0,则某些数据必须为负。


您可以使用只有一个两个转换。使用哪种方法取决于您的数据集的特点,以及-最后-这一个作品更好地为您的模型。

对于 [0,1] 缩放,您只需除以 255。

对于 mean=0, stdev=1 缩放,您执行您已经知道的简单线性变换:

new_val = (old_val - old_mean) / old_stdev
Run Code Online (Sandbox Code Playgroud)

这是否为您澄清,还是我完全错过了您的困惑点?

  • 它澄清了很多,但问题是这样的:当值保持在“[0, 255]”范围内并且数据仅标准化(没有缩放)时,每个人似乎都使用了错误的均值和错误的标准差。基本上,他们使用将数据缩放到“[0, 1]”时发现的平均值和标准差。 (2认同)
  • 未缩放的数据的平均值和标准差(即在“[0, 255]”范围内)为“33.31”和“78.56”。相反,缩放平均值和标准差(33 和 78 除以 255)为“0.1306”和“0.3081”。由于某种原因,每个人都使用这两个缩放值,即使他们不在“[0, 1]”之间缩放数据。他们使用缩放平均值/标准差,但他们的数据未缩放! (2认同)