机器学习之理解数据预处理

一、数据预处理简介

在机器学习中,无论什么模型,在建模训练之前都需要对训练数据进行预处理。在现实工作中,我们获取到的数据,总是会出现各种问题,比如数据缺失、数据异常、数据分布不均等等。所以,若不进行数据预处理,模型训练将得不到我们想要的结果。

数据挖掘的五大流程:

  1. 获取数据
  2. 数据预处理:从数据中检测、纠正或删除损坏、不准确或者不适用于模型的数据的过程。可能面对的问题有 a)数据类型不同,比如有的是文字、有的是数字、有的含时间序列、有的连续、有的间断等;b)数据质量不行,比如有噪声、有异常、有缺失、数据出错、量纲不一、有重复、数据是偏态、数据量太大或太小等。数据预处理的目的就是让数据适应模型、匹配模型的需求。
  3. 特征工程:将原始数据转换为更能代表预测模型的潜在问题的特征的过程。可以通过挑选最相关的特征,提取特征以及创造特征来实现,其中创造特征又经常以降维算法的方式实现。可能面对的问题有 a)特征之间有相关性、特征和标签无关、特征太多和太少、或者干脆就无法表现出应有的数据现象或无法展示数据的真实面貌。特征工程的目的就是降低计算成本、提升模型上限。
  4. 建模,测试模型并预测结果
  5. 上线,验证模型效果

在sklearn中有两个板块是关于数据预处理和特征工程的。分别是Dimensionality reduction和Preprocessing,这两个板块中包含几个模块数据预处理和特征工程的。模块preprocessing基本上包含了数据预处理的所有内容,模块Impute是专门用来填充缺失值的,模块feature_selection包含特征选择的各种方法,模块decomposition包含降维算法。
在这里插入图片描述

二、数据预处理方法

1、数据无量纲化
现实工作中,数据的规格或分布往往不尽相同,而在模型训练之前通常有转换到同一规格,或转换为某个特定分布的需求。这种需求被称为“无量纲化”。比如梯度和矩阵为核心的逻辑回归、支持向量机、神经网络等模型,无量纲化可以加速求解速度。比如距离类K近邻、KMeans聚类等模型,无量纲化可以提高模型的精度,避免某一个特征的取值范围特别大影响距离的计算。然而,决策树和树的集成算法对数据的无量纲化不作要求,树模型可以把任何模型都处理的很好

数据的无量纲化既可以是线性的,也可以是非线性的。线性的无量纲化有:中心化处理(Zero-centered或者Mean-substraction)和缩放处理(Scale)。中心化的本质是让所有记录减去一个固定值,缩放的本质是通过除以一个固定值。sklearn中的无量纲化处理包含数据归一化和数据标准化。

  • 数据归一化(preprocessing.MinMaxScaler)
    数据归一化主要是将数据(x)按照最小值中心化后,再按极差(最大值减去最小值)缩放,数据移动了最小值个单位,并且会被收敛到[0,1]之间。归一化之后的数据服从正态分布,公式如下:
    在这里插入图片描述
  • 数据标准化(preprocessing.StandardScaler)
    数据标准化主要是将数据(x)按照均值(u)中心化后,再按标准差(σ)缩放,标准化之后数据会服从标准正态分布N~(0,1),公式如下:
    在这里插入图片描述

MinMaxScaler和StandardScaler比较
在大多数机器学习模型中,一般情况都是用StandardScaler,因为MinMaxScaler对异常值非常敏感。PCA、聚类、逻辑回归、支持向量机、神经网络等算法,StandardScaler往往是比较好的选择。
但是在不涉及距离度量、梯度、协方差计算以及数据需要被压缩到特定区间时常常使用MinMaxScaler。比如数字图像处理中量化像素强度。
在实际工作中,可以先使用StandardScaler,当效果不好时换成MinMaxScaler。

除了MinMaxScaler和StandardScaler之外,sklearn中还提供了很多其他的缩放处理。比如,在希望压缩数据,却不影响数据的稀疏性时(不影响举证中取值为0的个数时),我们会使用MaxAbsScaler,在异常值多,噪声非常大时,我们可能会选用分位数来无量纲化,此时使用RobustScaler。

无量纲化功能中心化缩放描述
StandardScaler 标准化均值方差数据(x)按照均值(u)中心化后,再按标准差(σ)缩放,标准化之后数据会服从标准正态分布N~(0,1)
MinMaxScaler归一化最小值极差数据(x)按照最小值中心化后,再按极差(最大值减去最小值)缩放,最后取值范围在[0,1]
MaxAbsScaler缩放N/A最大值通过让每一个特征里的数据除以该特征中绝对值最大的数值的绝对值,将数据压缩到[-1,1]之间,这种做法并没有中心化数据,因此不会破坏数据的稀疏性。数据的稀疏性指数据中包含0的比例,0越多数据越稀疏
RobustScaler无量纲化中位数四分位数范围可以用来处理异常值。对异常值不敏感的统计量来缩放数据。这个缩放器删除中位数并根据百分位数范围(IQR:interquartile range)缩放数据,IQR是第一分位数(25%)和第三分位数(75%)之间的范围。数据集的标准化是将数据(x)按照均值(u)中心化后,再按标准差(σ)缩放来完成,但是异常值通常会对样本的均值和方差造成负面影响,当异常值很多噪声很大时,用中位数和四分位数范围通常会产生更好的效果
Normalizer无量纲化N/Asklearn中未明确,依范数原理应当是:L1:样本向量的长度/样本中每个元素绝对值的和L2:样本向量的长度/样本中每个元素的欧式距离将样本独立缩放到单位范数,每个至少带一个非0值的样本都会被独立放缩,使得整个样本(整个向量)的长度都为L1范数或L2范数。这个类可以处理密集数组(numpy arrays)或scipy中的稀疏矩阵(scipy.sparse),如果你希望避免复制/转换过程中的负担,请使用CSR格式的矩阵。将输入的数据缩放到单位范数是文本分类或聚类中常见的操作,例如两个L2正则化后的TF-IDF向量的点积是向量的余弦相似度,并且是信息检索社区常用的向量空间模型的基本相似性度量。使用参数norm来确定要正则化的范数方向,可以选择"l1","l2"以及"max"三种选项,默认l2范数。这个评估器的fit接口什么也不做,但在管道中使用依然很有用
PowerTransformer非线性无量纲化N/AN/A应用特征功率变换使数据更接近正态分布,功率变换是一系列参数单调变换,用于使数据更像高斯,这对于建模与异方差性(非常数方差)或其他需要正态性的情况相关的问题非常有用,要求输入的数据严格为正,power_transform()通过最大似然估计来稳定方差和并确定最小化偏度的最佳参数。默认情况下,标准化应用于转换后的数据
QuantileTransformer非线性无量纲化N/AN/A使用百分位数转换特征,通过缩小边缘异常值和非异常值之间的距离来提供特征的非线性变换,可以使用参数output_distribution="normal"来将数据映射到标准正态分布
KernelCenterer中心化均值N/A将核矩阵中心化。设K(x,z)是由phi(x)Tphi(z)定义的核,其中phi是将x映射到希尔伯特空间的函数。KernelCenterer在不明确计算phi(x)的情况下让数据中心化为0均值。它相当于使用sklearn.preprocessing.StandardScaler(with_std=False)来将phi(x)中心化

2、缺失值
现实工作中的数据总是会因为各种原因出现或多或少的特征值的缺失,而很多特征,对于分析和建模来说有很大的作用。因此,我们需要对这些缺失的数据进行预处理,填充或者删除缺失样本。
常见的填充缺失值的方法有:

  • Pandas库中dataframe对象的fillna()方法
# 均值填充
data.loc[:, key] = data.loc[:, key].fillna(data.loc[:, key].mean())

# 关于fillna()函数的填充,其参数可以是常数也可以如上是通过计算得到的数(均值、众数等)。
# 对于loc和iloc的区别,loc的中的参数是key值,iloc中的参数是key所对应的索引(index)。
  • impute.SimpleImputer
class sklearn.impute.SimpleImputer (missing_values=nan, 
									strategy=’mean’, 
									fill_value=None, 
									verbose=0, 
									copy=True)

这个类是专门用来填充缺失值的

参数描述
missing_values告诉SimpleImputer,数据中的缺失值长什么样,默认空值np.nan
strategy我们填充缺失值的策略,默认均值。
输入"mean"使用均值填补(仅对数值型特征可用)
输入"median"用中值填充(仅对数值型特征可用)
输入"most_frequent"用众数填充(对数值型和字符型特征都可用)
输入"constant"表示请参考参数"fill_value"中的值(对数值型和字符型特征都可用)
fill_value当参数strategy为"constant"的时候可用,可输入字符串或数字表示要填充的值,常用0
copy默认为True,将创建特征矩阵的副本,反之则会将缺失值填充到原本的特征矩阵中去

举例:

from sklearn.impute import SimpleImputer
# 需要填充的特征 假设是数值特征 data是pandas的DataFrame对象
# reshape()的原因是因为SimpleImputer对象的fit_transform()函数的入参需要是二维数据
fill_data = data.loc[:, key].values.reshape(-1,1)
fill_0 = SimpleImputer(strategy='constant', fill_value=0) # 使用常数0填充
fill_0 = fill_0.fit_transform(fill_data)

3、处理分类型特征:编码和哑变量
在机器学习中,大多数算法,都只能处理数值型的数据,如逻辑回归、SVM、K邻近算法等。有时候我们得到的数据有些特征比如性别是用字符表示的。所以我们需要把这些特征进行编码,将字符型数据转换成数值型。常用的方法:

  • preprocessing.LabelEncoder
    顾名思义,该对象是标签专用,将分类转换为分类数值
from sklearn.preprocessing import LabelEncoder
# data是pandas的DataFrame对象
y = data.loc[:, key]
le = LabelEncoder()
label = le.fit_transform(y)
  • preprocessing.OrdinalEncoder
    特征专用,将分类特征转换为分类数值
from sklearn.preprocessing import OrdinalEncoder
import pandas as pd
x = pd.DataFrame(['男','男', '女','男','女','男','女','女'])
oe = OrdinalEncoder()
label = oe.fit_transform(x)
# 输出的结果是array([[1.], [1.], [0.], [1.], [0.], [1.], [0.], [0.]]) 0表示女,1表示男
  • preprocessing.OneHotEncoder
    独热编码,创建哑变量,在OrdinalEncoder方法中我们可以将字符型数据转换成数值型数据,但是在数值上的0和1是由大小顺序之分的,而男和女是没有这个关系的,所以在某种程度上来说这种转换对模型的结果可能会产生意想不到的影响。因为1-0=1,但是男减女并不等于男。所以通过OneHotEncoder对象编码,然后通过增加特征来转换成哑变量。如
    在这里插入图片描述
    S、Q和C是一个特征的三种不同的取值,通过OneHotEncoder编码变成右边所示,然后将原来的特征转换成由S、Q、C命名的三个取值为0和1的哑变量特征。
from sklearn.preprocessing import OneHotEncoder
import pandas as pd
x = pd.DataFrame(['S','Q', 'S','Q','C','S','Q','C'],columns=['embaked'])
oe = OneHotEncoder(categories='auto')
label = oe.fit_transform(x)
# get_feature_names获取训练出来的新的特征名称
pd.DataFrame(label.toarray(),columns=oe.get_feature_names())
#输入结果:
#       x0_C x0_Q  x0_S
#  0	0.0  0.0   1.0
#  1	0.0	 1.0   0.0
#  2	0.0	 0.0   1.0
#  3	0.0	 1.0   0.0
#  4	1.0	 0.0   0.0
#  5	0.0	 0.0   1.0
#  6	0.0	 1.0   0.0
#  7	1.0	 0.0   0.0

4、处理连续型特征:二值化与分段
二值化就是根据设定的阈值将特征设置为0或1,用于处理连续型变量。大于阈值的设置为1小于或等于阈值的设置为0。二值化是对文本计数数据的常见操作,分析人员可以决定仅考虑某种现象的存在与否。它还可以用作考虑布尔随机变量的估计器的预处理步骤(例如使用贝叶斯设置中的伯努利分布建模)。常用的方法是sklearn.preprocessing.Binarizer。

from sklearn.preprocessing import Binarizer
x = data.loc[:,key].values.reshape(-1,1)
bi_x = Binarizer(threshold=20).fit_transform(x)

分段就是将连续型变量排序后按顺序分箱后编码。sklearn中的对象为preprocessing.KBinsDiscretizer。

参数描述
n_bins每个特征中分箱的个数,默认5,一次会被运用到所有导入的特征
encode编码的方式,默认"onehot"
“onehot”:做哑变量,之后返回一个稀疏矩阵,每一列是一个特征中的一个类别,含有该类别的样本表示为1,不含的表示为0
"ordinal":每个特征的每个箱都被编码为一个整数,返回每一列是一个特征,每个特征下含有不同整数编码的箱的矩阵
"onehot-dense":做哑变量,之后返回一个密集数组
strategy用来定义箱宽的方式,默认"quantile"
“uniform”:表示等宽分箱,即每个特征中的每个箱的最大值之间的差为(特征.max() - 特征.min())/n_bins
"quantile":表示等位分箱,即每个特征中的每个箱内的样本数量都相同
"kmeans":表示按聚类分箱,每个箱中的值到最近的一维k均值聚类的簇心的距离都相同
from sklearn.preprocessing import KBinsDiscretizer
x = data.loc[:, key].values.reshape(-1,1)
x_bins = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')
x_bins.fit_transform(x)
  • 1
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值