7.3.1 数据预处理preprocessing
现实世界中数据大体上都是不完整,不一致的脏数据,无法直接进行提供给机器学习模型。为了提高数据利用的质量产生了数据预处理技术。
数据预处理是指对所收集数据进行分类或分组前所做的审核排序等必要的处理。现实世界中数据大体上都是不完整,不一致的脏数据,无法直接进行数据挖掘,或挖掘结果差强人意。为了提高数据挖掘的质量产生了数据预处理技术。
数据预处理有多种方法:数据清理,数据集成,数据变换,数据归约等。这些数据处理技术在数据挖掘之前使用,大大提高了数据挖掘模式的质量,降低实际挖掘所需要的时间。
数据预处理分为无量纲化、特征二元化、特征哑编码和缺失值处理等。
7.3.2 无量纲化
无量纲化使不同规格的数据转换到同一规格。常见的无量纲化方法有标准化、区间缩放法和正则化。标准化的前提是特征值服从正态分布,标准化后,其转换成标准正态分布。区间缩放法利用了边界值信息,将特征的取值区间缩放到某个特点的范围。数据正则化针对单个样本,将样本某个范数缩放到单位1。
1. 标准化Standardization
数据标准化是将样本的属性缩放到某个指定的范围,标准化的原因在于:
- 某些算法要求数据具有零均值和单位方差;
- 样本不同特征有不同的量级和单位。所有依赖于样本距离的算法(如KNN)对于数据的数量级都非常敏感。量级大的特征属性将占主导地位,且量级的差异会导致迭代速度减慢。为了消除量级的影响,必须进行数据标准化。
标准化公式为:
标准化公式其中μ为数据x的平均值,σ为标准差。
使用sklearn.preprocessing.scale()函数,可以直接将给定数据进行标准化。示例代码:
from sklearn import preprocessing
import numpy as np
A = np.array([[ 1., -1., 2.],[ 2., 0., 0.],[ 0., 1., -1.]])
A_scaled = preprocessing.scale(A)
A_scaled
显示结果:
array([[ 0. , -1.22474487, 1.33630621],
[ 1.22474487, 0. , -0.26726124],
[-1.22474487, 1.22474487, -1.06904497]])
处理后均值,示例代码:
X_scaled.mean(axis=0)
运行结果:
array([ 0., 0., 0.])
求方差,示例代码:
X_scaled.std(axis=0)
运行结果:
array([ 1., 1., 1.])
使用StandardScaler方法,可以保存训练集中的参数(均值、方差)直接使用其对象转换测试集数据。示例代码:
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler().fit(X_train)
standardized_X=scaler.transform(X_train)
standardized_X_test=scaler.transform(X_test)
X_train数据集显示如下:
array([[ 0. , 0.7748339 , 0. , 0. , 0.80939893],
[ 0. , 0. , 0. , 0. , 0. ],
[ 0.94029749, 0. , 0. , 0. , 0. ],
[ 0. , 0.86847999, 0.84031636, 0.88293549, 0.75715913],
[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0.99279061, 0. , 0. ],
[ 0.73956947, 0. , 0.83682458, 0.82550419, 0.7967034 ]])
对X_train数据集标准化后的standardized_X显示如下:
array([[-0.62622762, 1.45169842, -0.86101085, -0.63195583, 1.20938042],
[-0.62622762, -0.63102272, -0.86101085, -0.63195583, -0.86542173],
[ 1.82746778, -0.63102272, -0.86101085, -0.63195583, -0.86542173],
[-0.62622762, 1.70341519, 1.03591063, 1.65424348, 1.07546963],
[-0.62622762, -0.63102272, -0.86101085, -0.63195583, -0.86542173],
[-0.62622762, -0.63102272, 1.38010443, -0.63195583, -0.86542173],
[ 1.30367034, -0.63102272, 1.02802833, 1.50553567, 1.17683686]])
2. 正则化Normalization
数据正则化将样本某个范数缩放到单位1,是针对单个样本的,对于每个样本将样本缩放到单位范数。其目的在于样本向量在点乘运算或其他核函数计算相似性时,拥有统一的标准。
Normalization主要思想是对每个样本计算其p-范数,然后对该样本中每个元素除以该范数,这样处理的结果是使得每个处理后样本的p-范数(L1-norm,L2-norm)等于1。p-范数的计算公式:
规则为L2的正则化公式为:
L2的正则化公式该方法主要应用于文本分类和聚类中。例如,对于两个TF-IDF向量的L2-norm进行点积,就可以得到这两个向量的余弦相似性。
使用preprocessing.normalize()函数对指定数据进行转换,示例代码:
A = [[ 1., -1., 2.],[ 2., 0., 0.],[ 0., 1., -1.]]
A_normalized = preprocessing.normalize(X, norm='l2')
A_normalized
运行结果:
array([[ 0. , 0. , 1. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 1. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 1. , 0. , 0. , 0. ],
[ 0.4619214 , 0. , 0.52266515, 0.51559464, 0.4976062 ],
[ 1. , 0. , 0. , 0. , 0. ],
[ 0. , 0.517792 , 0.50100071, 0.52641044, 0.45142196],
[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0.69151445, 0. , 0. , 0.72236263]])
使用processing.Normalizer()类实现对训练集和测试集的拟合和转换,示例代码:
from sklearn.preprocessing import Normalizer
scaler=Normalizer().fit(X_train)
normalized_X=scaler.transform(X_train)
normalized_X_test=scaler.transform(X_test)
normalized_X
正则化后,训练集normalized_X结果为:
array([[ 0. , 0.69151445, 0. , 0. , 0.72236263],
[ 0. , 0. , 0. , 0. , 0. ],
[ 1. , 0. , 0. , 0. , 0. ],
[ 0. , 0.517792 , 0.50100071, 0.52641044, 0.45142196],
[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 1. , 0. , 0. ],
[ 0.4619214 , 0. , 0.52266515, 0.51559464, 0.4976062 ]])
3. 区间缩放法MinMaxScaler
区间缩放法的思路有多种,常见的一种为利用两个最值min、max进行缩放,公式为:
区间缩放法区间缩放的目的包括:
- 对于方差非常小的属性可以增强其稳定性;
- 维持稀疏矩阵中为0的条目。
使用preprocessing库的MinMaxScaler类对数据进行区间缩放。示例代码:
A_train = np.array([[ 1., -1., 2.],
[ 2., 0., 0.],
[ 0., 1., -1.]])
min_max_scaler = preprocessing.MinMaxScaler()
A_train_minmax = min_max_scaler.fit_transform(A_train)
A_train_minmax
显示结果:
array([[ 0.5 , 0. , 1. ],
[ 1. , 0.5 , 0.33333333],
[ 0. , 1. , 0. ]])
7.3.3 特征二元化Binarization
特征二元化的过程是将数值型数据转换为布尔型属性,一般用于图像处理领域。设定一个阈值,大于阈值的赋值为1,小于等于阈值的赋值为0,公式表达如下:
特征二元化使用preprocessing库的Binarizer类对数据集进行二值化,示例代码:
from sklearn.preprocessing import Binarizer
binarizer = Binarizer(threshold=0.0).fit(X)
binary_X=binarizer.transform(X)
binary_X
显示结果:
array([[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 1., 0., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 1., 0., 0., 0.],
[ 1., 0., 1., 1., 1.],
[ 1., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 0., 1., 0., 0., 1.]])
源数据集X显示结果:
array([[ 0. , 0. , 0.99279061, 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0.75228332, 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0.96809177, 0. , 0. , 0. ],
[ 0.73956947, 0. , 0.83682458, 0.82550419, 0.7967034 ],
[ 0.94029749, 0. , 0. , 0. , 0. ],
[ 0. , 0.86847999, 0.84031636, 0.88293549, 0.75715913],
[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0.7748339 , 0. , 0. , 0.80939893]])
与源数据进行比对,可以发现,二进制化的作用是将所有非零值转换为1,零值依然为0。
7.3.4 类条件编码
利用preprocessing模块的LabelEncoder类,可以对枚举型特征值进行数值编码,本例中特征结果集y的值为枚举型'M'和'F',可以利用特征编码转换成数值型,示例代码:
from sklearn.preprocessing import LabelEncoder
enc = LabelEncoder()
y=enc.fit_transform(y)
y
运行结果
array([1, 1, 0, 0, 1, 0, 1, 1, 0, 0], dtype=int64)
源特征数据集y为
array(['M', 'M', 'F', 'F', 'M', 'F', 'M', 'M', 'F', 'F'], dtype='<U1')
由运行结果可知,将枚举型字符'M'和'F'分别对应转换为整型的数值1和0。
7.3.5 特征哑编码
哑编码(One Hot Encoding)采用N位状态寄存器对N个可能的取值进行编码,每个状态都由独立的寄存器位来表示,并且在任意时刻只有其中一位有效。假设某个属性的取值为非数值的离散集合[离散值1,离散值2,…,离散值m],则针对该属性的编码为一个m元的元组,且该元组的分量有且只有一个为1,其余都为0。
One Hot Encoding能够处理非数值属性;在一定程度上也扩充了特征,如性别本身是一个属性,经过One Hot Encoding后变成了男或女两个属性;编码后的属性是稀疏的,存在大量的零元分量。
使用preproccessing库的OneHotEncoder类对数据进行哑编码的代码如下:
from sklearn.preprocessing import OneHotEncoder
#哑编码,对IRIS数据集的目标值,返回值为哑编码后的数据
OneHotEncoder().fit_transform(iris.target.reshape((-1,1)))
7.3.6 缺失值处理
1. 删除缺失值
直接删除确实值,这是最简单最直接的方法,有的时候也是最有效的方法,但这种方法可能会导致信息丢失。
当某列特征的缺失值较多时,一般选择舍弃该特征,否则较多的缺失值反而会引入过多的噪声,对预测结果造成不利影响。
2. 数据补全
用规则或模型将缺失数据补全,这种做法的缺点是可能会引入噪声。
preprocessing的Imputer类提供了缺失值处理的方法,以下示例中,对训练集X_train中将0值设置为缺失值,并且以均值插补的方法进行替换处理,示例代码:
from sklearn.preprocessing import Imputer
imp=Imputer(missing_values=0, strategy='mean', axis=0)
imp.fit_transform(X_train)
运行结果:
array([[ 0.83993348, 0.7748339 , 0.88997719, 0.85421984, 0.80939893],
[ 0.83993348, 0.82165694, 0.88997719, 0.85421984, 0.78775382],
[ 0.94029749, 0.82165694, 0.88997719, 0.85421984, 0.78775382],
[ 0.83993348, 0.86847999, 0.84031636, 0.88293549, 0.75715913],
[ 0.83993348, 0.82165694, 0.88997719, 0.85421984, 0.78775382],
[ 0.83993348, 0.82165694, 0.99279061, 0.85421984, 0.78775382],
[ 0.73956947, 0.82165694, 0.83682458, 0.82550419, 0.7967034 ]])
除了均值插补,数据补全的方法还有同类值插补、建模预测、高维映射、多重插补、极大似然估计和压缩感知及矩阵补全等。
3. 忽略缺失值
一些机器学习模型(如决策树算法)能够直接处理数据缺失的情况,在这种情况下不需要对缺失数据做任何的处理,这种做法的缺点是在模型的选择上有局限。
7.3.7 数据变换
常见的数据变换有基于多项式的、基于指数函数的、基于对数函数的。4个特征,度为2的多项式转换公式如下:
多项式转换使用preproccessing库的PolynomialFeatures类对数据进行多项式转换的代码如下:
示例代码:
from sklearn.preprocessing import PolynomialFeatures
#多项式转换
#参数degree为度,默认值为2
PolynomialFeatures().fit_transform(iris.data)
基于单变元函数的数据变换可以使用一个统一的方式完成,使用preproccessing库的FunctionTransformer对数据进行对数函数转换的代码如下:
from numpy import log1p
from sklearn.preprocessing import FunctionTransformer
#自定义转换函数为对数函数的数据变换
#第一个参数是单变元函数
FunctionTransformer(log1p).fit_transform(iris.data)
回顾
类 | 功能 | 说明 |
---|---|---|
StandardScaler | 无量纲化 | 标准化,基于特征矩阵的列,将特征值转换至服从标准正态分布 |
MinMaxScaler | 无量纲化 | 区间缩放,基于最大最小值,将特征值转换到[0, 1]区间上 |
Normalizer | 归一化 | 基于特征矩阵的行,将样本向量转换为“单位向量” |
Binarizer | 二值化 | 基于给定阈值,将定量特征按阈值划分 |
OneHotEncoder | 哑编码 | 将定性数据编码为定量数据 |
Imputer | 缺失值计算 | 计算缺失值,缺失值可填充为均值等 |
PolynomialFeatures | 多项式数据转换 | 多项式数据转换 |
FunctionTransformer | 自定义单元数据转换 | 使用单变元的函数来转换数据 |
网友评论