谈谈数据预处理及scikit-learn示例

浏览: 2132


数据预处理或称特征预处理,在机器学习中非常重要。

本文聊聊几种常用的特征预处理方法。

  1. 标准化

    这种方法即为对于某个特征来说,减去其均值并且除以相应的方差。这种方法适用于服从或近似服从标准正态分布(均值为0,方差为1)的数据。之所以要这么做,是为了防止某个变量的方差的阶跟其余变量的方差的阶不在一个数量级上,进而方差学习算法无法从其余变量学到本该学到的知识。

    基于scikit-learn的示例如下:

from sklearn import preprocessing

import numpy as np

X = np.array([[ 1., -1., 2.],

... [ 2., 0., 0.],

... [ 0., 1., -1.]])

X_scaled = preprocessing.scale(X)

X_scaled


array([[ 0.  ..., -1.22...,  1.33...],      
      [ 1.22...,  0.  ..., -0.26...],
     
      [-1.22...,  1.22..., -1.06...]])

经过变换后的数据均值为0,方差为1。示例如下:

X_scaled.mean(axis=0)

array([ 0.,  0.,  0.])

X_scaled.std(axis=0)

array([ 1.,  1.,  1.])

scikit-learn也提供了在训练集中保存均值和方差的功能,这样可以方便在测试集中使用已保存的均值和方差。示例如下,在训练集上:

scaler = preprocessing.StandardScaler().fit(X)

scalerStandardScaler(copy=True, with_mean=True, with_std=True)

scaler.mean_
array([ 1. ...,  0. ...,  0.33...])

scaler.scale_
array([ 0.81...,  0.81...,  1.24...])

scaler.transform(X)

array([[ 0.  ..., -1.22...,  1.33...],

      [ 1.22...,  0.  ..., -0.26...],
     
      [-1.22...,  1.22..., -1.06...]])

在测试集上:

scaler.transform([[-1.,  1., 0.]])
array([[-2.44...,  1.22..., -0.26...]])

这种方法还包括了将数据缩放到某个范围之内。通常是缩放为0到1,或者按照使得绝对值的最大值为1的方式来缩放。这种方法主要是为了考虑某个特征具有比较小的标准差的情形,并且保持数据的稀疏性。

缩放为0到1的示例如下:

X_train = np.array([[ 1., -1.,  2.],

... [ 2., 0., 0.],

... [ 0., 1., -1.]])

min_max_scaler = preprocessing.MinMaxScaler()

X_train_minmax = min_max_scaler.fit_transform(X_train)

X_train_minmax

array([[ 0.5,  0.,  1.        ],

      [ 1.,  0.5,  0.33333333],
     
      [ 0.,  1.,  0.        ]])

这种方法在测试集上的效果如下:

X_test = np.array([[ -3., -1.,  4.]])

X_test_minmax = min_max_scaler.transform(X_test)

X_test_minmax

array([[-1.5,  0.,  1.66666667]])

如果给定最大值和最小值,则

X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))

X_scaled = X_std / (max - min) + min

还有一种方法是对于每个特征直接除以绝对值最大的值或该值的绝对值。示例如下:

X_train = np.array([[ 1., -1.,  2.],

... [ 2., 0., 0.],

... [ 0., 1., -1.]])

max_abs_scaler = preprocessing.MaxAbsScaler()

X_train_maxabs = max_abs_scaler.fit_transform(X_train)

X_train_maxabs # doctest +NORMALIZE_WHITESPACE^

array([[ 0.5, -1. ,  1. ],
      [ 1. ,  0. ,  0. ],
     
      [ 0. ,  1. , -0.5]])
     
X_test = np.array([[ -3., -1., 4.]])

X_test_maxabs = max_abs_scaler.transform(X_test)

X_test_maxabs

array([[-1.5, -1. ,  2. ]])

max_abs_scaler.scale_
array([ 2.,  1.,  2.])

2. 归一化

这种方法可以使得单个样本具有单位范数。这种方法适用于需要衡量两个样本之间相似性并且利用二阶范数的情形,在文本分类中比较常用。示例如下:

X = [[ 1., -1.,  2.],

... [ 2., 0., 0.],

... [ 0., 1., -1.]]

X_normalized = preprocessing.normalize(X, norm='l2')

X_normalized

array([[ 0.40..., -0.40...,  0.81...],

      [ 1.  ...,  0.  ...,  0.  ...],
     
      [ 0.  ...,  0.70..., -0.70...]])
 normalizer = preprocessing.Normalizer().fit(X)  # fit does nothing

normalizerNormalizer(copy=True, norm='l2')
normalizer.transform(X)

array([[ 0.40..., -0.40...,  0.81...],

      [ 1.  ...,  0.  ...,  0.  ...],
     
      [ 0.  ...,  0.70..., -0.70...]])
     
normalizer.transform([[-1., 1., 0.]])
array([[-0.70...,  0.70...,  0.  ...]])

3. 二值化

这种方法比较适用于概率推理的场景。示例如下:

X = [[ 1., -1.,  2.],

... [ 2., 0., 0.],

... [ 0., 1., -1.]]

binarizer = preprocessing.Binarizer().fit(X) # fit does nothing

binarizerBinarizer(copy=True, threshold=0.0)

binarizer.transform(X)

array([[ 1.,  0.,  1.],

      [ 1.,  0.,  0.],
     
      [ 0.,  1.,  0.]])

也可以设定二值化的阈值,示例如下:

binarizer = preprocessing.Binarizer(threshold=1.1)

binarizer.transform(X)

array([[ 0.,  0.,  1.],

      [ 1.,  0.,  0.],
      [ 0.,  0.,  0.]])

4 编码类别特征

比如给定特征集合 ["male", "female"]["from Europe", "from US", "from Asia"],["uses Firefox", "uses Chrome", "uses Safari", "uses Internet Explorer"]则["male", "from US", "uses Internet Explorer"]可以表示为[0, 1, 3]["female", "from Asia", "uses Chrome"] 可以表示为 [1, 2, 1].。

实际中这些编码不能直接用作特征,不过可以通过one-hot 编码来解决这个问题。

示例如下:

enc = preprocessing.OneHotEncoder()

enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])
OneHotEncoder(categorical_features='all', dtype=<... 'float'>,

      handle_unknown='error', n_values='auto', sparse=True)
     
enc.transform([[0, 1, 3]]).toarray()

array([[ 1.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  1.]])

5 缺失值

通常可以利用均值,中位数或者出现次数最多的数来代替缺失值。

示例如下:

import numpy as np

from sklearn.preprocessing import Imputer

imp = Imputer(missing_values='NaN', strategy='mean', axis=0)

imp.fit([[1, 2], [np.nan, 3], [7, 6]])

Imputer(axis=0, copy=True, missing_values='NaN', strategy='mean', verbose=0)

X = [[np.nan, 2], [6, np.nan], [7, 6]]

print(imp.transform(X))
[[ 4.          2.        ]
[ 6.          3.666...]

[ 7.          6.        ]]

同样的,对于稀疏矩阵也适用:

import scipy.sparse as sp

X = sp.csc_matrix([[1, 2], [0, 3], [7, 6]])

imp = Imputer(missing_values=0, strategy='mean', axis=0)

imp.fit(X)Imputer(axis=0, copy=True, missing_values=0, strategy='mean', verbose=0)

X_test = sp.csc_matrix([[0, 2], [6, 0], [7, 6]])

print(imp.transform(X_test))
[[ 4.          2.        ]
[ 6.          3.666...]
[ 7.          6.        ]]

另外,特别提一下,对于缺失值,也可以利用矩阵补全来解决。

6 生成多项式特征

示例如下:

import numpy as np

from sklearn.preprocessing import PolynomialFeatures

X = np.arange(6).reshape(3, 2)

X
array([[0, 1],

      [2, 3],
     
      [4, 5]])
     
poly = PolynomialFeatures(2)

poly.fit_transform(X)

array([[  1., 0., 1., 0., 0., 1.],

      [  1., 2., 3., 4., 6., 9.],
     
      [  1., 4., 5., 16., 20., 25.]])

特征 X 由  转变为 

上面是产生非线性特征,类似的,也可以产生交互性特征。示例如下:

X = np.arange(9).reshape(3, 3)

X
array([[0, 1, 2],

      [3, 4, 5],
     
      [6, 7, 8]])
     
poly = PolynomialFeatures(degree=3, interaction_only=True)

poly.fit_transform(X)

array([[1., 0., 1., 2., 0., 0., 2., 0.],
      [1., 3., 4., 5., 12., 15., 20., 60.],
      [1., 6., 7., 8., 42., 48., 56., 336.]])

特征 X 转变为

7 自定义转换

示例如下:

import numpy as np

from sklearn.preprocessing import FunctionTransformer

transformer = FunctionTransformer(np.log1p)

X = np.array([[0, 1], [2, 3]])

transformer.transform(X)

array([[ 0.        ,0.69314718],

      [ 1.09861229,1.38629436]])

参考资料:

http://scikit-learn.org/stable/modules/preprocessing.html

http://statweb.stanford.edu/~candes/papers/MatrixCompletion.pdf

http://web.stanford.edu/~hastie/TALKS/SVD_hastie.pdf

http://pages.cs.wisc.edu/~brecht/papers/09.Recht.ImprovedMC.pdf

https://people.orie.cornell.edu/miketodd/orie6327/lec28.pdf

http://www.jmlr.org/proceedings/papers/v35/hardt14b.pdf

推荐 0
本文由 深度学习 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册