特征工程探索之数据预处理

我在前面的几篇文章里面介绍了一些机器学习的算法,当然不是非常全面,只是大致介绍,但我觉得对我来说已经对算法有了一定的理解。但是当我想完成一个真正的数据处理任务的时候,发现还是不够,从原始数据到开始用算法训练之间还有一部分空白,这个空白就是——特征工程

我在一些文章里面都看到这种说法数据和特征决定了最后结果的上限,而算法只是用来逼近这个上限的工具。对此我深以为然,数据和选择的特征如果不好,算法再怎么巧夺天工也不可能从一堆垃圾里面找出金子。在使用sklearn做单机特征工程这篇博文里面,博主把从原始数据开始的清洗,预处理,特征选择,特征监控等都算作特征工程的一部分,所以,按照类似的分类方法我这篇文章先从数据预处理开始。

数据清洗

数据清洗可以说是非常重要的一步了,因为我们获得的原始数据很有可能有各种缺失值,并且有很多定性的特征(比如住址,性别等),这些算法都是无法处理的。
这里说明下,pandas 和sklearn都是可以用于数据预处理的。

缺失值处理

缺失值,在数据里面一般用”NaN”代替,是一定要处理的。

如果用pandas,可以直接把这条记录删除

import pandas as pd

data = pd.read_csv("file_path")
data.dropna()

利用dropna()函数可以滤除DataFrame中所有包含NaN的记录。如果采用

data.dropna(how = "all")

则删除全部为缺失值的行。
但是有时候含有NaN的记录太多,全都删除的话可能就没剩几条了,这样的话就浪费了太多的信息,这时候我们可以用能力更强的fillna()函数,来对缺失值进行进一步的处理。
比如

fillna(0)

将所有缺失值填充为0,

fillna(data.mean())

将缺失值填充为每一行的平均值,这个方法挺重要的

fillna(method = 'ffill')

这个是对每个缺失值按照他前面的值填充,同理还有’bfill’是按照后面的值填充。
还有一些其他的细节感兴趣的可以自己探索

如果用sklearn ,可以利用preprocessing库里面的Imputer
Imputer 的API为
class sklearn.preprocessing.Imputer(missing_values=’NaN’, strategy=’mean’, axis=0, ver-
bose=0, copy=True)
其中missing_values就是缺失值的符号,默认是NaN,在处理的时候所有的missing_values代表的缺失值都会被处理
strategy表示使用什么方法处理,有三种方式mean,代表用沿着axis所指示的轴的平均值来代替。median代表用沿着axis所指示的轴的中位数来代替。most_frequent代表用沿着axis所指示的轴的最普遍的值来代替。默认是mean
使用的时候用法

Imputer().fit_transform(data)

定性特征编码

实际中的数据可能是定性的,比如高,中,低,这是一种特殊的情况,因为各个值之间有可比较的关系,那么我们就可以把他们编码成2,1,0。但是有些情况一些定性的值之间没有这种关系,比如城市,可以是北京,上海,广州,如果我们把他们编码成2,1,0就引入了原本不存在的序列信息,所以正确的方式是使用向量来表示比如[1,0,0],[0,1,0],[0,0,1]分别代表三个城市,向量的每个维度就代表是否为这个城市。这叫做哑编码,在sklearn.preprocessing中有一个OneHotEncoder可以做到。

但是,OneHotEncoder的输入需要是一个整数的矩阵,自己转换比较麻烦,这里还有种方法就是利用feature_extraction中的DictVectorizer()将键值对形式的数据转换成向量,对于定性的数据自动采用哑编码。大致用法是

vec = DictVectorizer(sparse = False)
X_train  = vec.fit_transform(X_train.to_dict(orient ='record' ))

其中X_train是DataFrame,to_dict()函数可以将其变成一种字典,参数orient默认是dict,但是他产生的结果是
df.to_dict()
{‘col1’: {‘a’: 1, ‘b’: 2}, ‘col2’: {‘a’: 0.5, ‘b’: 0.75}}
这种形式的,这里我们用的是records产生的结果是
df.to_dict(‘records’)
[{‘col1’: 1.0, ‘col2’: 0.5}, {‘col1’: 2.0, ‘col2’: 0.75}]
这里面每个大括号相当于一条记录,也就是一个样本,然后DictVectorizer()再对这个结果进行处理编码。sparse参数用来确定是否生成稀疏矩和=阵。

数据标准化和归一化

单位对数据的影响是很大的,对于原始的样本,如果我们改变了某个维度上的样本的单位,可能造成这个维度上样本一下子散的很开或者收缩地很厉害。如果散的很开,说明数据在这个特征上变化很多,可能因此这个特征的重要性增加。如果突然收缩,比如对于聚类算法,本来因该分开的类就因此聚成了一个类。所以无量纲话就显得很重要。另外有很多算法在推到的时候就假设了数据的中心是0,也就是 xi=0 ∑ x i = 0 。那么如果不中心化的话,就会对结果产生影响。
所以标准化同时满足上面两个要求是很常用的方法

x=xE[x]S x ′ = x − E [ x ] S

其中S就是标准差,单位和x是一样的, E[x] E [ x ] 代表x的均值。显而易见新生成的 x x ′ 是服从 N(0,1) N ( 0 , 1 ) 的正态分布。

以上做法通过StandardScaler()实现,一般不用设置参数

from sklearn.preprocessing import StandardScaler
StandardScaler().fit_transform(data)

还有种情况就是离群点很多的情况下,标准化可能也效果不是很好,因为离群点对均值和方差都有影响,这时候可以用RobustScaler()来标准化,它对离群点的鲁棒性比较好,其API如下
sklearn.preprocessing.RobustScaler(with_centering=True, with_scaling=True, quan-
tile_range=(25.0, 75.0), copy=True)
好像是通过计算分位数,具体原理不是很清楚。

还有一种做法是归一化,归一化的做法和标准化不同,标准化在一个特征上对所有的样本标准化,归一化是把一个样本看作一个向量,然后将这个向量的范数变成1

x[i]=x[i]x[i]2 x ′ [ i ] = x [ i ] x [ i ] 2

x[i] x [ i ] 是样本向量的第i个分量。
归一化使用Normalizer()来完成

from sklearn.preprocessing import Normalizer()
Normalizer().fit_transform(data)

以上是对数据预处理的一些基本方法,在实践中切记要对数据进行标准化。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值