亚马逊AWS官方博客

Data-centric AI之特征工程(第一讲)

序言

这两年我们观察到越来越多的算法工程师重视数据的特征工程,AI业界大佬吴恩达教授在2021年提出了从model-centric AI切换到data-centric AI的论调,我个人认为data-centric AI的三个核心就是特征工程,样本工程和数据集质量(本系列文章将围绕这三个核心来介绍),即使使用深度学习,对结构化数据建模,特征工程仍然是重中之重,而对于结构化数据建模,随着机器学习平台的成熟比如亚马逊云科技的拳头产品Amazon SageMaker,让人们从底层基础设施以及繁杂的训练和推理的各种环境搭建中解放出来,从而有更多的时间和精力关注数据和特征本身,真正迈入“AI平民化”,只要掌握了data-centric AI三个核心,大家都可以利用成熟的模型来建模。很多场景下,甚至你只要把高质量的数据集准备好以后(比如可以借助Amazon  SageMaker Data Wrangler来做数据集的准备),就可以利用 SageMaker Canvas来基于UI的code-free建模,不需要关心算法本身的同时还能得到不错的效果。

为了行文方便,在之后的讨论中我不专门提结构化数据建模。对于涉及到非结构化数据的CV,NLP,语音识别这三大领域来说,现在(2022年)主流都是用深度学习来建模而不考虑复杂的人工提取的特征。因此目前来说,我们讨论的特征工程针对的就是结构化数据建模。更详细的data-centric AI相关的内容请参考该github repo

本文大纲

什么是特征?

连续特征和category特征

什么是好的特征?

特征工程概览

特征工程详细步骤

特征预处理

特征生成

特征选择

特征降维

总结

什么是特征?

特征这个术语有很多别名,比如字段,属性,自变量(在今后的内容中可能会混用这些别名)等等。我们看一个例子,下表中Play Cricket是目标变量也就是我们常说的label/ 标注,其他的变量比如Height,Gender等都是特征。

特征的大致类型如下表:

类型 举例
基本特征 IP地址,性别,年龄,常驻地,手机厂商
统计特征 游戏玩家最近一周内的累积消费金额
组合特征

用户最近点击过的10个商品组成的item id序列特征;

男性用户且使用苹果手机这样的交叉特征

特征有2个统计特点:一是特征是否发散,如果一个特征的方差接近于0,我们称这个特征不发散。也就是说所有样本在这个特征上基本没有差异,这个特征对于样本的区分没有什么用,可以丢弃它(比如1万条样本中的“性别”这个特征的取值都是“男性”,这时候我们说“性别”这个特征的方差就是0.  比如1万条样本中的“国家”这个特征的取值有9900都是“中国”,其他国家一共的样本数才100条,这个时候我们说“国家”这个特征的方差接近于0);二是特征与目标的相关性,与目标相关性高的特征(包括正相关和负相关),应当优选选择。(比如预测试用产品的用户是否在一个月内付费的目标任务,“用户的累积登录次数”这样的特征可能就是与目标相关性高的特征)

连续特征和category特征

在做特征工程的时候,我们要时刻注意每个特征到底是连续特征还是category特征,这个非常重要。Category特征指语义上有枚举特点的特征,包括字符串类型和数值类型。比如[“北京”,“上海”,“深圳”]这样的“城市”特征就是字符串类型category特征;而[“中国”,“美国”,“日本”]这样的特征经过数字编码为[0,1,2]后得到的“国家”特征就是数值类型的category特征。离散特征是指具有数值类型的Category特征。Category特征的枚举值数量越多,我们称它的基数越高(以后为了行文方便,不再区分离散特征和Category特征);连续特征指语义上连续的数值型特征,包括整数类型和浮点类型。需要注意的是,数值型特征不一定就是连续特征。(比如“身高”,“体重”这样的特征都是连续特征;而如上面提到的用数字编码过的“国家”这样的特征就不是连续特征)

对于Category特征来说,我们要判断它是无序还是有序。有序和无序只是相对于当前的目标任务。比如从小到大排列的“学历等级”特征[“小学”,“初中”,“高中”,“学士”,“硕士”,“博士”],在预测收入这样的任务的时候可能是有序特征(有序的含义在这里的体现是:可能学历越高,收入越高),而在预测身体健康程度这样的任务的时候可能就是无序特征(无序的含义在这里的体现是:是否健康与学历高低没有什么关系)。

特征工程阶段不同子步骤的不同方法对category特征的适用性是不同的(比如特征缩放主要是针对连续性特征;比如特征降维的PCA主成分分析算法只是针对连续性特征)。不同的机器学习模型对连续特征和category特征的适用性是不同的(比如GMM高斯混合模型只能使用连续特征,而多项式分布朴素贝叶斯模型只能使用category特征;比如XGBoost模型把所有特征都当成连续特征)。

不同的机器学习模型对category特征的无序和有序的适用性也是不同的。(比如逻辑回归模型LR,如果category特征的基数不是很高(比如小于10的情况),一个可行的做法是把单个category特征变成由多个二值特征组成的One-hot向量(如下图所示)。

比如LightGBM可以处理category特征并且它不考虑该category特征是有序还是无序,因为LightGBM在做树的节点分裂的时候,对于category特征的候选分裂点计算过程不涉及排序)

什么是好的特征?

我们的美好愿望是送到模型中的特征是我们“想要”的特征,这样的特征的特质如下:

特质 举例 备注
对当前任务“有用”的特征

“app版本”这个特征对于预测用户是否付费的任务就很有用;

“用户是否喜欢购物”这个特征对预测用户是否会报名马拉松这样的任务可能就没有用。

特征的好坏一定要放在具体的上下文中来看。
好的category特征的枚举值应在数据集中出现多次 比如8次以上 某个特征值出现次数太少的话,模型对该特征值就几乎学习不到什么知识。
最好具有清晰明确的含义 “商品最近一天的点击率”这样的特征含义就很清晰;而“商品day1点击率”这样的特征就有歧义了,是表示第一天的点击率还是最近一天的点击率还是当天的点击率? 最好能见文识意
特征的值不应该超出语义范围或者业务知识范围

“季节”特征不应该出现除了春夏秋冬外的其他季节;

“天气气温”特征不应该有太离谱的值比如100摄氏度出现。

为了更好的模型效果,这个一定要在训练时和推理时都要检查并处理的
与目标变量相关性高的特征(包括正相关和负相关) “用户消费等级”特征对于用户流失预测任务可能就是强特征 经常叫这样的特征是“ 强特征“

特征工程概览

特征工程本质是一项工程活动,它目的是最大限度地从原始数据中提取并加工特征以供模型或者算法使用。在传统机器学习领域流传着这样一句话: “数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已”,从而可见特征工程的重要性。其实对于结构化数据建模,即使用深度学习模型,特征工程也是比模型本身要重要的。

特征工程目前主要是纯手工打造(指的是结构化数据建模),因为特征工程是艺术,几乎不可能全部自动化。但是特征工程的某个部分可以自动化比如自动生成特征:目前(到2022年5月)特征生成自动化不是主流;第四范式在尝试一些特征工程自动化,包括:连续特征自动离散化, 时序特征自动提取,特征交叉自动生成。

下面我们来了解特征工程的详细步骤。

特征预处理之字符串特征转换为数字特征

我们拿到的原始数据中经常会有一些字段是字符串类型的,这个时候我们需要首先根据具体机器学习任务来判定这个字符串特征本质上是category特征还是文本语义特征?比如对于电影推荐场景的CTR点击率预估任务,电影内容的文本描述特征是形如“这个影片呈现了中国60年代知青下乡的各种景象”,该特征是对电影内容本身的刻画,属于文本语义特征;电影出产地的文本描述特征形如“中国北影”,“美国好莱坞”等这些是具有枚举特点的,属于category特征。

如果判定为文本语义特征并且该特征对当前目标任务有用的话,一种做法是用另一个预训练的语言模型来获得这个文本特征的sentence embedding向量(embedding向量可以简单理解为原始特征映射到另一个空间的不可解释的某种表示),然后和其他特征拼接作为下游模型的特征向量。如果判定为category特征,需要把这个字符串category特征转为数值型category特征。

参考如下的流程对字符串category特征做转换:首先结合业务知识考虑是否丢弃对目标任务没有意义的字符串category特征(比如对于信用卡欺诈检测任务来说,“姓名”category特征对这个任务没有什么意义,可以直接丢弃。比如对于音乐歌曲推荐场景来说,“歌曲的演唱者”category特征就不应该丢弃,因为用户可能就是对演唱者感兴趣才播放他唱的歌曲);然后或者把它转换为具有物理意义的数字(比如类似小区门牌号信息这样的地址特征转换为经纬度2个特征);或者将单个字符串特征拆为多个字符串特征并编码为数字值(比如把通信地址特征或者IP特征可以拆分/转换为国家,省,市三个特征);或者对某个字符串category特征的训练集中出现的所有字符串建立一个映射表并索引对应的字符串(为了完整,需要有一个占位索引来表示之后的数据中看到的不在映射表中的字符串)

特征预处理之异常值处理

我们拿到的原始数据很可能或多或少都会有一些特征的取值不太合理,也就是说这些特征值可能是异常值。异常点(又叫离群点)产生原因:一种是人为错误(人工录入数据或者人工整理数据出现了问题);一种是自然原因(某些数据样本本身就和大多数数据样本不同或者采集数据的设备/服务的问题导致)

对于非异常检测任务,机器学习模型希望数据集(包括训练集,测试集,验证集)都是正常的样本点。处理的流程如下:首先需要把异常检测任务作为非异常检测任务的前置任务来做数据预处理,找到并人工确认异常点。(异常检测的方法有很多比如基于规则的,基于统计的,基于模型的等等,可以参考我总结的另一个文档);然后如果异常点的原因能归结到特征粒度:如果之后要选择对异常值相对不敏感的模型比如随机森林或XGBoost,这里可以先跳过异常值处理步骤。然后把异常值当成缺失值来处理;或者用变换方法,比如对异常的连续性特征取自然对数,对异常的连续性特征分箱处理,对异常的连续特征做3-sigma截断处理,分位数上下限截断处理或者最大最小值截断处理(参考Amazon SageMaker Data Wrangler中关于异常值的处理:);否则从数据集中剔除异常样本,把异常样本单独存储以便之后做异常检测。

特征预处理之缺失值处理

我们拿到的原始数据中一般都会有一些特征有缺失的现象(见下图)。缺失值的原因有几下几种:暂时无法获取某些特征值;出现人为错误;数据采集阶段出现的程序/设备故障导致;历史局限性;有意隐瞒的特征值;有些样本的特征值根本就是不存在的;从异常值转换而来;线上预测时从feature store获取特征超时。

通常用来处理缺失值的方式:在预测时处理缺失值并写完整的特征向量到日志,训练时直接用该日志(最建议的方式,能最大程度的保证特征的线上线下一致性);或者让训练算法在训练阶段自行处理缺失值(XGBoost和LightGBM都支持自行处理缺失值);或者在训练开始前处理掉缺失值。(建议:在做缺失值处理的时候,尝试新增一个特征来标识有缺失值的特征对应的该条样本这个特征是否做了缺失值处理,可能最后的模型效果更好(相当于给模型更多的的信号)。具体可以参考Amazon SageMaker Data Wrangler缺失值处理中提到的这个indicator:)

对训练集处理缺失值(有可能多种特征都有缺失值),流程如下(处理过程中为了不发生信息泄露,不要去看验证集和测试集中的该特征的任何取值):

  • 首先逐个检查每个特征的缺失情况。对于某个特征,如果有太多的训练样本有缺失值比如超过1半的样本量,考虑是否可以从数据集中去除这个特征。如果需要去除的特征有很多个,说明数据集质量太差,最好考虑重新收集数据;
  • 然后逐个检查每个样本的缺失情况。对于某个样本,如果缺失的特征数量太多比如超过1半数量的特征都缺失,那么可以考虑是否可以把这个样本给去除;
  • 接着考虑如果之后的模型选择是能直接处理含缺失值样本的模型比如XGBoost,那么先跳过缺失值处理步骤;否则进行缺失值补全。

在训练集做完缺失值处理后,就可以处理测试集和验证集的缺失值了:如果是连续性特征,用训练集该特征的平均值或者中位数补全;如果是category特征,用训练集该特征的众数(出现频率最高的那个值)来补全。在预测时处理缺失值常见的方法就是使用预先计算好的连续特征的平均值/中位数,或者category特征的众数来补全。

针对训练集,常见的缺失值补全的方法(均值补全和同类均值补全可能是用的最多的方法):

方法 原理 备注
均值补全

如果特征是连续型, 用平均值补全;

如果特征是离散型,用众数补全

对于连续特征,除了均值补全,中位数补全也比较常用。
同类均值补全 首先按照目标变量的label对样本进行分类,然后以该类中的样本的均值或者众数来补全缺失值 适合分类问题
基于聚类的补全 把没有缺失值的特征都抽取出来组成新的数据集进行聚类,然后把每个样本的缺失值进行同簇均值或者众数补全

这种方法类似同类均值补全,不过它对分类和回归问题都适用;

它还可以做簇间加权均值补全,加权方法用样本对每个簇的归属度。

矩阵补全 从最小化矩阵的秩出发,通过利用数值优化来解出矩阵中的缺失值。
高维映射 把单个离散category变量变为one-hot向量。one-hot向量长度为category枚举值数量+1,缺失值就表示为最后的那个other特征 对于连续特征,高维映射无法直接处理。可以对连续特征离散化之后,再进行高维映射。
基于预测的补全 将含缺失值的特征作为预测目标,并排除掉原来的目标变量,建立模型来预测。 这种方法的效果相对较好。

对于有缺失值的数据集在经过缺失值处理后如何选型,可以参考如下:数据量很小,用贝叶斯模型;数据量适中或者较大,用XGBoost或者LightGBM这样的模型;数据量较大,也可以用神经网络;避免使用距离度量相关的模型,比如SVM,线性回归,逻辑回归(可能的原因是,缺失值处理会带入一定的噪音,而基于距离的模型本身对噪音就比较敏感)

Data-centric AI之特征工程第一讲到此结束。本文介绍了特征相关的概念以及连续特征和category特征的特点,归纳了“好的特征”应有的特质。在此基础上,介绍了特征预处理的三个子步骤即字符串特征转换为数值特征,异常值处理和缺失值处理。相信大家现在对特征以及特征工程有了更深刻的理解,接下来的第二讲我会继续讲特征预处理。再次感谢大家的阅读。

本篇作者

梁宇辉

亚马逊云科技机器学习产品技术专家,负责基于亚马逊云科技的机器学习方案的咨询与设计,专注于机器学习的推广与应用,深度参与了很多真实客户的机器学习项目的构建以及优化。对于深度学习模型分布式训练,推荐系统和计算广告等领域具有丰富经验。