什么是 Normalize?它干嘛的?为什么 std 和 mean 要设成 0.5?归一化和标准化,这到底是什么?
网上的说辞各执一词,没有一个统一的标准和意见。现在,笔者尽量以最严谨的方式(包括用词、公式、翻译不统一之处使用英文原文等等),把对于标准化与归一化(即所谓的Standardization与 Normalization)的最权威解释分享出来试图解释这个问题。如有纰漏,欢迎各位佬友指正 ![]()
首先从源头讲起。让我们把脑海中的所谓 标准化 、 归一化 这些中文翻译抛到九霄云外,之所以中文里有 “标准化”、“归一化” 混用和很多人搞不清区别,是因为目前中文翻译对几种 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)
用处:重新缩放特征范围,将范围缩放到 [a, b] 之间。
rescaling(直译为重缩放)为什么又叫 min-max normalization 呢?很简单,该缩放是通过引入最小、最大值(min x,max x)实现缩放。例如,假设我们有学生的体重资料,范围落在 [160 磅,200 磅],为了重新缩放这个资料,我们会先将每个学生的体重减掉 160,接着除以 40 (最大体重与最小体重的差值)。
[0,1] 的最小 - 最大值的一般公式为
该公式的使用次数最多。
3 Mean normalization
公式为
个人认为其与 min-max normalization 的区别就是将 min x 换为均值,从而使其在 x 轴上有均匀的正负分布。
4 Standardization (Z-score Normalization)
公式为
把每个特征值中的所有数据,变成平均值为 0,标准差为 1 的数据,这有点像正态分布(注意,并不是正态分布,与正态分布是否相像只取决于原始数据),见下图:
该公式也为经常使用的公式。
5 Scaling to unit length
公式:
其中||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 这个公式。
- ToTensor 在将图片转换为 Tensor 格式时,使用了 feature scaling 中的公式 Scaling to unit length(所谓的 MaxAbsScaler),即
out = in / 255,将原 tensor 缩放为 [0,1] 之间。 - 之后使用区间化公式 Rescaling (min-max normalization),a,b 分别取 - 1,1,将缩放为 [0,1] 区间的图像再次缩放为 [-1,1] 区间。
- 将a = -1,b = 1带入公式
结合 ToTensor 后的 [0,1] 范围(此时 min (x)=0,max (x)=1),推导可得
而当 mean=0.5、std=0.5 时,
与上述推导结果一致,所以笔者并不认为是x = (x - mean) / std,只是形式恰好为此而已。

