sklearn数据预处理
一、standardization
之所以标准化的原因是,如果数据集中的某个特征的取值不服从标准的正太分布,则性能就会变得很差
①函数scale提供了快速和简单的方法在单个数组形式的数据集上来执行标准化操作
from sklearn import preprocessing import numpy as np X=np.array([[1,-1,2], [2,0,0], [0,1,-1]]) X_scaled=preprocessing.scale(X) print(X_scaled) """ [ 1.22474487 0. -0.26726124] [-1.22474487 1.22474487 -1.06904497]] """ #尺度调整之后的数据有0均值和淡乏味方差(==1) print(X_scaled.mean(axis=0)) #[ 0. 0. 0.] print(X_scaled.std(axis=0)) #[ 1. 1. 1.]
②Preprocessing还提供了一个类StandarScaler,该类实现了变换器的API用于计算训练数据集的均值和标准差,然后将均值与标准差用到对测试数据集的变换操作中去,所以这个标准化过程应该被应用到Pipeline的早起阶段
scaler=preprocessing.StandardScaler().fit(X) print(scaler) #StandardScaler(copy=True, with_mean=True, with_std=True) print(scaler.mean_) #[ 1. 0. 0.33333333] print(scaler.scale_) #[ 0.81649658 0.81649658 1.24721913] print(scaler.transform(X)) """ [[ 0. -1.22474487 1.33630621] [ 1.22474487 0. -0.26726124] [-1.22474487 1.22474487 -1.06904497]] """
在上面的代码在,scalar实例已经训练完毕,就可以用来对新的数据执行在训练集上同样的变换操作
print(scaler.transform([[-1,1,0]])) #[[-2.44948974 1.22474487 -0.26726124]]
③将特征变换到指定范围内,
可以把特征的取值设置到最小值和最大值之间,通常是【0,1】区间或每个特征分量的最大绝对值被缩放为单位值,这样的特征变换可以使用MinMaxScaler 或 MaxAbsScaler
这些变换的作用主要是为那些变动范围特别小的 特征分量添加一定的鲁棒性,并且可以防止zero entries in sparse data
min_max_scaler=preprocessing.MinMaxScaler() X_train_minmax=min_max_scaler.fit_transform(X) print(X_train_minmax) """ [[ 0.5 0. 1. ] [ 1. 0.5 0.33333333] [ 0. 1. 0. ]] """
上面的X上训练好的MinMaxScaler就可以通过transform函数被用到新的数据上:同样的缩放和评议操作被用到测试数据集
X_test=np.array([[-3,-1,4]]) X_test_minmax=min_max_scaler.transform(X_test) print(X_test_minmax) #[[-1.5 0. 1.66666667]]
print(min_max_scaler.scale_)
#[ 0.5 0.5 0.33333333]
print(min_max_scaler.min_)
#[ 0. 0.5 0.33333333]
④Scaling features to a range
max_abs_scaler=preprocessing.MaxAbsScaler() X_train_maxabs=max_abs_scaler.fit_transform(X) print(X_train_maxabs) """ [[ 0.5 -1. 1. ] [ 1. 0. 0. ] [ 0. 1. -0.5]] """ X_test=np.array([[-3,-1,4]]) X_test_maxabs=max_abs_scaler.transform(X_test) print(X_test_maxabs) #[[-1.5 -1. 2. ]] print(max_abs_scaler.scale_) #[ 2. 1. 2.]
⑤缩放稀疏矩阵
⑥Scaling data with outliers
二、normalization
函数normalize提供了快速简单的方法,使用L1或L2范数执行规范化操作是:
from sklearn import preprocessing x=[[1,-1,2], [2,0,0], [0,1,-1]] x_normalized=preprocessing.normalize(x,norm="l2") print(x_normalized) """ 按行操作,把每一行变成单位长度!! [[ 0.40824829 -0.40824829 0.81649658] [ 1. 0. 0. ] [ 0. 0.70710678 -0.70710678]] """
规范化操作类Normalizer作为数据预处理步骤,应该用在sklearn.pipeline.Pipeline
normalizer=preprocessing.Normalizer().fit(x) print(normalizer) #Normalizer(copy=True, norm='l2') print(normalizer.transform(x)) """ [[ 0.40824829 -0.40824829 0.81649658] [ 1. 0. 0. ] [ 0. 0.70710678 -0.70710678]] """ print(normalizer.transform([[1,1,0]])) #[[ 0.70710678 0.70710678 0. ]]
三、二值化
Feat binarization:将数值型特征取值阈值化转变为布尔形特征取值,这一过程主要是概率型的学习器提供数据预处理机制
binarizer=preprocessing.Binarizer().fit(x) print(binarizer) #Binarizer(copy=True, threshold=0.0) print(binarizer.transform(x)) """ [[1 0 1] [1 0 0] [0 1 0]] """
还可以通过参数指定binarizer对象实例的阈值
四、离散化
有些情况下,某些特征的取值不是连续的数值,而是离散的标称变量
比如一个人的特征描述取值有以下几种:
"male","female" "Europe","US","Asia" "Firefox","chrome","Safari","IE"
这样的特征可以被有效的编码为整型特征值。样本实例:["Europe","US","Asia"]对于为[0,1,3],["chrome","Safari","IE"]对应于[1,2,1]
但是上面的这些整数型的特征向量是无法直接被sklearn的学习器使用的,因为学习器希望输入的是连续变化的量或者可以比较大小的量,但是上述特征向量里边的数字大小的比较是没有任何意义的
一种变换标称型特征的方法是使用one-of-K或者叫one-hot encoding,在类OneHotEncoder里面就已实现,这个编码器将每个标称型特征编码成一个m维二值特征,其中每一个样本特征向量就只有一个位置是1,其余位置全是0.
from sklearn import preprocessing enc=preprocessing.OneHotEncoder() enc.fit([[0,0,3],[1,1,0],[0,2,1],[1,0,2]]) print(enc) """ OneHotEncoder(categorical_features='all', dtype=<class 'numpy.float64'>, handle_unknown='error', n_values='auto', sparse=True) """ print(enc.transform([[0,1,3]]).toarray()) #[[ 1. 0. 0. 1. 0. 0. 0. 0. 1.]]
默认情况下,每个特征分量需要多少个值是从数据集自动推断出来的,我们还可以通过参数n_values进行显式的指定,上面的数据集中,有两种性别,三个可能的地方以及四个浏览器,然后we fit the estimator,再对每一个样本进行变换,结果里面,前两个值编码了性别,接下来的三个值编码了地方,最后的四个编码了浏览器。
注意:如果训练数据集中某个标称型分量的取值没有完全覆盖其所有可能的情况,则必须给OneHotEncoder指定每个标称型特征分量的取值个数,设置参数:n_values
enc=preprocessing.OneHotEncoder(n_values=[2,3,4]) enc.fit([[1,2,3],[0,2,0]]) print(enc) """ OneHotEncoder(categorical_features='all', dtype=<class 'numpy.float64'>, handle_unknown='error', n_values=[2, 3, 4], sparse=True) """ print(enc.transform([[1,0,0]]).toarray()) #[[ 0. 1. 1. 0. 0. 1. 0. 0. 0.]]
五、缺失值补充
一种方法是直接丢掉包含缺失值的整行或整列,然而这样可能丢失很多有价值的数据
另一种方法是从已知的部分数据中推断出未知的数据
Imputer Class提供了补全缺失值的基本策略:使用一行或一列的均值,中值,出现次数最多的值,该类也允许不同缺失值的编码。
下面的例子展示了如何替代缺失值,缺失值编码为np.nan:策略是使用包含缺失值的列均值来替代
#用中值来补充缺失值 import numpy as np from sklearn.preprocessing import Imputer imp=Imputer(missing_values="NaN",strategy="mean",axis=0) print(imp.fit([[1,2],[np.nan,3],[7,6]])) """ Imputer(axis=0, copy=True, missing_values='NaN', strategy='mean', verbose=0) """ x=[[np.nan,2],[6,np.nan],[7,6]] print(imp.transform(x)) """ [[ 4. 2. ] [ 6. 3.66666667] [ 7. 6. ]] """
Inputer 类支持稀疏矩阵
import scipy.sparse as sp X=sp.csc_matrix([[1,2],[0,3],[7,6]]) imp=Imputer(missing_values=0,strategy='mean',axis=0) print(imp.fit(X)) """ Imputer(axis=0, copy=True, missing_values=0, strategy='mean', verbose=0) """ X_test=sp.csc_matrix([[0,2],[6,0],[7,6]]) print(imp.transform(X_test)) """ [[ 4. 2. ] [ 6. 3.66666667] [ 7. 6. ]] """
六、产生多项式特征
为输入数据添加非线性特征可以增加模型的复杂度,实现这一点的常用的简单方法是使用多项式特征,他可以引入特征的高阶项和互乘积项。
Sklearn的类PolynomialFeatures可以用来在输入数据的基础上构造多项式特征
转化前的特征为(X1,X2),转化后的特征为(1,X1,X2,X1X1,X1X2,X2X2)
#引入特征的高阶项和互乘积项 import numpy as np from sklearn.preprocessing import PolynomialFeatures X=np.arange(6).reshape(3,2) print(X) """ [[0 1] [2 3] [4 5]] """ poly=PolynomialFeatures(2) print(poly.fit_transform(X)) """ [[ 1. 0. 1. 0. 0. 1.] [ 1. 2. 3. 4. 6. 9.] [ 1. 4. 5. 16. 20. 25.]] """
有些情况下,我们只想要原始特征分量之间的互乘积项,这时可以设置参数做到:interaction_only=True
#只想要原始特征分量之间的互乘积项 X=np.arange(9).reshape(3,3) print(X) """ [[0 1 2] [3 4 5] [6 7 8]] """ poly=PolynomialFeatures(degree=3,interaction_only=True) print(poly.fit_transform(X)) """ [[ 1. 0. 1. 2. 0. 0. 2. 0.] [ 1. 3. 4. 5. 12. 15. 20. 60.] [ 1. 6. 7. 8. 42. 48. 56. 336.]] """
转化前的特征为(X1,X2,X3),转化后的特征为(1,X1,X2,X3,X1X2,X1X3,X2X3,X1X2X3)
七、利用已有的函数自定义transformer
借助于FunctionTransformer类,可以从任意的Python函数实现一个transformer,比如,构造一个transformer实现对数变换
#构造一个transformer实现对数变换 import numpy as np from sklearn.preprocessing import FunctionTransformer transformer=FunctionTransformer(np.log1p) X=np.array([[0,1],[2,3]]) print(transformer.transform(X)) """ [[ 0. 0.69314718] [ 1.09861229 1.38629436]] """