我们都在讲标准化、归一化,这到底是什么,有什么区别?是否是翻译的不准确的问题?|详细解析

什么是 Normalize?它干嘛的?为什么 std 和 mean 要设成 0.5?归一化和标准化,这到底是什么?

网上的说辞各执一词,没有一个统一的标准和意见。现在,笔者尽量以最严谨的方式(包括用词、公式、翻译不统一之处使用英文原文等等),把对于标准化与归一化(即所谓的Standardization与 Normalization)的最权威解释分享出来试图解释这个问题。如有纰漏,欢迎各位佬友指正 :thinking:

首先从源头讲起。让我们把脑海中的所谓 标准化 、 归一化 这些中文翻译抛到九霄云外,之所以中文里有 “标准化”、“归一化” 混用和很多人搞不清区别,是因为目前中文翻译对几种 Normalization 的翻译是有些歧义 ,尤其是部分博客文章完全混用。
通常来说,它们都是指特征工程 中的特征缩放过程,由于中文翻译的原因,网上对它们的解释也是五花八门,但其实我们不考虑它们的名字,直接看它们的作用和操作方法,可能会更容易理解。
强烈建议直接用 Normalization 来区分和理解,不用中文翻译了,这样可以省很多理解时间。

1. Feature scaling

先看维基原文。

即特征缩放,特征缩放是用来统一资料中的自变项或特征范围的方法,在资料处理中,通常会被使用在资料前处理这个步骤。(简介中,维基官方翻译巧妙地避开了对 normalization 的解释)。

Normalization 操作被用于对数据属性进行缩放,使其落在较小的范围之内(即变化到某个固定区间中),比如 [-1,1] 和 [0, 1],简单理解就是特征缩放过程。但是为什么要缩放?这里图片更为清晰直观一些:

看到了没?使用 feature scaling 时,梯度下降的收敛速度比不使用特征缩放时要快得多。
而 feature scaling 一共有四种方法:Rescaling (min-max normalization)、Mean normalization、Standardization (Z-score Normalization) 与 Scaling to unit length。
至于其余的公式、叫法、翻译、解释,本文一概不涉及。

先看公式。

2 Rescaling (min-max normalization)

x' = a + \frac{(x - \min(x)) \times (b - a)}{\max(x) - \min(x)}

用处:重新缩放特征范围,将范围缩放到 [a, b] 之间。

rescaling(直译为重缩放)为什么又叫 min-max normalization 呢?很简单,该缩放是通过引入最小、最大值(min x,max x)实现缩放。例如,假设我们有学生的体重资料,范围落在 [160 磅,200 磅],为了重新缩放这个资料,我们会先将每个学生的体重减掉 160,接着除以 40 (最大体重与最小体重的差值)。

[0,1] 的最小 - 最大值的一般公式为

x' = \frac{x - \min(x)}{\max(x) - \min(x)}

该公式的使用次数最多。

3 Mean normalization

公式为

x' = \frac{x - \mu}{\max(x) - \min(x)}

个人认为其与 min-max normalization 的区别就是将 min x 换为均值,从而使其在 x 轴上有均匀的正负分布。

4 Standardization (Z-score Normalization)

公式为

x' = \frac{x - \mu}{\sigma}

把每个特征值中的所有数据,变成平均值为 0,标准差为 1 的数据,这有点像正态分布(注意,并不是正态分布,与正态分布是否相像只取决于原始数据),见下图:


该公式也为经常使用的公式。

5 Scaling to unit length

公式:

x' = \frac{x}{\|x\|},

其中||x|| 为向量的范数.该公式笔者认为,包括所谓的 MaxAbsScaler(原始数据除以数据最大绝对值)以及 Normalizer(将每个样本的特征向量调整到单位范数(即长度为 1))。它的作用就是将原始数据简单粗暴地除以某值,以求达到缩放到 [0,1] 中的目的。

Normalize 的用法及原理?

现在我们熟悉了 feature scaling 的四个公式,回头转向最初的问题。
什么是 normalize?我们依旧不做翻译,只能说它是一种对张量作计算的方法,将某张图片转化为 normalization 形式。
那么它的计算过程是什么?
贴出源码:

import torch
from torchvision import transforms
from PIL import Image
from torch.utils.tensorboard import SummaryWriter

# 引入png格式图片
img_path = "dataset/0000.png"
img = Image.open(img_path)

# 将png格式转化为totensor格式
writer = SummaryWriter("logs")
trans_to_tensor = transforms.ToTensor()
tensor_img = trans_to_tensor(img)

# 进行normalize计算
trans_to_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])  # 前一个为均值,后一个为标准差
img_norm = trans_to_norm(tensor_img)

第一步不必多说,我们从第二步看起。
很多人都说 Normalize 是按照 x = (x - mean) / std 得来的,实则大错特错。这个用法实际上并不是这个函数的本意,只是借用了(x-mean)/std 这个公式。

  1. ToTensor 在将图片转换为 Tensor 格式时,使用了 feature scaling 中的公式 Scaling to unit length(所谓的 MaxAbsScaler),即out = in / 255,将原 tensor 缩放为 [0,1] 之间。
  2. 之后使用区间化公式 Rescaling (min-max normalization),a,b 分别取 - 1,1,将缩放为 [0,1] 区间的图像再次缩放为 [-1,1] 区间。
  3. 将a = -1,b = 1带入公式
x' = a + ((x - min(x)) * (b - a)) / (max(x) - min(x))

结合 ToTensor 后的 [0,1] 范围(此时 min (x)=0,max (x)=1),推导可得

x' = -1 + \frac{(x - 0) \times (1 - (-1))}{1 - 0} = 2x - 1

而当 mean=0.5、std=0.5 时,

(x - 0.5) / 0.5 = 2x - 1

与上述推导结果一致,所以笔者并不认为是x = (x - mean) / std,只是形式恰好为此而已。

8 个赞

感谢分享