簡體   English   中英

規范化和縮放 MNIST 數據集的正確方法

[英]Correct way of normalizing and scaling the MNIST dataset

我到處都看過,但找不到我想要的東西。 基本上,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]之間,也不會具有 mean 0或 std 1 事實上,這就是我們正在做的:

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

這和這個很不一樣

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

其中scaled_data只是data / 255

我認為您誤解了一個關鍵概念:這是兩種不同且不一致的擴展操作。 您只能擁有以下兩者之一:

  • 均值 = 0,標准差 = 1
  • 數據范圍 [0,1]

想想看,考慮到 [0,1] 范圍:如果數據都是小的正值,min=0 和 max=1,那么數據的總和必須是正的,給出一個正的非零均值。 類似地,當沒有任何數據可能與平均值相差 1.0 時,stdev不能1

相反,如果您的均值 = 0,則某些數據必須為負。


您只使用了兩個轉變的一個 使用哪種方法取決於您的數據集的特點,和-最終-這一件作品更好地為您的模型。

對於 [0,1] 縮放,您只需除以 255。

對於 mean=0, stdev=1 縮放,您執行您已經知道的簡單線性變換:

new_val = (old_val - old_mean) / old_stdev

這是否為您澄清,還是我完全錯過了您的困惑點?

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 維 Tensor。 該函數自動將輸入數據縮放到 [0,1] 的范圍內。 (這相當於將數據縮小到 0,1)

因此,'transforms.Normalize(...)' 中使用的均值和標准差分別為 0.1307 和 0.3081 是有道理的。 (這等效於歸一化零均值和單位標准差。)

請參閱下面的鏈接以獲得更好的解釋。

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

目的

特征縮放的兩個最重要的原因是:

  1. 您可以縮放特征以使它們具有相同的量級(即重要性或權重)。

示例

具有兩個特征的數據集:年齡和體重。 以年為單位的年齡和以克為單位的重量! 現在,一個 20 歲、體重只有 60Kg 的家伙將轉換為向量 = [20 yrs, 60000g],對整個數據集依此類推。 在訓練過程中,權重屬性將占主導地位。 這是怎么回事,取決於您使用的算法的類型 - 有些比其他算法更敏感:例如,梯度下降的學習率受神經網絡 Thetas(即權重)大小影響的神經網絡,以及后者在訓練過程中與輸入(即特征)的相關性不同; 特征縮放也提高了收斂性。 另一個例子是 K 均值聚類算法需要相同量級的特征,因為它在空間的所有方向上都是各向同性的。 有趣的名單

  1. 您可以縮放功能以加快執行時間。

這很簡單:與非常大的數字相比,所有這些矩陣乘法和參數求和在小數字下會更快(或通過將特征乘以其他參數而產生的非常大的數字......等)


類型

最流行的特征縮放器類型可以總結如下:

  1. StandardScaler :通常是您的第一個選項,它非常常用。 它通過標准化數據(即使它們居中)來工作,即使它們達到STD=1Mean=0 它會受到 outliers 的影響,並且只有在您的數據具有Gaussian-Like Distribution時才應該使用。

在此處輸入圖片說明

  1. MinMaxScaler :通常用於將所有數據點置於特定范圍內(例如 [0-1] )。 僅僅因為它使用Range ,它就會受到異常值的嚴重影響

在此處輸入圖片說明

  1. RobustScaler :它對異常值具有穩健性”,因為它根據分位數范圍縮放數據。 但是,您應該知道,縮放后的數據中仍會存在異常值。

在此處輸入圖片說明

  1. MaxAbsScaler :主要用於稀疏數據

在此處輸入圖片說明

  1. Unit Normalization :它基本上將每個樣本的向量縮放為具有單位范數,與樣本的分布無關。

在此處輸入圖片說明


哪一個和多少

您需要先了解您的數據集。 如上所述,您需要先查看一些內容,例如:數據分布、異常值存在以及正在使用算法

無論如何,除非有特定要求,否則每個數據集都需要一個定標器,例如,如果存在一種算法,該算法僅在數據在特定范圍內並且具有零均值和標准差為 1 的情況下才有效 - 全部在一起。 盡管如此,我從未遇到過這種情況。


關鍵要點

  • 根據上面提到的一些經驗法則,可以使用不同類型的特征縮放器。

  • 您可以根據要求選擇一個 Scaler,而不是隨機選擇。

  • 您出於某種目的縮放數據,例如, 在隨機森林算法中,您通常不需要縮放

好吧,使用 torchvision.transforms.ToTensor() 將數據縮放到 [0,1],然后應用歸一化 (0.1306,0.3081)。 您可以在 Pytorch 文檔中查看它: https://pytorch.org/vision/stable/transforms.html
希望這能回答你的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM