机器学习之特征工程


一、特征工程——概述

特征工程是数据分析中最耗时间和精力的一部分工作。数据和特征决定了机器学习的上限,而模型和算法则是逼近这个上限。因此,特征工程就变得尤为重要了。特征工程的主要工作就是对特征的处理,包括数据的采集,数据预处理,特征选择,甚至降维技术等跟特征有关的工作。

1、特征(Feature)

特征是数据中抽取出来的对结果预测有用的信息。

2、特征工程(Feature Engineering)

特征工程是使用专业背景知识和技巧处理数据,使得特征能在机器学习算法上发挥更好的作用的过程。

3、特征工程的意义

  1. 特征工程是将原始数据转化为特征,能更好表示预测模型处理的实际问题,提升对于未知数据预测的准确性。
  2. 更好的特征意味着更强的灵活度、更好的特征意味着只需要用简单模型、更好的特征意味着更好的结果。

二、特征工程——数据预处理

1、缺失值处理

  1. 连续值:可以选择该特征值的所有样本的均值或中位数来填充缺失值。
  2. 离散值:选择该特征值的所有样本中最频繁出现的类别值来填充缺失值。
    注:不可信的样本丢掉,缺省值极多的字段考虑不用(即删掉)
from sklearn.preprocessing import Imputer

2、离散特征的连续化处理

(1)独热编码(one-hot encoding)(哑变量)

处理方法比较简单,比如某特征的取值是高,中和低,那么我们就可以创建三个取值为0或者1的特征,将高编码为1,0,0,中编码为0,1,0,低编码为0,0,1。也就是说,之前的一个特征被我们转化为了三个特征。

from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder

(2)特征嵌入(embedding)

这个一般用于深度学习中。比如对于用户的ID这个特征,如果要使用独热编码,则维度会爆炸,如果使用特征嵌入维度就低很多了。对于每个要嵌入的特征,我们会有一个特征嵌入矩阵,这个矩阵的行很大,对应我们该特征的数目。比如用户ID,如果有100万个,那么嵌入的特征矩阵的行就是100万。但是列一般比较小,比如可以取20。这样每个用户ID就转化为了一个20维的特征向量,进而参与深度学习模型。

3、连续特征的离散化处理

连续特征的离散化就是在数据的取值范围内设定若干个离散的划分点,将取值范围划分为一些离散化的区间,最后用不同的符号或整数值代表落在每个子区间中的数据值。
首先要确定分类数,然后将连续特征值映射到这些分类值(等宽法、等频法、一维聚类)。

(1)根据阈值进行分组

比如我们根据连续值特征的分位数,将该特征分为高,中和低三个特征。将分位数从0~0.3的设置为低,0.3~0.7的设置为中,0.7~1的设置为高。

(2)基于聚类分析的方法

一维聚类的方法包括两个步骤,首先将连续特征的值用聚类算法(如K-Means算法)进行聚类,然后再将聚类得到的簇进行处理,合并到一个簇的连续特征值并做同一标记。聚类分析的离散化方法也需要用户指定簇的个数,从而决定产生的区间数。

(3)使用梯度提升树(GDBT)将连续值转化为离散值

sklearn中,我们可以用GradientBoostingClassifier的 apply方法很方便的得到样本离散化后的特征,然后使用独热编码即可。

4、特征的标准化和归一化(数值型数据)

数据规范化处理是数据挖掘的一项基础工作。不同的评价指标往往具有不同的量纲,数值间的差别可能很大,不进行处理可能会影响到数据分析的结果。为了消除指标之间的量纲和取值范围差异的影响,需要进行标准化处理,将数据按照比例进行缩放,使之落入一个特定的区域,便于进行综合分析。

(1)零-均值标准化(Z-score)

具体的方法是求出样本特征x的均值mean和标准差std,然后用(x-mean)/std来代替原特征。这样特征就变成了均值为0,方差为1。该方法是当前用的最多的数据标准化方法。

from sklearn.preprocessing import StandardScaler

(2)最小-最大标准化(min-max)

最小 - 最大标准化也成为离差标准化,是对原始数据的线性变换,将数值映射到[0,1]之间。

具体的方法是求出样本特征x的最大值max和最小值min,然后用(x-min)/(max-min)来代替原特征。如果我们希望将数据映射到任意一个区间[a,b],而不是[0,1],那么也很简单。用(x-min)(b-a)/(max-min)+a来代替原特征即可。

from sklearn.preprocessing import MinMaxScaler

(3)L1/L2范数标准化

from sklearn.preprocessing import Normalizer

通常情况下,范数标准化首选L2范数标准化。

5、时间类型的数据处理

(1)连续的时间差值法

即计算出所有样本的时间到某一个未来时间之间的数值差距,这样这个差距是UTC的时间差,从而将时间特征转化为连续值。

(2)将一个时间转化为离散特征

根据时间所在的年,月,日,星期几,小时数,将一个时间特征转化为若干个离散特征,这种方法在分析具有明显时间趋势的问题比较好用。

6、文本类型的数据预处理

(1)词袋

直接把文本数据丢给模型,模型是无法解释的,因此需要把文本型的数据用数值表示。去掉停用词,标点符号,留下表达实际含义的词组成列表,在词库中映射稀疏向量。

(2)把词袋中的词扩充到n-gram

它的思想是:在整个语言环境中,句子T的出现概率是由组成T的N个词组成的。

(3)使用TF-IDF方法

(4)word2vec将词转化为词向量

7、异常特征样本清洗

异常数据的清洗,目标是将原始数据中异常的数据清除。

(1)偏差检测( 聚类(KMeans)和最近邻(KNN))

比如我们可以用KMeans聚类将训练样本分成若干个簇,如果某一个簇里的样本数很少,而且簇质心和其他所有的簇都很远,那么这个簇里面的样本极有可能是异常特征样本了。我们可以将其从训练集过滤掉。

(2)异常点检测(iForest,one class SVM)

主要是使用iForest或者one class SVM,使用异常点检测的机器学习算法来过滤所有的异常点。

(3)基于统计的异常点检测

例如极差,四分位数间距,均差,标准差等,这种方法适合于挖掘单变量的数值型数据。全距(Range),又称极差,是用来表示统计资料中的变异量数(measures of variation) ,其最大值与最小值之间的差距;四分位距通常是用来构建箱形图,以及对概率分布的简要图表概述。

(4)基于距离的异常点检测

主要通过距离方法来检测异常点,将数据集中与大多数点之间距离大于某个阈值的点视为异常点,主要使用的距离度量方法有绝对距离 ( 曼哈顿距离 ) 、欧氏距离和马氏距离等方法。

(5)基于密度的异常点检测

考察当前点的周围密度,可以发现局部异常点,例如LOF算法。

8、处理不平衡数据

另外一篇(参考如下)
不平衡数据集介绍和处理方法

三、特征工程——特征选择

1、过滤法选择特征(Filter)

它按照特征的发散性或者相关性指标对各个特征进行评分,设定评分阈值或者待选择阈值的个数,选择合适的特征。

(1)方差筛选法

使用方差选择法,先要计算各个特征的方差,然后根据阈值,选择方差大于阈值的特征。(方差越大的特征,那么我们可以认为它是比较有用的。如果方差较小,比如小于1,那么这个特征可能对我们的算法作用没有那么大。最极端的,如果某个特征方差为0,即所有的样本该特征的取值都是一样的,那么它对我们的模型训练没有任何作用,可以直接舍弃。在实际应用中,我们会指定一个方差的阈值,当方差小于这个阈值的特征会被我们筛掉。)

from skearn.feature_selection import VarianceThreshold

(2)相关系数

这个主要用于输出连续值的监督学习算法中。我们分别计算所有训练集中各个特征与输出值之间的相关系数,设定一个阈值,选择相关系数较大的部分特征。即使用相关系数法,先要计算各个特征对目标值的相关系数以及相关系数的P值。

from sklearn.feature_selection import SelectKBest
from scipy.stats import pearsonr

(3)假设检验法(卡方检验、F检验、t检验)

卡方检验可以检验某个特征分布和输出值分布之间的相关性。

经典的卡方检验是检验定性自变量对定性因变量的相关性。假设自变量有N种取值,因变量有M种取值,考虑自变量等于i且因变量等于j的样本频数的观察值与期望的差距。

我们还可以使用F检验和t检验,它们都是使用假设检验的方法,只是使用的统计分布不是卡方分布,而是F分布和t分布而已。

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

(4)互信息

即从信息熵的角度分析各个特征和输出值之间的关系评分。在决策树算法中我们讲到过互信息(信息增益)。互信息值越大,说明该特征和输出值之间的相关性越大。

经典的互信息也是评价定性自变量对定性因变量的相关性。

[熵与信息增益算法详解](决策树算法熵与信息增益(Python3实现)_信息增益比最大的特征 python实现-CSDN博客)

2、包装法选择特征(Wrapper)

根据目标函数,通常是预测效果评分,每次选择部分特征,或者排除部分特征。

(1)递归消除特征算法(Recursive feature elimination algorithm)

递归消除特征法使用一个机器学习模型来进行多轮训练,每轮训练后,消除若干权值系数的对应的特征,再基于新的特征集进行下一轮训练。

from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression

3、嵌入法选择特征(Embedded)

先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据权值系数从大到小来选择特征。(类似于Filter方法,但是是通过训练来确定特征的优劣。)

(1)基于惩罚项的特征选择法

使用带惩罚项的基模型,除了筛选出特征外,同时也进行了降维。
最常用的是使用L1正则化和L2正则化来选择特征。正则化惩罚项越大,那么模型的系数就会越小。当正则化惩罚项大到一定的程度的时候,部分特征系数会变成0,当正则化惩罚项继续增大到一定程度时,所有的特征系数都会趋于0. 但是我们会发现一部分特征系数会更容易先变成0,这部分系数就是可以筛掉的。也就是说,我们选择特征系数较大的特征。常用的L1正则化和L2正则化来选择特征的基学习器是逻辑回归。(L1惩罚项降维的原理在于保留多个对目标值具有同等相关性的特征中的一个,所以没选到的特征不代表不重要。故,可结合L2惩罚项来优化。具体操作为:若一个特征在L1中的权值为1,选择在L2中权值差别不大且在L1中权值为0的特征构成同类集合,将这一集合中的特征平分L1中的权值,故需要构建一个新的逻辑回归模型)

from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression

(2)基于树模型的特征选择法

可以使用决策树或者GBDT。一般来说,可以得到特征系数coef或者可以得到特征重要度(feature importances)的算法才可以做为嵌入法的基学习器。
树模型中GBDT也可用来作为基模型进行特征选择,使用feature_selection库的SelectFromModel类结合GBDT模型。

from sklearn.feature_selection import SelectFromModel
from slearn.ensemble import GradientBoostingClassifier

4、寻找高级特征(特征构造)

在数据挖掘的过程中,为了提取更有用的信息,挖掘更深层次的模式,提高挖掘结果的精度,我们需要利用已有的特征集构造出新的特征,并加入到现有的特征集合中。(即我们从业务特征中自己去寻找高级数据特征)

在Kaggle之类的算法竞赛中,高分团队主要使用的方法除了集成学习算法,剩下的主要就是在高级特征上面做文章。所以寻找高级特征是模型优化的必要步骤之一。当然,在第一次建立模型的时候,我们可以先不寻找高级特征,得到基准模型后,再寻找高级特征进行优化。(比如有车的路程特征和时间间隔特征,我们就可以得到车的平均速度这个二级特征。根据车的速度特征,我们就可以得到车的加速度这个三级特征等)

寻找高级特征最常用的方法有:若干项特征加和,若干项特征之差,若干项特征乘积,若干项特征除商。

寻找高级特征它是根据业务和模型需要而得,而不是随便的两两组合形成高级特征,这样容易导致特征爆炸,反而没有办法得到较好的模型。

一般而言,聚类的时候高级特征尽量少一点,分类回归的时候高级特征适度的多一点。

四、特征工程——降维

当特征选择完成后,可以直接训练模型了,但是可能由于特征矩阵过大,导致计算量大,训练时间长的问题,因此降低特征矩阵维度也是必不可少的。常见的降维方法除了以上提到的基于L1惩罚项的模型以外,另外还有主成分分析法(PCA)和线性判别分析(LDA),线性判别分析本身也是一个分类模型。PCA和LDA有很多的相似点,其本质是要将原始的样本映射到维度更低的样本空间中,但是PCA和LDA的映射目标不一样:PCA是为了让映射后的样本具有最大的发散性;而LDA是为了让映射后的样本有最好的分类性能。所以说PCA是一种无监督的降维方法,而LDA是一种有监督的降维方法。

1、主成分分析法(PCA)

from sklearn.decomposition import PCA
"""PCA主成分分析"""
def pca():
"""
PCA:
本质:PCA是一种分析、简化数据集的技术
目的:是数据维数压缩,尽可能降低原数据的维数(复杂度),损失少量信息。
作用:可以消减回归分析或聚类分析中特征的数量
语法:
PCA(n_components=None)
将数据分解为较为低维空间
PCA.fit=transform(X)
X: numpy array 格式的数据[n_samples,n_features]
返回值: 转换后的指定维度的array
Returns:None
"""
from sklearn.decomposition import PCA
p = PCA(n_components=0.9)
a = [[2, 8, 4, 5],
[6, 3, 0, 8],
[5, 4, 9, 1]]
data = p.fit_transform(a)
print(data)

2、线性判别分析法(LDA)

from sklearn.lda import LDA

3、奇异值分解(SVD)-文本降维

在对文本数据进行向量化以后,由于是稀疏矩阵太稀疏,同样可以使用降维技术,这里使用的是奇异值分解。

from sklearn.decomposition import TruncatedSVD

注:降维技术不是特征选择,降维是把高维数据的特征映射到低维空间中,而特征选择是在高维空间中直接剔除部分特征,选出重要特征。


文章作者: zhen666wua
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 zhen666wua !
  目录