sklearn数据预处理

 

 

 

1、数据预处理概述

 

数据预处理是构建特征工程的基本环境,并且是提高算法精确度的有效手段。数据预处理需要根据数据本身的特性进行,不同的格式有不同的处理要求,比如无效的要剔除,缺失值要回填和冗余维度的选择等。大致主要分为三个步骤:数据的准备、转换和输出。本文主要利用sklearn讲解转换数据的常用方法。

 

2、无量纲化

 

在机器学习算法实践中,我们往往有着将不同规格的数据转换到同一规格,或不同分布的数据转换到某个特定分布的需求,这种需求统称为将数据无量纲化。数据的无量纲化可以是线性的,也可以是非线性的。线性的无量纲化包括中心化(Zero-centered或者Mean-subtraction)处理和缩放处理(Scale)。中心化的本质是让所有记录减去一个固定值,即让数据样本数据平移到某个位置。缩放的本质是通过除以一个固定值,将数据固定在某个范围之中,取对数也算是一种缩放处理。

 

(1)preprocessing.MinMaxScaler类

 

在scikit-learn中,可以通过数据MinMaxScaler来调整数据尺度,将属性缩放到一个指定的范围,或者将数据标准化并将数据都聚集到0附近,方差为1。即先将数据移动了$min(x)$个单位,按极差$max(x)-min(x)$缩放,则数据会被收敛到[0,1]之间。而这个过程,就叫做数据归一化。归一化之后的数据服从正态分布,公式如下:

 
$$x^*=\frac{x-min(x)}{max(x)-min(x)}$$
In [170]:
from sklearn.preprocessing import MinMaxScaler  #导入类
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]      #测试数据准备
scaler = MinMaxScaler()                            #实例化
scaler = scaler.fit(data)                          #fit,在这里本质是生成min(x)和max(x)
result = scaler.transform(data)                    #通过接口导出结果
result
Out[170]:
array([[0.  , 0.  ],
       [0.25, 0.25],
       [0.5 , 0.5 ],
       [1.  , 1.  ]])
In [171]:
result_ = scaler.fit_transform(data)                #训练和导出结果一步达成
result
Out[171]:
array([[0.  , 0.  ],
       [0.25, 0.25],
       [0.5 , 0.5 ],
       [1.  , 1.  ]])
In [172]:
scaler.inverse_transform(result)                    #将归一化后的结果逆转
Out[172]:
array([[-1. ,  2. ],
       [-0.5,  6. ],
       [ 0. , 10. ],
       [ 1. , 18. ]])
In [173]:
#使用MinMaxScaler的参数feature_range实现将数据归一化到[0,1]以外的范围中
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
scaler = MinMaxScaler(feature_range=[5,10])         #依然实例化
result = scaler.fit_transform(data)                 #fit_transform一步导出结果
result
Out[173]:
array([[ 5.  ,  5.  ],
       [ 6.25,  6.25],
       [ 7.5 ,  7.5 ],
       [10.  , 10.  ]])
 

(2)preprocessing.StandardScaler类

 

正态化数据是有效的处理符合高斯分布的数据的手段,输出结果以0为中位数,方差为1,并作为假定数据符合高斯分布的算法的输入。当数据$x$按均值$\mu$中心化后,再按标准差$\sigma$缩放,数据就会服从为均值为0,方差为1的正态分布(即标准正态分布),而这个过程,就叫做数据标准化(Standardization,又称Z-score normalization),公式如下:

 
$$x^*=\frac{x-\mu}{\sigma}$$
In [174]:
from sklearn.preprocessing import StandardScaler   #导入包
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]         #测试数据准备
scaler = StandardScaler()                             #实例化
scaler.fit(data)                                      #fit,本质是生成均值和方差
Out[174]:
StandardScaler(copy=True, with_mean=True, with_std=True)
In [175]:
scaler.mean_                             #查看均值的属性mean_
Out[175]:
array([-0.12,  9.  ])
In [176]:
scaler.var_                             #查看方差的属性var_
Out[176]:
array([ 0.55, 35.  ])
In [177]:
x_std = scaler.transform(data)         #通过接口导出结果
x_std
Out[177]:
array([[-1.18, -1.18],
       [-0.51, -0.51],
       [ 0.17,  0.17],
       [ 1.52,  1.52]])
In [178]:
x_std.mean()                           #导出的结果是一个数组,用mean()查看均值
Out[178]:
0.0
In [179]:
x_std.std()                            #用std()查看方差
Out[179]:
1.0
In [180]:
scaler.fit_transform(data)             #使用fit_transform(data)一步达成结果
Out[180]:
array([[-1.18, -1.18],
       [-0.51, -0.51],
       [ 0.17,  0.17],
       [ 1.52,  1.52]])
In [181]:
scaler.inverse_transform(x_std)        #使用inverse_transform逆转标准化
Out[181]:
array([[-1. ,  2. ],
       [-0.5,  6. ],
       [ 0. , 10. ],
       [ 1. , 18. ]])
 

注意:

1.对于StandardScaler和MinMaxScaler来说,空值NaN会被当做是缺失值,在fit的时候忽略,在transform的时候保持缺失NaN的状态显示。

2.fit接口中,依然只允许导入至少二维数组,一维数组导入会报错。

 

3、缺失值处理

 

数据处理过程中,不可避免的会出现很多空值,这时就需要我们通过业务经验选择性的进行数值填充,尽量保证模型的准确性。

 

参数说明:

class sklearn.impute.SimpleImputer(missing_values=nan, strategy=’mean’, fill_value=None, verbose=0, copy=True)

1.missing_values:告诉SimpleImputer,数据中的缺失值长什么样,默认空值np.nan

2.strategy:我们填补缺失值的策略,默认均值。

  • 输入“mean”使用均值填补(仅对数值型特征可用)

  • 输入“median"用中值填补(仅对数值型特征可用)

  • 输入"most_frequent”用众数填补(对数值型和字符型特征都可用)

  • 输入“constant"表示请参考参数“fill_value"中的值(对数值型和字符型特征都可用)

3.fill_value:当参数startegy为”constant"的时候可用,可输入字符串或数字表示要填充的值,常用0。

4.copy:默认为True,将创建特征矩阵的副本,反之则会将缺失值填补到原本的特征矩阵中去。

In [ ]:
#缺失值处理代码
from sklearn.impute import SimpleImputer
import pandas as pd
#导入数据
filename = 'pima_indian.csv'
names = ['preg','plas','pres','skin','test','mass','pedi','age','class']
data = pd.read_csv(filename,names=names)
data.head()
 

image

In [183]:
#以填补年龄为例,sklearn当中特征矩阵必须是二维
Age = data.loc[:,"age"].values.reshape(-1,1)
Age[0:5]
Out[183]:
array([[50],
       [31],
       [32],
       [21],
       [33]], dtype=int64)
In [184]:
#实例化,默认均值填补
imp_mean = SimpleImputer()                             
imp_mean = imp_mean.fit_transform(Age)   
data.loc[:,"age"] = imp_median
In [185]:
#用中位数填补
imp_median = SimpleImputer(strategy="median")           
imp_median = imp_median.fit_transform(Age) 
data.loc[:,"age"] = imp_median
In [186]:
#用众数填补
imp_median = SimpleImputer(strategy="most_frequent")           
imp_median = imp_median.fit_transform(Age) 
data.loc[:,"age"] = imp_median
In [187]:
#用0填补
imp_0 = SimpleImputer(strategy="constant",fill_value=0)
imp_0 = imp_0.fit_transform(Age) 
data.loc[:,"age"] = imp_0
 

当然,此处均已年龄这个特征为例进行填充,实际应用的时候要根据业务经验来进行选择填充缺失值的方案。

 

4、分类型特征处理

 

由于很多的机器学习算法是计算数值型数据的,但现实情况下特征数据中包含很多文本数据,又不能忽略掉。比如说学历的取值可以是["小学",“初中”,“高中”,"大学"]。在这种情况下,为了让数据适应算法和库,我们必须将数据进行编码,即是说,将文字型数据转换为数值型。

 

首先介绍下编码变量类型:

名义变量:变量取值是相互独立的,彼此之间完全没有联系。比如性别男和性别女。

有序变量:变量取值不完全独立的,彼此之间有一些联系,但没有计算关系。比如本科、硕士、博士。

有距变量:各个取值之间是联系的,且是可以互相计算的。比如重量10kg、20kg、30kg。

 

(1)preprocessing.LabelEncoder类

标签专用,能够将分类转换为分类数值,是对不连续的数字或者文本进行编号(连续的会是同一个编号)。

In [ ]:
from sklearn.preprocessing import LabelEncoder
import pandas as pd
#导入数据
filename = 'info.csv'
names = ['segment','weight','building','class']
data = pd.read_csv(filename,names=names,index_col=0)
data.head()
 

image

In [189]:
#LabelEncoder编码标签
y = data.iloc[:,-1]                #要输入的是标签,不是特征矩阵,所以允许一维
le = LabelEncoder()                #实例化
le = le.fit(y)                     #导入数据
label = le.transform(y)            #transform接口调取结果
label
Out[189]:
array([0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0])
In [190]:
le.classes_                        #属性.classes_查看标签中究竟有多少类别
Out[190]:
array(['否', '是'], dtype=object)
In [191]:
data.iloc[:,-1] = label            #让标签等于我们运行出来的结果
 

(2)preprocessing.OrdinalEncoder类

特征专用,能够将分类特征转换为分类数值,其主要处理有序变量。

In [193]:
#OrdinalEncoder编码有序变量{青年,中年,老年}
Ordinal = OrdinalEncoder()
Ordinal = Ordinal.fit(data.iloc[:,0:1])
In [194]:
Ordinal.categories_                               #接口categories_对应LabelEncoder的接口classes_,一模一样的功能
Out[194]:
[array(['中年', '老年', '青年'], dtype=object)]
In [195]:
data.iloc[:,0:1] = OrdinalEncoder().fit_transform(data.iloc[:,0:1])   #让特征数据等于我们运行出来的结果
 

(3)preprocessing.OneHotEncoder类

独热编码,创建哑变量,其处理名义变量

In [197]:
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder(categories='auto')
enc.fit(data.iloc[:,1:3])
ans = enc.transform(data.iloc[:,1:3]).toarray() 
ans[0:5]           #显示编码后的前5行
Out[197]:
array([[1., 0., 0., 1., 0.],
       [0., 1., 0., 1., 0.],
       [0., 0., 1., 1., 0.],
       [0., 0., 1., 0., 1.],
       [0., 1., 0., 1., 0.]])
 

参数说明:

OneHotEncoder(n_values=’auto’, categorical_features=’all’, dtype=<class ‘numpy.float64’>, sparse=True, handle_unknown=’error’)

1.n_values=’auto’,表示每个特征使用几维的数值由数据集自动推断,即几种类别就使用几位来表示。可以设定维度比正常维度多,将未编码到的数据分类到一起。

2.categorical_features = 'all',这个参数指定了对哪些特征进行编码,默认对所有类别都进行编码。

3.dtype=<class ‘numpy.float64’> 表示编码数值格式,默认是浮点型。

4.sparse=True 表示编码的格式,默认为True,即为稀疏的格式,指定False 则就不用 toarray() 了。

5.handle_unknown=’error’,其值可以指定为 "error" 或者 "ignore",即如果碰到未知的类别,是返回一个错误还是忽略它。

 

5、连续型特征处理

 

(1)sklearn.preprocessing.Binarizer类

根据阈值将数据二值化(将特征值设置为0或1),用于处理连续型变量。大于阈值的值映射为1,而小于或等于阈值的值映射为0。默认阈值为0时,特征中所有的正值都映射到1。二值化是对文本计数数据的常见操作,分析人员可以决定仅考虑某种现象的存在与否。它还可以用作考虑布尔随机变量的估计器的预处理步骤(例如,使用贝叶斯设置中的伯努利分布建模)。

In [198]:
from sklearn import preprocessing
import numpy as np
# 创建一组特征数据,每一行表示一个样本,每一列表示一个特征
x = np.array([[1., -1., 2.],
              [2., 0., 0.],
              [0., 1., -1.]])
 
binarizer = preprocessing.Binarizer().fit(x)
binarizer.transform(x)
Out[198]:
array([[1., 0., 1.],
       [1., 0., 0.],
       [0., 1., 0.]])
In [199]:
#当然也可以自己设置这个阀值,只需传出参数threshold即可
binarizer = preprocessing.Binarizer(threshold=1.5)
binarizer.fit_transform(x)
Out[199]:
array([[0., 0., 1.],
       [1., 0., 0.],
       [0., 0., 0.]])
 

(2)preprocessing.KBinsDiscretizer

这是将连续型变量划分为分类变量的类,能够将连续型变量排序后按顺序分箱后编码。总共包含三个重要参数:

 

1.n_bins:每个特征中分箱的个数,默认5,一次会被运用到所有导入的特征

2.encode:编码的方式,默认onehot。

  • onehot:做哑变量,之后返回一个稀疏矩阵,每一列是一个特征中的一个类别,含有该 类别的样本表示为1,不含的表示为0

  • ordinal:每个特征的每个箱都被编码为一个整数,返回每一列是一个特征,每个特征下含 有不同整数编码的箱的矩阵

  • onehot-dense:做哑变量,之后返回一个密集数组。

3.strategy:用来定义箱宽的方式,默认quantile。

  • uniform:表示等宽分箱,即每个特征中的每个箱的最大值之间的差为 (特征.max() - 特征.min())/(n_bins)

  • quantile:表示等位分箱,即每个特征中的每个箱内的样本数量都相同

  • kmeans:表示按聚类分箱,每个箱中的值到最近的一维k均值聚类的簇心得距离都相同

In [200]:
from sklearn.preprocessing import KBinsDiscretizer
import numpy as np
# 创建一组特征数据,每一行表示一个样本,每一列表示一个特征
X = np.array([[1., -1., 2.],
              [2., 0., 0.],
              [0., 1., -1.]])
est = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')
est.fit_transform(X)
Out[200]:
array([[1., 0., 2.],
       [2., 1., 1.],
       [0., 2., 0.]])
In [201]:
#查看转换后分的箱:变成了一列中的三箱
set(est.fit_transform(X).ravel())
Out[201]:
{0.0, 1.0, 2.0}
In [202]:
est = KBinsDiscretizer(n_bins=3, encode='onehot', strategy='uniform')
#查看转换后分的箱:变成了哑变量
est.fit_transform(X).toarray()
Out[202]:
array([[0., 1., 0., 1., 0., 0., 0., 0., 1.],
       [0., 0., 1., 0., 1., 0., 0., 1., 0.],
       [1., 0., 0., 0., 0., 1., 1., 0., 0.]])
posted @ 2020-02-17 14:50  雨中漫步人生  阅读(802)  评论(0编辑  收藏  举报