Python sklearn学习之数据预处理——标准化

Python sklearn学习之数据预处理——标准化

1. 数据集常见标准化方式

  • min-max标准化(Min-Max-normalization)

    • 也叫离差标准化(归一化),本质是对原始数据进行线性变换,使结果落到[0,1]之间
    • 变换本质:

    (XXmin)(XmaxXmin) (X-X_{min})\over(X_{max}-X_{min})

    • 结果:变换后结果落在[0,1]之间,且无量纲
    • 优点:实现特征极小方差的鲁棒性(即稳定性)以及在稀疏矩阵中保留零元素
    • 缺点:当有新数据加入时,可能导致max和min的变化,需要重新定义

此处量纲简单理解,由于数据的不同单位出现的不同表现力,即单位

  • z-score 标准化(zero-mean-normalization)

    • 标准差标准化
    • 变换本质:

    (XXmean)(Xstd) (X-X_{mean})\over(X_{std})

    • 结果:变换后每个特征的均值为0,标准差为1
    • 适用范围:数据集最大值和最小值未知,或存在超出取值范围的离群数据的情况

2. 数据标准化实现

2.1 z-score 标准化(zero-mean-normalization)

2.1.1 StandardScaler类
  • 类定义
def __init__(self, copy=True, with_mean=True, with_std=True)
  • 参数说明
    • copy :一个可选的boolean类型值参数,默认为True,
      • True:不修改原数据,而是在原数据的一份拷贝中进行处理,并返回这份拷贝
      • False:用计算处理后的值替换原数据,并进行浅拷贝,即地址引用,但如果被标准化的数据不是np.array或scipy.sparse CSR matrix, 原来的数据还是被copy而不是被替代
    • with_mean :接受boolean型值True和False,默认为True,表示将数据均值规范到0,但是在处理稀疏矩阵或者 CSC matrices 一定要设置False不然会超内存
    • with_std :接受boolean型值True和False,默认为True,表示将数据方差规范到1
  • 常见属性说明
    • scale_: 缩放比例,同时也是标准差
    • mean_: 每个特征的平均值
    • var_: 每个特征的方差
    • n_sample_seen_: 样本数量,可以通过 patial_fit 增加
  • 类主要包含三个方法
    • fit() :计算用于以后缩放的均值和标准差
    • transform() :标准化数据
    • fit_transform() :先计算用于以后缩放的均值和标准差,再标准化
X_scaled = preprocessing.StandardScaler().fit_transform(X_train)
X_scaled = preprocessing.StandardScaler().fit(X_train).transform(X_train)

以上两句代码是等价的,其目的都是首先构造一个数据标准化转换器,之后用需要标准化的数据训练转换器以拟合数据,最后实现标准化。

在函数 fit_transform 中,其实调用的是就是fit(X_train).transform(X_train)

if y is None:
	# fit method of arity 1 (unsupervised transformation)
	return self.fit(X, **fit_params).transform(X)
else:	
    # fit method of arity 2 (supervised transformation)
	return self.fit(X, y, **fit_params).transform(X)
  • 其他函数
    • get_params(deep=True): 返回StandardScaler对象的设置参数,即StandardScaler类构造函数中设置的参数
    • **inverse_transform(X,copy=None):**按照缩放规律反向还原当前数据
    • partial_fit(X, y=None): 函数fit() 的实际实现函数,计算平均值和标准差。适合X作为连续的数据流输入
  • 实例展示
X_scaled = preprocessing.StandardScaler().fit(X_train).transform(X_train)
X_scaled
array([[ 0.        , -1.22474487,  1.33630621],
       [ 1.22474487,  0.        , -0.26726124],
       [-1.22474487,  1.22474487, -1.06904497]])

X_scaled = preprocessing.StandardScaler().fit_transform(X_train)
X_scaled
array([[ 0.        , -1.22474487,  1.33630621],
       [ 1.22474487,  0.        , -0.26726124],
       [-1.22474487,  1.22474487, -1.06904497]])
  • 原理分析

构造StandardScaler对象的实际意义在于它首先通过执行转换器的API计算测试集数据的均值和标准差,之后便可用该构造器对测试集数据进行转换。

scaler = preprocessing.StandardScaler().fit(X_train)  # 用训练集数据训练scaler
X_scaled = scaler.transform(X_train)   # 用其转换训练集是理所当然的
X_scaled
array([[ 0.        , -1.22474487,  1.33630621],
       [ 1.22474487,  0.        , -0.26726124],
       [-1.22474487,  1.22474487, -1.06904497]])

然而实际上,用训练好的转换器去转换测试集数据也是可以的

# scaler.mean_ = [1.        , 0.        , 0.33333333]
# scaler.scale_ = [0.81649658, 0.81649658, 1.24721913]
X_test = [[-1., 1., 0.]]
X_test_scaled = scaler.transform(X_test)
# [-2.44948974,  1.22474487, -0.26726124]]

上述 X_test_scaledscaler 利用前面测试集的数据得到的均值与标准差完成对测试集数据的标准化,可见它只是简单的对每个特征进行计算。

2.1.2 preprocessing.scale 函数
  • 函数定义
def scale(X, axis=0, with_mean=True, with_std=True, copy=True)
  • 参数说明
    • X :需要标准化的数组(矩阵)
    • axis :接受int型值0和1,默认为0
      • 0:对列进行标准化处理
      • 1:对行进行标准化处理
    • with_mean :接受boolean型值True和False,默认为True,表示将数据均值规范到0
    • with_std :接受boolean型值True和False,默认为True,表示将数据方差规范到1
    • copy :一个可选的boolean类型值参数,默认为True,
      • True:不修改原数据,而是在原数据的一份拷贝中进行处理,并返回这份拷贝
      • False:用计算处理后的值替换原数据,并进行浅拷贝,即地址引用
  • 实例展示
X_train = np.array([[1., -1.,  2.],
                    [2.,  0.,  0.],
                    [0.,  1., -1.]])
x_scale = preprocessing.scale(X_train)
out:
    x_scale
    array([[ 0.        , -1.22474487,  1.33630621],
       [ 1.22474487,  0.        , -0.26726124],
       [-1.22474487,  1.22474487, -1.06904497]])
    # 均值
    x_scaled.mean(axis=0)
	array([ 0.,  0.,  0.])
    # 标准差
    x_scaled.std(axis=0)
	array([ 1.,  1.,  1.])
  • 原理分析

可见数据已经缩放为标准化,其特征均值为0,标准差为1,该函数的实现方式是对每个特征,即每一列按如下公式计算:
(XXmean)(Xstd) (X-X_{mean})\over(X_{std})

2.2 min-max标准化(Min-Max-normalization)

2.2.1 MinMaxScaler类
  • 类定义
def __init__(self, feature_range=(0, 1), copy=True)
  • 参数说明

    • feature_range : 特征范围,指定标准化后的数据需要落在的范围,默认设定为[0,1]

      • 限制:feature_range参数的两个值分别表示最小值与最大值,其中,最小值一定要小于最大值,不然会抛出 ValueError 错误,这个错误在执行partial_fit 函数时才会报错,partial_fit 函数是 fit 函数的具体实现
      if feature_range[0] >= feature_range[1]:
      	raise ValueError("Minimum of desired feature range must be smaller"
                           " than maximum. Got %s." % str(feature_range))
      
    • copy :一个可选的boolean类型值参数,默认为True,

      • True:不修改原数据,而是在原数据的一份拷贝中进行处理,并返回这份拷贝
      • False:用计算处理后的值替换原数据,并进行浅拷贝,即地址引用
  • 常见属性说明

    • data_min_ :每个特征(列)中的最小值
    • data_max_ :每个特征(列)中最大值
    • data_range_ :每个特征(列)中最大值与最小值之差
    • scale_ :期望数据范围与数据特征(列)中实际极差之间的比值,含义是每列特征相对缩放量,计算公式为 (max-min)/(data_max_ - data_min_)
    • min_ : 期望数据最小值与数据特征(列)中实际最小值乘相对缩放量之间的差,含义是每列特征相对最小缩放值,计算公式为 min-data_min_*scale_
  • 类主要函数

    • fit() :计算用于以后缩放的最大值与最小值
    • transform() :标准化数据
    • fit_transform() :先计算用于以后缩放的最大值与最小值,再标准化
min_max_scaled = preprocessing.MinMaxScaler().fit_transform(X_train)
min_max_scaled = preprocessing.MinMaxScaler().fit(X_train).transform(X_train)

以上两句代码是等价的,其目的都是首先构造一个数据标准化转换器,之后用需要标准化的数据训练转换器以拟合数据,最后实现标准化。

  • 其他函数
    • get_params(deep=True): 返回MinMaxScaler对象的设置参数,即MinMaxScaler类构造函数中设置的参数
    • partial_fit(X, y=None): 函数fit() 的实际实现函数,计算用于以后缩放的最大值与最小值。适合X作为连续的数据流输入
    • **inverse_transform(X,copy=None):**按照缩放规律反向还原当前数据
  • 基本例子
X_train = np.array([[1., -1.,  2.],
                    [2.,  0.,  0.],
                    [0.,  1., -1.]])
min_max_scaled = preprocessing.MinMaxScaler().fit_transform(X_train)
min_max_scaled
array([[0.5       , 0.        , 1.        ],
       [1.        , 0.5       , 0.33333333],
       [0.        , 1.        , 0.        ]])
  • minmax_scale 函数

实际上,类似于 z-score 标准化,min-max 标准化也有单独的一个简单函数可以实现而不是必须构建 MinMaxScaler 类。minmax-scale 函数的参数与 MinMaxScaler 类的参数一致,实现功能也是一致。

实际上,不得不说的一点是,minmax-scale 函数本质上是构造 MinMaxScaler 对象并调用 fit_transform 函数

s = MinMaxScaler(feature_range=feature_range, copy=copy)
    if axis == 0:
        X = s.fit_transform(X)
    else:
        X = s.fit_transform(X.T).T
2.2.2 拓展

MaxAbsScaler 类的工作原理与MinMaxScaler十分相似,它的功能是将数据缩放到[-1,1]之间。但 preprocessing.MinMaxScaler(feature_range=(-1,1)).fit_transform(X_train)preprocessing.MaxAbsScaler().fit_transform(X_train) 所得到的结果并不一致

X_train
array([[ 1., -1.,  2.],
       [ 2.,  0.,  0.],
       [ 0.,  1., -1.]])
preprocessing.MaxAbsScaler().fit_transform(X_train)
array([[ 0.5, -1. ,  1. ],
       [ 1. ,  0. ,  0. ],
       [ 0. ,  1. , -0.5]])
preprocessing.MinMaxScaler(feature_range=(-1,1)).fit_transform(X_train)
array([[ 0.        , -1.        ,  1.        ],
       [ 1.        ,  0.        , -0.33333333],
       [-1.        ,  1.        , -1.        ]])

原因是MinMaxScaler 实际操作是将数据集中每个数据除以该列特征中的最大值,以此实现最大绝对值缩放操作,并不是线性的。但 MinMaxScaler 却是需要线性变换,其相对变换比例一致。

3. 其他方式的数据集预处理

3.1 稀疏矩阵数据的缩放

Tips:拓展

在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵;

与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。

稠密度:非零元素的总数比上矩阵所有元素的总数

对稀疏矩阵数据的缩放,maxabs_scale 函数与 MaxAbsScaler 类均可实现,不过前提是,训练数据应该是已经零中心化或者是稀疏数据。

Tips:数据中心化

使数据特征转换为均值为0的数据,称之为中心化。本质是将特征中每个数据减去该特征的均值

MaxAbsScaler 类以及 maxabs_scale 函数的功能十分简单,将每个元素除以该列特征中的最大值,因此它们的可选参数只有一个,不同的是,函数将原数据对象作为参数,而在转换器中,元数据是转换器调用链的其中一个环节的参数。

copy :boolean类型,默认为True,其含义即是否对原数据对象进行修改。

实际上,不得不说的一点是,maxabs_scale 函数本质上是构造 MaxAbsScaler 对象并调用 fit_transform 函数

s = MaxAbsScaler(copy=copy)
    if axis == 0:
        X = s.fit_transform(X)
    else:
        X = s.fit_transform(X.T).T

3.2 存在离群值数据的缩放

Tips:拓展

离群值:在数据中有一个或几个数值与其他数值相比差异较大,定量描述则是,如果一个数值偏离观测平均值的概率小于等于1/(2n),则该数据应当舍弃(其中n为观察例数,概率可以很据数据的分布进行估计)

对存在离群值数据的缩放,robust_scale 函数以及 RobustScaler 类均可实现

3.2.1 RobustScaler类
  • 函数定义
def __init__(self, with_centering=True, with_scaling=True,
                 quantile_range=(25.0, 75.0), copy=True):
  • 参数说明

    • with_centering :默认为True

      • 本质:对数据居中,操作分两步,首先计算列特征中位数,之后将每个数据减去对应列中位数
      # 第一步,位于fit()函数
      if self.with_centering:
          self.center_ = np.nanmedian(X, axis=0)
      # 第二步,位于transform()函数
      if self.with_centering:
          X -= self.center_
      
      • 限制:在处理稀疏矩阵或者 CSC matrices 一定要设置False不然会超内存
      if self.with_centering:
          if sparse.issparse(X):
              raise ValueError(
                  "Cannot center sparse matrices: use `with_centering=False`"
                  " instead. See docstring for motivation and alternatives.")
      
    • with_scaling :默认为True

      • 本质:将数据缩放到四分位数范围,操作分三步,第一,计算列特征在quantile_range 指定位置的百分位值;第二步,转置百分位值矩阵并在列维度计算差值;第三步将差值为0的数变为1得到列特征百分位值;第四步,将每个数据除以对应列中位数
      # 第一步,位于fit()函数
      for feature_idx in range(X.shape[1]):
      	quantiles.append(np.nanpercentile(column_data,self.quantile_range))
      # 第一步,位于fit()函数
      quantiles = np.transpose(quantiles)
      self.scale_ = quantiles[1] - quantiles[0]
      # 第三步,位于fit()函数
      self.scale_ = _handle_zeros_in_scale(self.scale_, copy=False)
      # 第四步,位于transform()函数
      if self.with_scaling:
          X /= self.scale_
      
    • quantile_range:指定百分位值的位置,一个二元数组,默认是[25.0,75.0]

    • copy :略(与前面相同)

  • 属性说明

    • center_ :训练集中每个特征的中值
    • scale_ :训练集中每个特征的(缩放)四分位数范围
  • 基本例子

X = [[1., -2.,  2.],
     [-2.,  1.,  3.],
     [4.,  1., -2.]]
transformer = RobustScaler().fit_transform(X)
transformer
array([[ 0. , -2. ,  0. ],
       [-1. ,  0. ,  0.4],
       [ 1. ,  0. , -1.6]])
  • 移除特征间的线性关联

通过使用sklearn.decomposition.PCA 并设定whiten=True 移除特征间的线性关联

  • robust_scale 函数

实现的功能与RobustScaler 类一样的功能,robust_scale 函数本质上是构造 RobustScaler 对象并调用 fit_transform 函数

s = RobustScaler(with_centering=with_centering, with_scaling=with_scaling,
                     quantile_range=quantile_range, copy=copy)
    if axis == 0:
        X = s.fit_transform(X)
    else:
        X = s.fit_transform(X.T).T

3.3 核矩阵的中心化

  • 核函数:在低维输入空间中通过某个函数就能得到等同于将输入空间映射到高维特征空间进行内积计算后的值,这个函数就称为核函数
  • 核矩阵:将N个样本,每两个样本进行一次核函数影射得到的N*N维的矩阵,称为核矩阵

设K(x,z)是由phi(x)^ T phi(z)定义的核矩阵,其中phi是将x映射到希尔伯特空间的函数。

3.3.1 KernelCenterer类

KernelCenterer 类构造过程中不需要设定任何参数,只在 fit 过程中需要传入核矩阵,之后进行转换。实质上,KernelCenterer 中心化数据的过程就是将数据集转换为零均值的归一化过程。但却不明确地计算phi(x)。可以认为它是使用sklearn.preprocessing.StandardScaler(with_std=False)phi(x) 居中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章