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

Posted

技术标签:

【中文标题】标准化和缩放 MNIST 数据集的正确方法【英文标题】:Correct way of normalizing and scaling the MNIST dataset 【发布时间】:2020-12-24 00:32:16 【问题描述】:

我到处找,但找不到我想要的。基本上,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))

这会输出以下内容

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

但是很明显,以上都没有!结果数据 1) 不会介于 [0, 1] 之间,并且不会有平均值 0 或标准 1。事实上,这就是我们正在做的事情:

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

这与这个非常不同

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

其中scaled_data 就是data / 255

【问题讨论】:

【参考方案1】:

Euler_Salter

我可能发现这个有点太晚了,但希望我能提供一点帮助。

假设您使用的是 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,))
        ])),

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

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

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

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

【讨论】:

这个答案解决了OP的问题所提出的关键点。【参考方案2】:

目的

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

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

示例

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

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

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


类型

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

    StandardScaler:通常是你的首选,非常常用。它通过标准化数据(即居中)工作,将它们带到STD=1Mean=0它会受到异常值的影响,只有当您的数据有 Gaussian-Like Distribution 时才应该使用它。

    MinMaxScaler:通常用于将所有数据点置于特定范围内(例如 [0-1])。 它受到异常值的影响很大,仅仅是因为它使用了Range。

    RobustScaler:它对异常值“鲁棒”,因为它根据 quantile range 缩放数据。但是,您应该知道,缩放数据中仍然存在异常值。

    MaxAbsScaler:主要用于sparse data。

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


哪一个和多少

您需要先了解您的数据集。如上所述,您需要先查看一些内容,例如:数据的分布异常值的存在 strong>,以及正在使用的算法

无论如何,除非有特殊要求,否则每个数据集都需要一个缩放器1 - 所有在一起。不过,我从来没有遇到过这种情况。


关键要点

根据上面提到的一些经验法则,可以使用不同类型的特征缩放器。

您根据要求选择一个 Scaler,而不是随机选择。

您出于某种目的缩放数据,例如,in the Random Forest Algorithm you do NOT usually need to scale。

【讨论】:

也许我的问题当时不是很清楚。问题在于人们使用了错误的均值和错误的标准差(至少看起来如此)【参考方案3】:

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

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

考虑一下,考虑 [0,1] 范围:如果数据都是小的正值,min=0 和 max=1,那么数据之和必须为正,给出一个积极的,非零的意思。同样,当 none 的数据可能与平均值相差 1.0 之多时,stdev 不能1

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


您只使用了两种转换中的一种。您使用哪一种取决于您的数据集的特征,以及 - 最终 - 哪个对您的模型更有效

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

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

new_val = (old_val - old_mean) / old_stdev

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

【讨论】:

它澄清了很多,但问题是:当值保持在[0, 255] 范围内并且数据仅被标准化(没有缩放)时,每个人似乎都使用了错误的平均值和错误的标准差。基本上,如果您将数据缩放到[0, 1],它们会使用您会发现的平均值和标准差。 没有缩放的数据的平均值和标准差(即在[0, 255]范围内)是33.3178.56。相反,标度均值和标准差(33 和 78 除以 255)是 0.13060.3081。出于某种原因,每个人都使用这两个缩放值,即使他们没有在[0, 1] 之间缩放数据。他们正在使用缩放的平均值/标准,但他们的数据没有缩放!

以上是关于标准化和缩放 MNIST 数据集的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

点云数据集的归一化(特征缩放)

python,tensorflow,CNN实现mnist数据集的训练与验证正确率

有没有像「scaler.inverse_transform()」这样的方法来获取部分缩放器参数来反规范化答案?

数据标准化

【实战篇】信用卡交易风险检测(三)

用标准3层神经网络实现MNIST识别