数据预处理

数据预处理是在各类算法的使用前对数据进行一定的操作,让数据能在训练中得到更好的使用效果,而数据有很多种,如连续型特征数据,分类型的特征数据(也称离散型)等等,因此预处理有很多种方法,依次可分为以下几种:

  • Standardization,or mean removal and variance scaling(标准化、去均值和方差按比例缩放)
  • Non-linear transformation(非线性转换)
  • Normalization(归一化)
  • Feature binarization(特征二值化)
  • Encoding categorical features(分类特征编码)
  • Imputation of missing values(缺失值插补)
  • Generating polynomial features(生成多项式特征)
  • Custom transformers(自定义转换器)

在介绍这些方法的开头,为了方便,先将某大佬的经验总结贴在这里:

  • 首先要明确有多少特征,哪些是连续的,哪些是类别的。
  • 检查有没有缺失值,对确实的特征选择恰当方式进行弥补,使数据完整。
  • 对连续的数值型特征进行标准化,使得均值为0,方差为1。
  • 对类别型的特征进行one-hot编码。
  • 将需要转换成类别型数据的连续型数据进行二值化。
  • 为防止过拟合或者其他原因,选择是否要将数据进行正则化。
  • 在对数据进行初探之后发现效果不佳,可以尝试使用多项式方法,寻找非线性的关系。
  • 根据实际问题分析是否需要对特征进行相应的函数转换。

Standardization,or mean removal and variance scaling(标准化、去均值和方差按比例缩放)

  • 目的:让特征拥有零均值和单位方差,以在未来的训练中达到更好的效果
    • 实现方式:
      • 放缩scale
        1 >>> from sklearn import preprocessing
        2 >>> import numpy as np
        3 >>> X_train = np.array([[ 1., -1.,  2.],
        4 ...                     [ 2.,  0.,  0.],
        5 ...                     [ 0.,  1., -1.]])
        6 >>> X_scaled = preprocessing.scale(X_train)
        7 
        8 >>> X_scaled                                          
        9 array([[ 0\.  ..., -1.22... ,  1.33...],
        10       [ 1.22... ,  0\.  ..., -0.26...],
        11       [-1.22... ,  1.22... , -1.06...]])
        
      • 经过缩放后的数据具有零均值以及标准方差
        1 >>> X_scaled.mean(axis=0)
        2 array([ 0.,  0.,  0.])
        3 
        4 >>> X_scaled.std(axis=0)
        5 array([ 1.,  1.,  1.])
        
    • 另一种实现方式:
      • StandardScaler模块
        • 它实现了转化器的API来计算训练集上的平均值和标准偏差,以便以后能够在测试集上重新应用相同的变换
        • 这是相当好的一个功能。可以对训练数据,测试数据应用相同的转换,以后有新的数据进来也可以直接调用,不用再重新把数据放在一起再计算一次了
      • 使用方法
        • 调用fit方法,根据已有的训练数据创建一个标准化的转换器
          1 >>> scaler = preprocessing.StandardScaler().fit(X_train)
          2 >>> scaler
          3 StandardScaler(copy=True, with_mean=True, with_std=True)
          
        • 使用上面这个转换器去转换训练数据x,调用transform方法
          1 >>> scaler.transform(X_train)                           
          2 array([[ 0\...., -1.22...,  1.33...],
          3       [ 1.22...,  0\. ..., -0.26...],
          4       [-1.22...,  1.22..., -1.06...]])
          
        • 比如现在又来了一组新的样本,也想得到相同的转换
          1 >>> X_test = [[-1., 1., 0.]]
          2 >>> scaler.transform(X_test)                
          3 array([[-2.44...,  1.22..., -0.26...]])
          
      • 注意:StandardScaler()中可以传入两个参数:with_mean,with_std.这两个都是布尔型的参数,默认情况下都是true,但也可以自定义成false.即不要均值中心化或者不要方差规模化为1.
    • 实践操作
      • 验证缩放情况
        1 >>>from sklearn import preprocessing
        2 >>>import numpy as np
        3 >>>y = np.array([[ 1., 0.,  0.],
        4                  [ 2., 0.,  0.],
        5                  [ 0., 0.,  0.]])
        6 >>>y_scaled = preprocessing.scale(y)
        7 >>>y_scaled
        8 array([[ 0.        ,  0.        ,  0.        ],
        9        [ 1.22474487,  0.        ,  0.        ],
        10       [-1.22474487,  0.        ,  0.        ]]
        
      • 再看一个例子
        1 >>>z = np.array([[ 1., 0.,  1.],
        2                  [ 0., 1.,  2.],
        3                  [ 0., 0.,  0.]])
        4 >>>z_scaled = preprocessing.scale(z)
        5 >>>z_scaled
        6 array([[ 1.41421356, -0.70710678,  0.        ],
        7        [-0.70710678,  1.41421356,  1.22474487],
        8        [-0.70710678, -0.70710678, -1.22474487]])
        
        • 可以明显发现,放缩scale是按照列为单位进行放缩,中心点始终为0,而大小规模是根据数值进而让方差为1才算出来的
      • 验证均值和方差是否为0和1
        1 >>>y_scaled.mean(axis=0)
        2 array([0., 0., 0.])
        3 >>>y_scaled.std(axis=0)
        4 array([1., 0., 0.])
        5 >>>z_scaled.mean(axis=0)
        6 array([7.40148683e-17, 7.40148683e-17, 0.00000000e+00])
        7 >>>z_scaled.std(axis=0)
        8 array([1., 1., 1.])
        
        • 注:上面的7.40148683e-17十分接近于0,所以可以视为其均值为0
      • 验证StandarScaler
        • 第一个例子
          1 >>>scaler = preprocessing.StandardScaler().fit(y)
          2 >>>scaler
          3 StandardScaler(copy=True, with_mean=True, with_std=True)
          4 >>>scaler.transform(y)
          5 array([[ 0.        ,  0.        ,  0.        ],
          6        [ 1.22474487,  0.        ,  0.        ],
          7        [-1.22474487,  0.        ,  0.        ]])
          8 >>>scaler.transform(z)
          9 array([[ 0.        ,  0.        ,  1.        ],
          10       [-1.22474487,  1.        ,  2.        ],
          11       [-1.22474487,  0.        ,  0.        ]])
          
        • 第二个例子
          1 >>>new_scaler = preprocessing.StandardScaler().fit(z)
          2 >>>new_scaler
          3 StandardScaler(copy=True, with_mean=True, with_std=True)
          4 >>>new_scaler.transform(y)
          5 array([[ 1.41421356, -0.70710678, -1.22474487],
          6        [ 3.53553391, -0.70710678, -1.22474487],
          7        [-0.70710678, -0.70710678, -1.22474487]])
          8 >>>new_scaler.transform(z)
          9 array([[ 1.41421356, -0.70710678,  0.        ],
          10       [-0.70710678,  1.41421356,  1.22474487],
          11       [-0.70710678, -0.70710678, -1.22474487]])
          
        • 由此可以发现,调用fit方法创建的标准的转换器,其传入的数据作为标准,然后transform的数据都会根据原先的数据标准计算标准化后的值,即如果训练的是z,transform的数据是y,则y的第一列会按照z的第一列的均值和方差计算,第二列会按照z的第二列,以此类推,另外,如果transform的列数大于训练的列数,则会报错
    • 将特征缩放到指定范围
      • 将特征放缩到最大值和最小值之间,通常是0和1之间
        • MinMaxScaler
        • 公式
          • 缩放后数据:x _ { s t d } = \frac { x - x _ { \min } } { x _ { \max } - x _ { \min } }
        • 代码实例:
            1 >>> X_train = np.array([[ 1., -1.,  2.],
            2 ...                     [ 2.,  0.,  0.],
            3 ...                     [ 0.,  1., -1.]])
            4 ...
            5 >>> min_max_scaler = preprocessing.MinMaxScaler()
            6 >>> X_train_minmax = min_max_scaler.fit_transform(X_train)
            7 >>> X_train_minmax
            8 array([[ 0.5        ,  0\.        ,  1\.        ],
            9        [ 1\.        ,  0.5        ,  0.33333333 ],
           10        [ 0\.        ,  1\.        ,  0\.        ]])
          
        • 当有新的测试数据进来,也可以进行相同的数据转换
            1 >>> X_test = np.array([[ -3., -1.,  4.]])
            2 >>> X_test_minmax = min_max_scaler.transform(X_test)
            3 >>> X_test_minmax
            4 array([[-1.5       ,  0\.        ,  1.66666667]])
          
        • 可以检查缩放器(scaler)属性,来观察在训练集中学习到的转换操作的基本性质
            1 >>> min_max_scaler.scale_                             
            2 array([ 0.5       ,  0.5       ,  0.33...])
            3 
            4 >>> min_max_scaler.min_                               
            5 array([ 0\.        ,  0.5       ,  0.33...])
          
      • 将每个特征的最大绝对值转换至单位大小
        • MaxAbsScaler
        • 工作原理和MinMaxScaler非常相似,但是它只通过除以每个特征的最大值将训练数据特征缩放至【-1,1】区间内,这就意味着,训练数据应该是已经零中心化或者是稀疏数据,即这个方法对中心化均值为0的数据或者稀疏的数据有意义
        • 公式
          • x _ { n e w } = \frac { x } { x _ { \max } }
        • 代码实例
            1 >>> X_train = np.array([[ 1., -1.,  2.],
            2 ...                     [ 2.,  0.,  0.],
            3 ...                     [ 0.,  1., -1.]])
            4 ...
            5 >>> max_abs_scaler = preprocessing.MaxAbsScaler()
            6 >>> X_train_maxabs = max_abs_scaler.fit_transform(X_train)
            7 >>> X_train_maxabs           # doctest +NORMALIZE_WHITESPACE^
            8 array([[ 0.5 , -1\. ,  1\. ],
            9        [ 1\. ,  0\. ,  0\. ],
           10        [ 0\. ,  1\. , -0.5]])
          
        • 当有新的测试数据进来
            1 >>> X_test = np.array([[ -3., -1.,  4.]])
            2 >>> X_test_maxabs = max_abs_scaler.transform(X_test)
            3 >>> X_test_maxabs                 
            4 array([[-1.5, -1\. ,  2\. ]])
          
        • 检查放缩器的属性
            1 >>> max_abs_scaler.scale_         
            2 array([ 2.,  1.,  2.])
          
      • 注意:在 scale 模块中进一步提供了方便的功能。当你不想创建对象时,可以使用如 minmax_scale 以及 maxabs_scale
    • 缩放稀疏矩阵
      • 中心化稀疏(矩阵)数据会破坏数据的稀疏结构,但是缩放稀疏输入还是有意义的,尤其是当几个特征在不同的量级范围时,而MaxAbsScaler 以及 maxabs_scale 是专为缩放数据而设计的,并且是缩放数据的推荐方法;但是, scale 和 StandardScaler 也能够接受 scipy.sparse 作为输入,只要参数 with_mean=False 被准确传入它的构造器。否则会出现 ValueError 的错误,因为默认的中心化会破坏稀疏性,并且经常会因为分配过多的内存而使执行崩溃。
    • 缩放有离群值的数据
      • 如果你的数据包含许多异常值,使用均值和方差缩放可能并不是一个很好的选择,这种情况下,你可以使用 robust_scale 以及 RobustScaler 作为替代品。它们对你的数据的中心和范围使用更有鲁棒性的估计。

Non-linear transformation(非线性转换)

  • 类似于缩放, QuantileTransformer 类是将每个特征都缩放在同样的范围或分布情况下,不再是单个特征的缩放了
    • 好处:通过执行一个秩转换能够使异常的分布平滑化,并且能够比缩放更少地受到离群值的影响
    • 坏处:使特征间及特征内的关联和距离失真
  • QuantileTransformer类与quantile_transform函数提供了一个基于分位数函数的无参数转换
    • 将数据映射到了0到1的均匀分布上
      • 我们以iris数据集为例
        • 将数据集导入,并且进行划分
           1 >>> from sklearn.datasets import load_iris
           2 >>> from sklearn.model_selection import train_test_split
           3 >>> iris = load_iris()
           4 >>> X, y = iris.data, iris.target
           5 >>> X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
          
        • 对训练集部分进行非线性转换
           1 quantile_transformer = preprocessing.QuantileTransformer(random_state=0)
           2 >>> X_train_trans = quantile_transformer.fit_transform(X_train)
           3 >>> np.percentile(X_train[:, 0], [0, 25, 50, 75, 100]) 
           4 array([ 4.3,  5.1,  5.8,  6.5,  7.9])
          
          • 注:np.percentile()是对数据进行分位数处理,即X_train[:, 0]先选择了X_train的第一列所有数据,然后np.percentile()选择了排序后的0%、25%、50%、75%和100%的数据元素,总的来说,这就是一种抽查数据的手段
          • 注:X_train[:, 0]选择的第一列数据是指的萼片的厘米单位的长度,上面的输出结果array([ 4.3, 5.1, 5.8, 6.5, 7.9])是未经过转换的原数据
             1 >>> np.percentile(X_train_trans[:, 0], [0, 25, 50, 75, 100])
             2 array([ 0.00... ,  0.24...,  0.49...,  0.73...,  0.99... ])
            
          • 可以发现,经过分位数转换后,所有的数据都被映射到了【0,1】的范围内
        • 对训练集部分进行非线性转换
           1 quantile_transformer = preprocessing.QuantileTransformer(random_state=0)
           2 >>> X_train_trans = quantile_transformer.fit_transform(X_train)
           3 >>> np.percentile(X_train[:, 0], [0, 25, 50, 75, 100]) 
           4 array([ 4.3,  5.1,  5.8,  6.5,  7.9])
          
          • 注:np.percentile()是对数据进行分位数处理,即X_train[:, 0]先选择了X_train的第一列所有数据,然后np.percentile()选择了排序后的0%、25%、50%、75%和100%的数据元素,总的来说,这就是一种抽查数据的手段
          • 注:X_train[:, 0]选择的第一列数据是指的萼片的厘米单位的长度,上面的输出结果array([ 4.3, 5.1, 5.8, 6.5, 7.9])是未经过转换的原数据
           1 >>> np.percentile(X_train_trans[:, 0], [0, 25, 50, 75, 100])
           2 array([ 0.00... ,  0.24...,  0.49...,  0.73...,  0.99... ])
          
          • 可以发现,经过分位数转换后,所有的数据都被映射到了【0,1】的范围内
        • 对测试集部分进行同样的转换
          1 >>> np.percentile(X_test[:, 0], [0, 25, 50, 75, 100])
          2 array([ 4.4  ,  5.125,  5.75 ,  6.175,  7.3  ])
          3 >>> np.percentile(X_test_trans[:, 0], [0, 25, 50, 75, 100])
          4 array([ 0.01...,  0.25...,  0.46...,  0.60... ,  0.94...])
          
    • 将转换后的数据映射到正态分布
      • 方法:通过设置 output_distribution='normal'
      • 代码:
          1 >>> quantile_transformer = preprocessing.QuantileTransformer(
          2 ...     output_distribution='normal', random_state=0)
         3 >>> X_trans = quantile_transformer.fit_transform(X)
         4 >>> quantile_transformer.quantiles_ 
         5 array([[ 4.3 ...,  2   ...,  1   ...,  0.1...],
         6        [ 4.31...,  2.02...,  1.01...,  0.1...],
         7        [ 4.32...,  2.05...,  1.02...,  0.1...],
         8          ...
         9        [ 7.84...,  4.34...,  6.84...,  2.5...],
        10        [ 7.87...,  4.37...,  6.87...,  2.5...],
        11        [ 7.9 ...,  4.4 ...,  6.9 ...,  2.5...]])
        
    • 注意:输入的中值称为输出的平均值,并且以0为中心。正常输出被剪切,使得输入的最小和最大值分别对应于1e-7和1-1e-7分位数——在变换下不会变得无限大

Normalization(归一化,也称正则化)

  • 归一化 是缩放单个样本以让其具有单位范数的过程,它是将样本在向量空间模型上的一个转换,经常被使用在分类与聚类中
  • 实现方式:normalize函数
    • 函数 normalize 提供了一个快速简单的方法在类似数组的数据集上执行操作,使用 l1 或 l2 范式
    • 代码实现:
        1 >>> X = [[ 1., -1.,  2.],
        2 ...      [ 2.,  0.,  0.],
        3 ...      [ 0.,  1., -1.]]
        4 >>> X_normalized = preprocessing.normalize(X, norm='l2')
        5 
        6 >>> X_normalized                                      
        7 array([[ 0.40 ..., -0.40...,  0.81...],
        8        [ 1\.  ...,  0\. ...,  0\. ...],
        9        [ 0\.  ...,  0.70..., -0.70...]])
      
    • 注意:代码中使用的是L2范式,其公式为x _ { i j } ^ { \prime } = \frac { x _ { i j } } { \sqrt { \sum _ { i } \left( x _ { i j } \right) ^ { 2 } } }
  • 另一种实现方式:
    • preprocessing这个模块还提供了一个实用类Normalizer,实用transform方法同样也可以对新的数据进行同样的转换
    • 代码实现:
      • 根据训练数据创建一个归一化的转换器
         1 >>> normalizer = preprocessing.Normalizer().fit(X)  # fit does nothing
         2 >>> normalizer
         3 Normalizer(copy=True, norm='l2') 
        
      • 对训练数据进行归一化
        1 >>> normalizer.transform(X)                            
        2 array([[ 0.40...,  -0.40...,   0.81...],
        3        [ 1\. ...,   0\. ...,   0\. ...],
        4        [ 0\. ...,   0.70...,  -0.70...]]) 
        
      • 对新的测试数据进行归一化
        1 >>> normalizer.transform([[-1.,  1., 0.]])             
        2 array([[-0.70...,  0.70...,  0\.  ...]])
        
    • 注意:函数 normalize 和类 Normalizer 接收来自scipy.sparse的密集类数组数据和稀疏矩阵作为输入,但对于稀疏的输入数据,在被提交给高效Cython例程前,数据被转化为压缩的稀疏行形式

Feature binarization(特征二值化)

  • 特征二值化是将数值特征用阈值过滤得到布尔值的过程
  • 实现方法:Binarizer
    • 代码实现:
      1 >>> X = [[ 1., -1.,  2.],
      2 ...      [ 2.,  0.,  0.],
      3 ...      [ 0.,  1., -1.]]
      4 
      5 >>> binarizer = preprocessing.Binarizer().fit(X)  # fit does nothing
      6 >>> binarizer
      7 Binarizer(copy=True, threshold=0.0)
      8 
      9 >>> binarizer.transform(X)
      10 array([[ 1.,  0.,  1.],
      11        [ 1.,  0.,  0.],
      12        [ 0.,  1.,  0.]]) 
      
      • 注:可以发现,Binarizer函数默认的阈值是0,所以样本x所有小于等于0的值全部为0,大于0的值全部为1,变成了一个布尔型的数据集
    • 也可以为二值化器赋一个阈值
      1 >>> binarizer = preprocessing.Binarizer(threshold=1.1)
      2 >>> binarizer.transform(X)
      3 array([[ 0.,  0.,  1.],
      4        [ 1.,  0.,  0.],
      5        [ 0.,  0.,  0.]])
      
  • 注意:
    • 相比于前面的放缩 StandardScaler 和归一化 Normalizer 类的情况,预处理模块还提供了一个相似的函数 binarize ,以便不需要转换接口时可以使用
    • binarize 和 Binarizer 可以接收来自scipy.sparse的密集类数组数据和稀疏矩阵作为输入 。其中对于稀疏输入,数据被转化为压缩的稀疏行形式

Encoding categorical features(分类特征编码)

  • 我们知道特征可能是连续型的也可能是类别型的变量,比如说
    • 对于一个人,他可能的特征有以下
      • 性别:["male", "female"]
      • 洲:["from Europe", "from US", "from Asia"]
      • 浏览器使用:["uses Firefox", "uses Chrome", "uses Safari", "uses Internet Explorer"]
    • 如果,我们简单的对这些分类型的特征进行编码,比如将洲特征中的"from Europe"编码为0,"from US"编码为1, "from Asia"编码为2,然后我们综合起来,对某单个样本的数据["male", "from US", "uses Internet Explorer"]可以编码为[0,1,3],["female", "from Asia", "uses Chrome"] 可以编码为[1, 2, 1],虽然这样实现了编码,但这样的整数特征并不能在scikit-learn的估计器中直接使用,因为这样的连续输入,估计器会认为类别之间是有序的,但实际却是无序的,比如洲之间的类别数据可能是随意排序的
  • 实现方法:
    • 一种将分类特征转换为能够被scikit-learn中模型使用的编码是one-of-K或one-hot编码,在 OneHotEncoder 中实现,它可以将有n种值的一个特征变成n个二元的特征
    • 例如下表:
      特征洲经过one-hot编码的模样
      • 因此,如果经过了one-hot编码,那么一个人的洲特征是from US,那么它对应的编码就是010,其他以此类推
    • 代码实现:
      1 >>> enc = preprocessing.OneHotEncoder()
      2 >>> enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])  
      3 OneHotEncoder(categorical_features='all', dtype=<... 'numpy.float64'>,
      4  handle_unknown='error', n_values='auto', sparse=True)
      
      5 >>> enc.transform([[0, 1, 3]]).toarray()
      6 array([[ 1.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  1.]])
      
      • 注:上面的数据结果中,前两位数值表明性别编码,紧接着中间的三位数值表明洲编码,最后的四位数值表示浏览器编码(如果看不明白,可以把代码中fit的数字想象成汉字或英文即可,或者看下面的一个例子)
    • 再举个简单的实现例子:
      • 创建数据
        1 >>>enc = preprocessing.OneHotEncoder()
        2 >>>import pandas as pd
        3 >>>data = [['male'  ,'us' ],
        4            ['female','eur'],
        5            ['female','asi']] 
        6 >>>x = pd.DataFrame(data)
        7 >>>x
        8         0      1
        9   0    male    us
       10   1   female  eur
       11   2   female  asi
      
      • 进行one-hot编码
        1 >>>enc.fit(x)
        2 OneHotEncoder(categorical_features=None, categories=None,
        3        dtype=<class 'numpy.float64'>, handle_unknown='error',
        4        n_values=None, sparse=True) 
      
      • 选取样本数据进行测试
        1 >>>y = x.iloc[:1,:]
        2 >>>y
        3         0      1
        4   0   male    us
      
        5 >>>enc.transform(y).toarray()
        6 array([[0., 1., 0., 0., 1.]])
      
    • 注意:默认情况下,每个特征使用几维的数值由数据集自动推断,当然,你也可以通过使用参数n_values来精确指明每个特征中值的总个数,另外,如果训练集中有丢失的分类特征值,必须显式地设置 n_values
      • 举例如下
      1 >>> enc = preprocessing.OneHotEncoder(n_values=[2, 3, 4])
      2 >>> # 注意下面fit的数据,其中第二、三个特征是不全的 
      3 >>> # features 
      
      4 >>> enc.fit([[1, 2, 3], [0, 2, 0]])  
      5 OneHotEncoder(categorical_features='all', dtype=<... 'numpy.float64'>,
      6  handle_unknown='error', n_values=[2, 3, 4], sparse=True)
      
      7 >>> enc.transform([[1, 0, 0]]).toarray()
      8 array([[ 0.,  1.,  1.,  0.,  0.,  1.,  0.,  0.,  0.]]) 
      

Imputation of missing values(缺失值插补)

  • 许多数据集都包含缺失数据,这类数据经常被编码成空格、NaNs,或者是其他的占位符,但是这样的数据集并不能scikit-learn学习算法兼容,因为大多的学习算法都默认假设数组中的元素都是数值。所以,使用不完整的数据集的一个基本策略就是舍弃掉整行或整列包含缺失值的数据。但是这样就付出了舍弃可能有价值数据(即使是不完整的 )的代价。 因此,处理缺失数值的一个更好的策略就是从已有的数据推断出缺失的数值。
  • 目的:减少数据价值的损失
  • 实现方法:Imputer
    • Imputer类提供了估算缺失值的基本策略,它可以使用缺失值所在的行or列中的平均值、中位数或者众数来填充。
    • 代码实现:
      • 训练一个数据
      1 >>> import numpy as np
      2 >>> from sklearn.preprocessing import Imputer
      3 >>> imp = Imputer(missing_values='NaN', strategy='mean', axis=0)
      4 >>> imp.fit([[1, 2], [np.nan, 3], [7, 6]])
      5 Imputer(axis=0, copy=True, missing_values='NaN', strategy='mean', verbose=0)
      
      • 以fit的填补策略填补新的数据集中的缺失值
      1 >>> X = [[np.nan, 2], [6, np.nan], [7, 6]]
      2 >>> print(imp.transform(X))                           
      3 [[ 4\.          2\.        ]
      4  [ 6\.          3.666…     ]
      5  [ 7\.          6\.        ]] 
      
      • 注意,该代码演示的是如何使用包含缺失值的列(轴0)的平均值来替换编码为 np.nan 的缺失值,其中新的数据集填充的平均值是fit方法里的列平均值
    • Imputer 类也支持稀疏矩阵
      • 举例
        1 >>> import scipy.sparse as sp
        2 >>> X = sp.csc_matrix([[1, 2], [0, 3], [7, 6]])
        3 >>> imp = Imputer(missing_values=0, strategy='mean', axis=0)
        4 >>> imp.fit(X)
        5 Imputer(axis=0, copy=True, missing_values=0, strategy='mean', verbose=0)
      
        6 >>> X_test = sp.csc_matrix([[0, 2], [6, 0], [7, 6]])
        7 >>> print(imp.transform(X_test))                      
        8 [[ 4\.          2\.        ]
        9  [ 6\.          3.666...   ]
       10  [ 7\.          6\.        ]]
      
      • 注意,矩阵中的缺失值被编码为0,隐式地存储在了矩阵中,而填补的时候还是用的fit的数据

Generating polynomial features(生成多项式特征)

  • 在机器学习中,通过增加一些输入数据的非线性特征来增加模型的复杂度通常是有用的,一个简单通用的办法是使用多项式特征,这可以获得特征的更高维度和互相间关系的项
  • 实现方法:PolynomialFeatures
    • 比如:将 X 的特征从(x_1,x_2)转换为(1,x_1,x_2,x_1^2,x_1 x_2,x_2^2)
      1 >>> import numpy as np
      2 >>> from sklearn.preprocessing import PolynomialFeatures
      3 >>> X = np.arange(6).reshape(3, 2)
      4 >>> X                                                 
      5 array([[0, 1],
      6        [2, 3],
      7        [4, 5]])
      8 >>> poly = PolynomialFeatures(2)
      9 >>> poly.fit_transform(X)                             
      10 array([[  1.,   0.,   1.,   0.,   0.,   1.],
      11        [  1.,   2.,   3.,   4.,   6.,   9.],
      12        [  1.,   4.,   5.,  16.,  20.,  25.]])
      
    • 在一些情况下,如果只需要特征间的交互项,这可以通过设置 interaction_only=True 来得到
       1 >>> X = np.arange(9).reshape(3, 3)
       2 >>> X                                                 
       3 array([[0, 1, 2],
       4  [3, 4, 5],
       5  [6, 7, 8]])
       6 >>> poly = PolynomialFeatures(degree=3, interaction_only=True)
       7 >>> poly.fit_transform(X)                             
       8 array([[   1.,    0.,    1.,    2.,    0.,    0.,    2.,    0.],
       9        [   1.,    3.,    4.,    5.,   12.,   15.,   20.,   60.],
      10        [   1.,    6.,    7.,    8.,   42.,   48.,   56.,  336.]])
      
      • 此时,X 的特征从(x_1,x_2,x_3)转换为(1,x_1,x_2,x_3,x_1 x_2,x_1 x_3,x_2 x_3,x_1 x_2 x_3)

Custom transformers(自定义转换器)

  • 在机器学习中,可以将一个已有的 Python 函数转化为一个转换器来协助数据清理或处理,通俗的讲,就是把原始的特征放进一个函数中做转换,这个函数出来的值作为新的特征
  • 使用方法:FunctionTransformer
    • 功能:从任意函数中实现一个转换器
    • 举例:在一个管道中构建一个实现日志转换的转化器
        1 >>> import numpy as np
        2 >>> from sklearn.preprocessing import FunctionTransformer
        3 >>> transformer = FunctionTransformer(np.log1p)
        4 >>> X = np.array([[0, 1], [2, 3]])
        5 >>> transformer.transform(X)
        6 array([[ 0\.        ,  0.69314718],
        7        [ 1.09861229 ,  1.38629436]]) 
      

参考资料:
【1】Preprocessing data(sklearn官方文档)
【2】预处理数据(sklearn中文文档)
【3】预处理数据的方法总结(使用sklearn-preprocessing)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348