特征工程之特征表达

          在特征工程之特征选择中,我们讲到了特征选择的一些要点。本篇我们继续讨论特征工程,不过会重点关注于特征表达部分,即如果对某一个特征的具体表现形式做处理。主要包括缺失值处理,特殊的特征处理比如时间和地理位置处理,离散特征的连续化和离散化处理,连续特征的离散化处理几个方面。

1. 缺失值处理

          特征有缺失值是非常常见的,大部分机器学习模型在拟合前需要所有的特征都有值,不能是空或者NULL。那么如果有缺失值我们需要怎么处理呢?

     首先我们会看是该特征是连续值还是离散值。如果是连续值,那么一般有两种选择,一是选择所有有该特征值的样本,然后取平均值,来填充缺失值,另一种是取中位数来填充缺失值。如果是离散值,则一般会选择所有有该特征值的样本中最频繁出现的类别值,来填充缺失值。在sklearn中,可以使用preprocessing.Imputer来选择这三种不同的处理逻辑做预处理。

2. 特殊的特征处理

   有些特征的默认取值比较特殊,一般需要做了处理后才能用于算法。比如日期时间,比如显示20180519,这样的值一般没办法直接使用。那么一般需要如何变换呢?

        对于时间原始特征,处理方法有很多,这里只举例几种有代表性的方法。 第一种是使用连续的时间差值法,即计算出所有样本的时间到某一个未来时间之间的数值差距,这样这个差距是UTC的时间差,从而将时间特征转化为连续值。第二种方法是根据时间所在的年,月,日,星期几,小时数,将一个时间特征转化为若干个离散特征,这种方法在分析具有明显时间趋势的问题比较好用。第三种是权重法,即根据时间的新旧得到一个权重值。比如对于商品,三个月前购买的设置一个较低的权重,最近三天购买的设置一个中等的权重,在三个月内但是三天前的设置一个较大的权重。当然,还有其他的设置权重的方法,这个要根据要解决的问题来灵活确定。

       对地理特征,比如“广州市天河区XX街道XX号”,这样的特征我们应该如何使用呢?处理成离散值和连续值都是可以的。如果是处理成离散值,则需要转化为多个离散特征,比如城市名特征,区县特征,街道特征等。但是如果我们需要判断用户分布区域,则一般处理成连续值会比较好,这时可以将地址处理成经度和纬度的连续特征。

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

    有很多机器学习算法只能处理连续值特征,不能处理离散值特征,比如线性回归,逻辑回归等。那么想使用逻辑回归,线性回归时这些值只能丢弃吗?当然不是。我们可以将离散特征连续化处理。

   最常见的离散特征连续化的处理方法是独热编码one-hot encoding。处理方法其实比较简单,比如某特征的取值是高,中和低,那么我们就可以创建三个取值为0或者1的特征,将高编码为1,0,0这样三个特征,中编码为0,1,0这样三个特征,低编码为0,0,1这样三个特征。也就是说,之前的一个特征被我们转化为了三个特征。sklearn的OneHotEncoder可以帮我们做这个处理。

   第二个方法是特征嵌入embedding。这个一般用于深度学习中。比如对于用户的ID这个特征,如果要使用独热编码,则维度会爆炸,如果使用特征嵌入就维度低很多了。对于每个要嵌入的特征,我们会有一个特征嵌入矩阵,这个矩阵的行很大,对应我们该特征的数目。比如用户ID,如果有100万个,那么嵌入的特征矩阵的行就是100万。但是列一般比较小,比如可以取20。这样每个用户ID就转化为了一个20维的特征向量。进而参与深度学习模型。在tensorflow中,我们可以先随机初始化一个特征嵌入矩阵,对于每个用户,可以用tf.nn.embedding_lookup找到该用户的特征嵌入向量。特征嵌入矩阵会在反向传播的迭代中优化。

   此外,在自然语言处理中,我们也可以用word2vec将词转化为词向量,进而可以进行一些连续值的后继处理。

4. 离散特征的离散化处理

   离散特征有时间也不能直接使用,需要先进行转化。比如最常见的,如果特征的取值是高,中和低,那么就算你需要的是离散值,也是没法直接使用的。

   对于原始的离散值特征,最常用的方法也是独热编码,方法在第三节已经讲到。

   第二种方法是虚拟编码dummy coding,它和独热编码类似,但是它的特点是,如果我们的特征有N个取值,它只需要N-1个新的0,1特征来代替,而独热编码会用N个新特征代替。比如一个特征的取值是高,中和低,那么我们只需要两位编码,比如只编码中和低,如果是1,0则是中,0,1则是低。0,0则是高了。目前虚拟编码使用的没有独热编码广,因此一般有需要的话还是使用独热编码比较好。

   此外,有时候我们可以对特征进行研究后做一个更好的处理。比如,我们研究商品的销量对应的特征。里面有一个原始特征是季节春夏秋冬。我们可以将其转化为淡季和旺季这样的二值特征,方便建模。当然有时候转化为三值特征或者四值特征也是可以的。

   对于分类问题的特征输出,我们一般需要用sklearn的LabelEncoder将其转化为0,1,2,...这样的类别标签值。

5. 连续特征的离散化处理

   对于连续特征,有时候我们也可以将其做离散化处理。这样特征变得高维稀疏,方便一些算法的处理。

   对常用的方法是根据阈值进行分组,比如我们根据连续值特征的分位数,将该特征分为高,中和低三个特征。将分位数从0-0.3的设置为高,0.3-0.7的设置为中,0.7-1的设置为高。

   当然还有高级一些的方法。比如使用GBDT。在LR+GBDT的经典模型中,就是使用GDBT来先将连续值转化为离散值。那么如何转化呢?比如我们用训练集的所有连续值和标签输出来训练GBDT,最后得到的GBDT模型有两颗决策树,第一颗决策树有三个叶子节点,第二颗决策树有4个叶子节点。如果某一个样本在第一颗决策树会落在第二个叶子节点,在第二颗决策树落在第4颗叶子节点,那么它的编码就是0,1,0,0,0,0,1,一共七个离散特征,其中会有两个取值为1的位置,分别对应每颗决策树中样本落点的位置。在sklearn中,我们可以用GradientBoostingClassifier的 apply方法很方便的得到样本离散化后的特征,然后使用独热编码即可。 

         具体的一个示例代码如下:

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.preprocessing import OneHotEncoder
X, y = make_classification(n_samples=10)  
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5)
gbc = GradientBoostingClassifier(n_estimators=2)
one_hot = OneHotEncoder()
gbc.fit(X_train, y_train)
X_train_new = one_hot.fit_transform(gbc.apply(X_train)[:, :, 0])
print (X_train_new.todense())

       输出是:

[[0. 1. 1. 0.]
 [1. 0. 0. 1.]
 [1. 0. 0. 1.]
 [1. 0. 0. 1.]
 [0. 1. 1. 0.]]

6. 小结

       本文总结了特征表达的一些具体方法, 但是特征表达的方法便不止于上文中的方法,毕竟这是工程实践。但是上文中的方法是比较普遍的,希望可以给大家一些帮助和启发。 下一篇我们讨论特征预处理和分类类别不平衡的问题处理。

(欢迎转载,转载请注明出处。欢迎沟通交流: liujianping-ok@163.com)             

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大数据挖掘DT机器学习

深度学习大神都推荐入门必须读完这9篇论文

Introduction 卷积神经网络CNN,虽然它听起来就像是生物学、数学和计算机的奇怪混杂产物,但在近些年的机器视觉领域,它是最具影响力...

5245
来自专栏大数据挖掘DT机器学习

挖掘算法&模型

原文:一只鸟的天空(http://blog.csdn.net/heyongluoyao8) 在进行数据挖掘时,首先要进行商业理解,即我们需要...

3917
来自专栏机器学习和数学

[高大上的DL] Deep Learning中常用loss function损失函数的小结

在前面我们分享的如何来训练CNN中,提到了BP算法,还记得BP算法是怎么更新参数w,b的吗?当我们给网络一个输入,乘以w的初值,然后经过激活函数得到一个输出。然...

4.7K8
来自专栏AI科技评论

学界 | 超越何恺明等组归一化 Group Normalization,港中文团队提出自适配归一化取得突破

AI 科技评论:港中文最新论文研究表明目前的深度神经网络即使在人工标注的标准数据库中训练(例如 ImageNet),性能也会出现剧烈波动。这种情况在使用少批量数...

1281
来自专栏企鹅号快讯

人工智能开发者必须知道的十种深度学习方法!

源| AI 科技评论文| Camel 不管是AI也好,其他学科也好,学习、研究的过程中不断反思学科的历史,总结学科的发展现状,找出最重要的理念,总能让人能“吾道...

39713
来自专栏SnailTyan

Going Deeper with Convolutions——GoogLeNet论文翻译——中文版

Going Deeper with Convolutions 摘要 我们在ImageNet大规模视觉识别挑战赛2014(ILSVRC14)上提出了一种代号为In...

5330
来自专栏AI科技大本营的专栏

入门 | 零基础入门深度学习——线性单元和梯度下降

为了帮助编程爱好者,从零开始入门,AI100特别精选了韩炳涛所著《零基础入门深度学习》系列文章,以下Enjoy! 作者 | 韩炳涛 无论即将到来的是大数据时代还...

4278
来自专栏机器之心

深度 | 一文介绍3篇无需Proposal的实例分割论文

选自Medium 作者:Bar Vinograd 机器之心编译 参与:Nurhachu Null、黄小天 本文解析了实例分割领域中的三篇论文,它们不同于主流的基...

4015
来自专栏智能算法

亚像素边缘的直线及圆弧的基元分割

从20世纪70年代起就有不少专家提出了一些有效的亚像素边缘定位的方法,如插值法、灰度矩法和一些组合的算法等。本文在前辈的基础上描述一种图像亚像素边缘检测方法,...

3056
来自专栏人工智能LeadAI

零基础入门深度学习 | 第二章:线性单元和梯度下降

无论即将到来的是大数据时代还是人工智能时代,亦或是传统行业使用人工智能在云上处理大数据的时代,作为一个有理想有追求的程序员,不懂深度学习(Deep Learni...

49712

扫码关注云+社区

领取腾讯云代金券