Amateur Hour

标准化与归一化 with Scikit-learn

2018-12-16

1. 范数公式

范数公式看起来很枯燥,但是对于理解机器学习的各个方面都很重要,包括模型(非常多模型的正则化都是基于范数的)和数据预处理(本文介绍的内容)。因此范数的概念真的是必需牢记。

范数的数学含义,反正我是没怎么真的搞懂。感兴趣的话,推荐这篇博文讲的挺细致的。对于机器学习来讲,通常理解下面几个概念即可。

  • L0 范数:所有非零元素个数

  • L1 范数:

$$\left | X \right | = \sum_{i=1}^{n} \left | x_{i} \right |$$

  • L2 范数:

$$\left | X \right |_{2} = $$

$$\left (\sum_{i=1}^{n} \left ( xi \right )^{2} \right )^{1/2}$$

  • Lp 范数:

$$\left | X \right |_{p} = $$

$$\left (\sum_{i=1}^{n} \left ( xi \right )^{p} \right )^{1/p}$$

2. 标准化(Standardization)

对于一个数据集,如果其某些特征不服从正态分布,那么这些特征在建模时的表现力就会比较差。同时,在机器学习算法的目标函数(例如 SVM 的 RBF 内核或线性模型的 L1 和 L2 正则化),许多目标函数的基础都是假设所有的特征都是零均值并且具有同一阶数上的方差。如果某个特征的方差比其他特征大几个数量级,那么它对最终模型的影响将远大于其他小量级的特征,导致模型质量下降。

因此,在实际情况中,我们经常忽略特征的分布形状,直接经过去均值来对某个特征进行中心化,再通过除以非常量特征(non-constant features)的标准差进行缩放。下面的标准化公式就是这个原理。

2.1 基于标准差的标准化公式:

$$x^{(i)}_{std} = \frac{x^{(i)} - \mu }{\sigma }$$

2.2 scikit-learn 示例:

1
2
3
from sklearn.preprocessing import StandardScaler

X_scaled = StandardScaler().fit_transform(X)
  • scale 是更快捷的实现
1
2
3
from sklearn.preprocessing import scale

X_scaled = scale(X)

2.3 特定范围缩放的标准化:

一种标准化是将特征缩放到给定的最小值和最大值之间,通常在零和一之间,或者也可以将每个特征的最大绝对值转换至单位大小。可以分别使用 MinMaxScalerMaxAbsScaler 实现。这样的方式可以实现特征极小的方差, 提升训练的鲁棒性。

2.4 scikit-learn 示例

原理如下所示:

1
2
X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std * (max - min) + min
1
2
3
4
from sklearn.preprocessing import MinMaxScaler

# 可通过feature_range参数指定缩放后的范围
X_scaled = MinMaxScaler(feature_range=(0, 1)).fit_transform(X)
  • MaxAbsScaler:根据每个特征最大值,将特征缩放至:[0, 1]。

2.5 大量离群值特征的标准化

当特征有大量离群值的时候,用均值和方差来做缩放很明显不大合适,这个时候可以选用RobustScaler,它利用基于 quantile 的方式进行缩放,对中心和范围有更好的估计,避免了离群值的影响。

2.6 稀疏矩阵的标准化

稀疏矩阵的标准化一直是个难题,没有很好地解决方式。因为去中心化会破坏稀疏矩阵的结构,所以比如用 StandardScaler 标准化的时候,其with_mean参数一定要设置为False


标准化比归一化要用的更多,因为像逻辑回归和支持向量机算法,刚开始训练的时候会将参数初始化为 0 或趋于 0 的随机极小值,如果是标准化的数据(均值为 0,方差为 1)对于它们而言,这更加容易利于权重的更新。

3. 归一化(Normalization)

归一化是缩放单个样本以具有单位范数的过程。范数的定义可以参考第一节。

归一化和标准化的最大区别在于: 标准化是基于特征的,是对一个特征的所有数据进行处理;而归一化是居于数据点的,是对于每个数据点(sample)做处理使  他们的范数等于 1。

scikit-learn 的实例类是Normalizer

1
2
3
4
from sklearn.preprocessing import Normalizer

# norm参数指定用的范数,默认是l2
X_scaled = Normalizer(norm='l1').fit_transform(X)

以上