特征预处理 --1

    技术2022-07-11  71

    特征预处理

    阅读机器学习书籍中,经常看到一句话:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限,本文总结常见的数据预处理方法.文章的内容会逐步添加新学习到的预处理方法.

    数据无量纲化

    在机器学习实践中,我们经常会遇到将不同量纲的数据放到同一个训练集中,这样的坏处是: 量纲大的特征对模型的影响效果会增大,影响模型计算的精度.所以,不同规格的数据会转换到同一规格下,后进行训练.同时,对于以梯度和矩阵为核心的算法中,无量纲化会增加模型求解的速度. 常见的无量纲化方法为:

    1. 数据归一化(Normalization)

    数据会被缩放到[0,1]之间,不会影响数据的分布 x ∗ = x − m i n ( x ) m a x ( x ) − m i n ( x ) x^{*} = \frac{x- min(x)}{max(x)-min(x)} x=max(x)min(x)xmin(x)sklearn 中实现 data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]] import numpy as np X = np.array(data) from sklearn.preprocessing import MinMaxScaler mms = MinMaxScaler().fit(X) mms.transform(X) X:array([[-1. , 2. ], [-0.5, 6. ], [ 0. , 10. ], [ 1. , 18. ]]) # 归一化的结果 array([[0. , 0. ], [0.25, 0.25], [0.5 , 0.5 ], [1. , 1. ]])

    2.数据标准化(Standardization)

    -将数据进行缩放,使数据满足标准差为1, 均值为0 ; x ∗ = x − μ σ x^* = \frac{x-\mu}{\sigma} x=σxμ

    sklearn 中实现 from sklearn.preprocessing import StandardScaler atd = StandardScaler().fit(data) std.transform(data) #归一化结果 array([[-4.77235833, 4.69592834], [-3.19431055, 17.32031057], [-1.61626277, 29.94469281], [ 1.53983278, 55.19345727]])

    缺失值填补

    以下主要介绍在sklearn中的缺失值填补

    class sklearn.impute.SimpleImputer(*, missing_values=nan, strategy='mean', fill_value=None, verbose=0, copy=True, add_indicator=False)

    重要参数

    Parameters含义defaultmissing_values缺失值的样式np.nanstrategy使用什么策略填补缺失值‘mean’fill_value当strategy设置为’constant’时,填补的值Nonecopy创建副本True

    详情见sklearn官方文档 实例: 以泰坦尼克号为例:

    查看缺失值: data.isnull().mean() Age 0.198653 Sex 0.000000 Embarked 0.002245 Survived 0.000000 dtype: float64

    可知,特征Age和Embarked含有缺失值,比例分别为0.19和0.002; 但,对于分类型变量,要小心!

    data['Survived'].value_counts() No 486 Yes 310 Unknown 95 Name: Survived, dtype: int64

    虽然survived显示没有缺失值,但unknown也相当于缺失值 分析后,决定使用中位数来填补Age, 众数来填补Survived和embarked

    from sklearn.impute import SimpleImputer Age = data[['Age']] imp_median = SimpleImputer(strategy='median').fit(Age) data['Age'] = imp_median.transform(Age) Emb = data[['Embarked']] imp_mode = SimpleImputer(strategy= 'most_frequent').fit(Emb) data['Embarked'] = imp_mode.transform(Emb) Sur = data[['Survived']] imp_s = SimpleImputer(missing_values='Unknown',strategy='most_frequent').fit(Sur) data['Survived'] = imp_s.transform(Sur)

    分类型变量编码

    机器学习中,大部分喂进去的数据需要是数组,然而, 我们收集到的数据往往不是连续性的,而是分类型的,比如形容人的特征: [“male”, “female”], [“from Europe”, “from US”, “from Asia”], [“uses Firefox”, “uses Chrome”, “uses Safari”, “uses Internet Explorer”],所以要对文字型数据编码成数值型.

    OrdinalEncoder 将 [“male”, “female”] 转换为[0,1] [“uses Firefox”, “uses Chrome”, “uses Safari”, “uses Internet Explorer”] 转化为[0,1,2]的形式 class sklearn.preprocessing.OrdinalEncoder(*, categories='auto', dtype=<class 'numpy.float64'>) >>> enc = preprocessing.OrdinalEncoder() >>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']] >>> enc.fit(X) OrdinalEncoder() >>> enc.transform([['female', 'from US', 'uses Safari']]) array([[0., 1., 1.]])

    注意:OrdinalEncoder在有两种以上的种类(名义变量)是不常用,因为0,1,2默认了自带数学特征,可计算,可排序,但这不符合现实情况,所以这种情况下,我们引入哑变量

    OneHot Encoder 哑变量是将每个具有n个种类的特征转换为n个二进制的特征,在每个特征中,其中一个数是1, 其他的都是0 >>> enc = preprocessing.OneHotEncoder() >>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']] >>> enc.fit(X) OneHotEncoder() >>> enc.transform([['female', 'from US', 'uses Safari'], ... ['male', 'from Europe', 'uses Safari']]).toarray() array([[1., 0., 0., 1., 0., 1.], [0., 1., 1., 0., 0., 1.]])

    重要参数

    Parameters含义defaultcategories决定样本种类autodrop编码为哑变量后,是否删除一列Nonehandle_unknown当出现未知的种类时,是否报错‘error’

    详情见sklearn官方文档 可使用 .categories_ 查看种类

    >>> enc.categories_ [array(['female', 'male'], dtype=object), array(['from Europe', 'from US'], dtype=object), array(['uses Firefox', 'uses Safari'], dtype=object)]

    连续变量离散化(Discrerization)

    通过对连续型变量切分,可以将连续性变量转换成离散型变量,用于分裂问题.

    Binarizer 通过设置阈值,将大于阈值的数离散化为1,小于阈值的数,转换为1 X = np.array([[ -3., 5., 15 ], [ 0., 6., 14 ], [ 6., 3., 11 ]]) from sklearn.preprocessing import Binarizer X_bin = Binarizer(threshold= 10).fit(X) X_bin.transform(X) array([[0., 0., 1.], [0., 0., 1.], [0., 0., 1.]])

    Binarizer 只能将变量离散化为0,1,会使得结果丢失了很多信息,于是引入了 K-bins discretization

    K-bins discretization 在默认情况下, 按照一定规则将连续性变量分箱,后Onehot编码. class sklearn.preprocessing.KBinsDiscretizer(n_bins=5, *, encode='onehot', strategy='quantile')

    规则主要有三种:

    等宽分箱(uniform) 比如,一组数组为[1,3,3,3,4,4,5,9,10],分为3个箱,则: l = 10 − 1 3 = 3 l =\frac{10-1}{3} = 3 l=3101=3,分箱后结果为[A,A,A,A,B,B,C,C,C];等位分箱(quantile) 比如,一组数组为[1,3,3,3,4,4,5,9,10],分为3个箱, 分箱后结果为[A,A,A,B,B,B,C,C,C]聚类分箱(kmeans) 同K-means, 每个箱中的值到最近的一维k均值聚类的簇心距离相等

    重要参数

    Parameters含义defaultn_bins分的箱的数量5encode分箱后编码‘onehot’strategy分箱策略(如上文介绍)‘quantile’

    详情见sklearn官方文档

    代码示例

    X = np.array([[ -3., 5., 15 ], [ 0., 6., 14 ], [ 6., 3., 11 ]]) est = preprocessing.KBinsDiscretizer(n_bins=[3, 2, 2], encode='ordinal').fit(X) >>> est.transform(X) array([[ 0., 1., 1.], [ 1., 1., 1.], [ 2., 0., 0.]])

    注: 在示例中,encode选用的’ordinal’, 所以连续型被离散成[0,1,2]

    计划在下一篇文章中,介绍,特征选择相关知识.

    Processed: 0.010, SQL: 9