数据分析之数据预处理
特征工程
- 特征工程详细分解为特征使用、特征获取、特征处理、特征监控。
特征使用是指基于业务理解,尽可能找出对因变量有影响的所有自变量(特征)。找出特征后需要评价其特征的获取难度、覆盖率和准确率。
特征获取是指如何获取这些特征、如何存储这些特征。
接下来是特征处理,特征处理分为特征清洗、对单个特征的预处理、对多个特征的预处理和衍生变量。
最后是特征监控,指验证特征的有效性分析,防止特征质量下降、影响模型效果
数据预处理
- 未经特征处理存在问题:
不属于同一量纲:即特征的单位不同,不能相互比较。
信息冗余:这里主要争对定量特征,我们只关心某变量属于哪一类区间而不是具体等于具体值,这个时候需要对其值进行区间划分,比如二值化。
定性特征不能直接使用:对于某些模型不能直接使用定性特征,通常使用哑编码(又叫独热编码)的方式将定性特征转化为定量特征,假设某个定类特征有N个定类值,则处理方式是原始特征值为第i种定性值时,将第i个扩展特征赋值为1,其余扩展特征赋值为0。这样原来一个特征从形式上来看就被扩展为N个特征,这种方式不用增加调参的工作。
存在缺失值:要么剔除要么填充。
信息利用率低:不同的机器学习算法和模型对数据中信息的利用是不同的,之前提到在线性模型中,使用对定性特征哑编码可以达到非线性的效果。类似地,对定量变量多项式化,或者进行其他的转换,都能达到非线性的效果
无量纲化
无量纲化使不同量纲的数据转换到同一标准上。目前数据标准化方法有多种,归结起来可以分为直线型方法(如极值法、标准差法)、折线型方法(如三折线法)、曲线型方法(如半正态性分布)。
- 常用的无量纲化方法:min-max标准化, log函数转换,atan函数转换,z-score标准化,模糊量化法。
标准化
标准化的前提是特征值服从正态分布,标准化后,其转换成标准正态分布。标准化需要计算特征的均值和标准差,对特征进行以下处理
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
iris = load_iris()
a = StandardScaler()
b = a.fit_transform(iris.data)
print(b)
[[-9.00681170e-01 1.03205722e+00 -1.34127240e+00 -1.31297673e+00]
[-1.14301691e+00 -1.24957601e-01 -1.34127240e+00 -1.31297673e+00]
[-1.38535265e+00 3.37848329e-01 -1.39813811e+00 -1.31297673e+00]
[-1.50652052e+00 1.06445364e-01 -1.28440670e+00 -1.31297673e+00]
[-1.02184904e+00 1.26346019e+00 -1.34127240e+00 -1.31297673e+00]
...
[ 7.95669016e-01 -1.24957601e-01 8.19624347e-01 1.05353673e+00]
[ 4.32165405e-01 8.00654259e-01 9.33355755e-01 1.44795564e+00]
[ 6.86617933e-02 -1.24957601e-01 7.62758643e-01 7.90590793e-01]]
# 归一化(区间缩放) 区间缩放利用了边界值信息,将特征的取值区间缩放到某个特点的范围,例如[0, 1]等。区间缩放需要找特征中的最大最小值
from sklearn.preprocessing import MinMaxScaler
b = a.fit_transform(iris.data)
print(b)
[[-9.00681170e-01 1.03205722e+00 -1.34127240e+00 -1.31297673e+00]
[-1.14301691e+00 -1.24957601e-01 -1.34127240e+00 -1.31297673e+00]
...
[ 4.32165405e-01 8.00654259e-01 9.33355755e-01 1.44795564e+00]
[ 6.86617933e-02 -1.24957601e-01 7.62758643e-01 7.90590793e-01]]
正则化
标准化和正则化的区别,简单来说,标准化是依照特征矩阵的列处理数据,其通过求z-score的方法,将样本的特征值转换到同一量纲下。正则化是依照特征矩阵的行处理数据,其目的在于样本向量在点乘运算或其他核函数计算相似性时,拥有统一的标准,也就是说都转化为“单位向量”
Normalization主要思想是对每个样本计算其p-范数,然后对该样本中每个元素除以该范数,这样处理的结果是使得每个处理后样本的p-范数(l1-norm,l2-norm)等于1。在sklearn中有三种正则化方法,l1范数、l2范数、max范数。
from sklearn.preprocessing import Normalizer
Normalizer(norm='l2').fit_transform(iris.data)
array([[0.80377277, 0.55160877, 0.22064351, 0.0315205 ],
[0.82813287, 0.50702013, 0.23660939, 0.03380134],
[0.80533308, 0.54831188, 0.2227517 , 0.03426949],
...
[0.67467072, 0.36998072, 0.58761643, 0.25028107],
[0.69025916, 0.35097923, 0.5966647 , 0.21058754]])
normalization(归一化),regurlarization(正则化),但是这里的normalizer方法是正则化方法。
对定量特征二值化
定量特征二值化的核心在于设定一个阈值,大于阈值的赋值为1,小于等于阈值的赋值为0
from sklearn.preprocessing import Binarizer
Binarizer(threshold=3).fit_transform(iris.data)
array([[1., 1., 0., 0.],
[1., 0., 0., 0.],
[1., 1., 0., 0.],
...
[1., 0., 1., 0.],
[1., 1., 1., 0.],
[1., 0., 1., 0.]])
对特定性特征独热编码
除了使用sklearn中的OneHotEncoder类得到哑特征,还推荐使用pandas中的get_dummies方法来创建哑特征,get_dummies默认会对DataFrame中所有字符串类型的列进行独热编码,使用preproccessing库的OneHotEncoder类对数据进行独热编码的代码如下
from sklearn.preprocessing import OneHotEncoder
OneHotEncoder().fit_transform(iris.target.reshape((-1, 1)))
<150x3 sparse matrix of type '<class 'numpy.float64'>'
with 150 stored elements in Compressed Sparse Row format>
缺失值计算
对值缺失严重的可以采用dropna方法直接消除该特征或样本。
而不想丢失数据信息,保留那些非缺失值数据的同时处理缺失值,要进行处理的数据集中包含缺失值一般步骤如下:
1、使用字符串’nan’来代替数据集中的缺失值;
2、将该数据集转换为浮点型便可以得到包含np.nan的数据集;
3、使用sklearn.preprocessing.Imputer类来处理使用np.nan对缺失值进行编码过的数据集
import numpy as np
from sklearn.preprocessing import Imputer
imp = Imputer(missing_values='NaN', strategy='mean', axis=0)
x = np.array([[1,2],
[np.nan, 3],
[7,6]])
imp.fit(x)
print(x)
print(imp.transform(x))
[[ 1. 2.]
[nan 3.]
[ 7. 6.]]
[[1. 2.]
[4. 3.]
[7. 6.]]
生成多项式特征和自定义转换
常见的数据变换有基于多项式的、基于指数函数的、基于对数函数的
from sklearn.preprocessing import PolynomialFeatures
PolynomialFeatures().fit_transform(iris.data)
array([[ 1. , 5.1 , 3.5 , ..., 1.96, 0.28, 0.04],
[ 1. , 4.9 , 3. , ..., 1.96, 0.28, 0.04],
[ 1. , 4.7 , 3.2 , ..., 1.69, 0.26, 0.04],
...,
[ 1. , 6.5 , 3. , ..., 27.04, 10.4 , 4. ],
[ 1. , 6.2 , 3.4 , ..., 29.16, 12.42, 5.29],
[ 1. , 5.9 , 3. , ..., 26.01, 9.18, 3.24]])
基于单变元函数的数据变换可以使用一个统一的方式完成,使用preproccessing库的FunctionTransformer对数据进行对数函数转换的代码如下
from numpy import log1p
from sklearn.preprocessing import FunctionTransformer
FunctionTransformer(log1p).fit_transform(iris.data)
array([[1.80828877, 1.5040774 , 0.87546874, 0.18232156],
[1.77495235, 1.38629436, 0.87546874, 0.18232156],
[1.74046617, 1.43508453, 0.83290912, 0.18232156],
...
[2.01490302, 1.38629436, 1.82454929, 1.09861229],
[1.97408103, 1.48160454, 1.85629799, 1.19392247],
[1.93152141, 1.38629436, 1.80828877, 1.02961942]])