样本特征由于来源以及度量单位不同,它们的尺度(Scale),或者说是取值范围有可能差异很大。如果一个机器学习算法在缩放全部或者部分特征后不影响它的学习和预测,我们就称该算法具有尺度不变性(Scale Invariance)。神经网络从理论上应该具有尺度不变性,可以通过参数的调整来适应不同特征的尺度。但是尺度不同的输入特征会增加训练的难度。1
1/ 最小最大值归一化
归一化(Normalization)方法泛指把数据特征转换为相同尺度的方法。最小最大值归一化(Min-Max Normalization)是最为简单的归一化方法,通过简单的缩放将每一个特征的取值范围归一到 $[0,1]$ 或 $[-1, 1]$. 假如样本数据 $\{\boldsymbol{x}^{(n)}\}^N_{n=1}$,最小最大归一化到 $[0,1]$ 的公式为:
$$ \hat{x}^{(n)}=\frac{x^{(n)}-\min{(x^{(n)})}}{\max_n(x^{(n)})-\min_n(x^{(n)})}, $$
最小最大归一化到 $[-1,1]$ ,可以先将数据归一化到 $[0, 1]$ 之间,然后再进行平移缩放:
$$ \hat{x}^{(n)}=\frac{2}{\text{max}_n(x^{(n)})-\text{min}_n(x^{(n)})}\left(x^{(n)}-\text{min}_n(x^{(n)})\right)-1, $$
所以将数据利用最小最大归一化到某个范围 $[r_1, r_2]$ 的代码为:
import torch
import numpy as np
from sklearn import preprocessing
np.random.seed(9) # 设置随机种子为 9
def min_max_norm(X, feature_range=(0, 1)):
r1, r2 = feature_range # 将数据归一化到 [r1, r2] 之间
xmin, xmax = X.min(axis=0), X.max(axis=0) # 得到数据的最大最小值
X_std = (X - xmin) / (xmax - xmin) # 标准化到 [0, 1]
X_scaled = X_std * (r2 - r1) + r1 # 数据平移缩放到 [r1, r2]
return X_scaled
与 sklearn.preprocessing
中的 MinMaxScaler()
进行对比:
sample_size = 5
X = np.random.randn(sample_size) * 255
X = X.reshape(-1, 1)
min_max_norm(X, feature_range=(0, 1)) # 数据归一化到 [0, 1] 之间
preprocessing.MinMaxScaler(feature_range=(0, 1)).fit_transform(X.reshape(-1, 1))
# array([1. , 0.73983247, 0. , 0.98747617, 0.66033068])
min_max_norm(X, feature_range=(-1, 1)) # 数据归一化到 [-1, 1] 之间
preprocessing.MinMaxScaler(feature_range=(-1, 1)).fit_transform(X.reshape(-1, 1))
# array([ 1. , 0.47966494, -1. , 0.97495233, 0.32066137])
# 两种方法得到的结果是一样的
2/ 标准化
标准化(Standardization)也叫 Z 值归一化(Z-Score Normalization),它的作用是将每一维特征都调整为均值为 0,方差为 1. 首先计算均值与方差:
$$ \begin{aligned} \mu &=\frac{1}{N} \sum_{n=1}^{N} x^{(n)} \\ \sigma^{2} &=\frac{1}{N} \sum_{n=1}^{N}\left(x^{(n)}-\mu\right)^{2} \end{aligned} $$
然后将特征 $x^{(n)}$ 减去均值,并除以标准差,得到新的特征值 $\hat{x}^{(n)}$:
$$ \hat{x}^{(n)}=\frac{x^{(n)}-\mu}{\sigma} $$
标准差 $\sigma$ 不能为零,否则说明这一维的特征没有任何区分性,可以直接删掉。
标准化的代码:
def z_score_norm(X):
mu = X.mean() # 计算数据的均值
sigma = X.std() # 计算数据的标准差(方差的平方根)
return (X - mu) / sigma
z_score_norm(X)
preprocessing.StandardScaler().fit_transform(X)
# array([ 0.88537948, 0.17106352, -1.86022047, 0.85099404, -0.04721657])
3/ 归一化与标准化的作用2
归一化与标准化的本质其实是一种线性变换,即可以看成是对数据进行比例为 $\alpha$ 的压缩,然后再平移 $\beta$ 个单位。线性变化具有的良好性质是,线性变化不改变原始数据的数值排序。
而归一化是将数据直接缩放到一个区间内,相对来说比较「硬」,它仅仅只跟数据的最大最小值有关。标准化更加「软」,它的缩放跟每一个点都有关,通过方差(Variance)体现。
从公式上看,当数据较为集中,$\alpha$ 更小,数据在标准化后更为分散,原始数据分布广,那么 $\alpha$ 比较大,那么标准化后数据就会被集中到更为小的范围。
那么什么时候使用归一化,什么时候使用标准化?
- 如果对输出结果范围有要求,用归一化;
- 数据较为稳定,不存在极端的最大最小值,用归一化;
- 数据存在异常值或者较多噪音,用标准化;
当然使用归一化与标准化并没有一个明确的指标,可以两个方法都试一下,选择表现比较好的。