购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

4.5 自动化特征工程生成方法

下面主要介绍3种自动化特征工程的生成方法,分别是深度特征合成算法、FeatureTools自动特征提取以及基于时序特征的自动化特征工程。

4.5.1 深度特征合成算法

深度特征合成(Deep Feature Synthesis,DFS)是一种用于对关系数据和时间数据执行特征工程的自动方法。深度特征合成并不是通过深度学习生成特征,而是通过多重的特征叠加,一个特征的深度是构建这个特征所用到的基元的个数。关于DFS有如下3个关键的概念:

1)特征主要来源是数据集中数据点之间的关系。数据库多表数据和日志文件的事物数据等关系数据集是企业中最常见的数据类型,而处理关系型数据也是数据处理的主要部分。DFS也擅长针对这一类数据实施特征工程。

2)对于不同的数据集,许多特征的构建是通过相似的数学运算得到的。例如对某公司的购买记录数据集进行分析,可以挖掘出用户的最大金额交易。对于其他数据集,例如航班数据集,我们可以通过相同的数学运算,挖掘出航班最长等待时间。不同的数据集尽管描述各不相同,但可以对数值列表采用相同的数据操作。这些操作与数据本身无关,所以称之为“基元”。

3)新的特征是基于先前获取的特征构建的。基元定义了数据的输入和输出类型,通过特征基元组合,可以构建出更为复杂且有效的特征。使用基元的另一个好处在于,基元可以通过参数化的操作生成许多意想不到的有趣特征,如果要添加新的基元,DFS会自动与现有基元进行组合,不需要人工设置。这是因为基元是独立于特定数据集的,只要数据类型相同,基元就可以进行自动组合。

4.5.2 Featuretools自动特征提取

1.Featuretools库介绍

Featuretools是一个自动执行特征工程的开源库,它可以提高特征工程的效率,采用客观的方法来创建新的特征并将其用于机器学习的任务。Featuretools将深度特征合成算法作为库的核心内容,以特征基元作为基本操作,通过叠加基元操作得到新的特征。

2.Featuretools库使用规则

Featuretools是基于数据实体和实体时间的关系,基于DFS算法使用特征基元等操作来实现自动化的特征提取。

(1)实体和实体集

一个实体集(entity set)是实体(entity)和实体之间关系(relationship)的集合,在Featuretools中,实体集有利于准备和结构化数据集用作特征工程。

原始的数据表一般以DataFrame的形式保存,每一张数据表都是一个实体,而每个实体都必须含有唯一元素的索引,用来区分不同的数据。我们需要为这些实体构建有利于Featuretools使用的实体集。

①创建实体集

实体集的初始化可以使用ft.EntitySet(id="name")函数来构建一个新的实体集,如果需要对实体集命名,修改id参数即可对实体集命名。

②添加实体

实体集创建成功后需要向实体集内添加实体,使用ft.entity_from_dataframe()函数可以通过修改以下参数,来实现对函数功能的选择:

·entity_id参数设置添加实体的名字;

·dataframe参数确定表;

·index和time_index参数确定实体的索引;

·variable_types字典可以对实体中的数据类型进行定义。

③添加实体间的关系

最后我们需要添加实体集中各个实体之间的关系,通过ft.relationship()函数添加实体之间的关系,也可以通过EntitySet.add_relationship(new_relationship)来添加新的实体关系。

创建好实体集后就可以将实体集用于后续的特征提取。

(2)DFS

如果不使用自动化特征工程,则可以直接运行DFS来生成特征,通过ft.dfs()函数来生成特征矩阵,dfs函数具有以下参数:

Entityset:实体集的名称。

target_entity:实体集中的目标实体。

primitives:选择使用的特征基元操作列表,这里的基元操作有两种,一种是聚合基元,一种是转换基元。

max_depth:特征叠加深度。通过叠加产生的特征比通过单个特征基元产生的特征更加具有表现力,这就能够为机器学习模型提供更为复杂有效的特征。

(3)特征基元

特征基元是Featuretools用来自动构建特征的基础操作,通过单独使用或者叠加使用特征基元构造新的特征。使用特征基元的意义在于,只要限制输入和输出的数据类型,就可以在不同的数据集中采用相同的特征基元操作。

特征基元有如下两种:

·聚合基元:根据父表与子表的关联,在不同的实体间完成对子表的统计操作。

·转换基元:转换基元是对单个实体进行的操作,对实体的一个或者多个变量进行操作,并为该实体统计出一个新的变量。

如果需要自动提取特征,只需要调用相同的ft.dfs()函数,但是不传入agg_primitives选择特征基元,就可以让Featuretools自动生成特征。

除此之外,我们还可以通过API来定义自己的特征基元,确定特征基元的类型,定义输入和输出的数据类型,在Python中编写该特征基元的功能函数,就可以实现特征基元,并可以在和其他基元的叠加中使用。

Featuretools库以DFS为核心,通过叠加使用特征基元操作,能够构建大量有效的特征,为自动化特征工程提供了很大的帮助。

3.Featuretools库使用实例

(1)Featuretools安装

Featuretools已经可以用于Python 2.7、3.5和3.6了,官网推荐的安装方式是使用pip或者conda安装,pip的安装方式如下:


python -m pip install featuretools

也可以从conda-forge上安装,安装方式如下:


conda install -c conda-forge featuretools

为了能使用EntitySet.plot来更直观地观察数据,可能需要安装graphviz库,在conda下的安装方式为:


conda install python-graphviz

在macOS环境下的安装方式为:


brew install graphviz
pip install graphviz

(2)Featuretools库导入

下面会介绍一个使用DFS自动提取特征的实例,以基于时间戳的客户事务组成的多表数据集为例。首先需要载入Featuretools库:


import featuretools as ft

(3)数据的载入

导入多表数据集。导入的多表数据集是一个字典,我们需要从多表数据集中提取我们需要的表:


data = ft.demo.load_mock_customer()
customers_df = data["customers"]
sessions_df = data["sessions"]
transactions_df = data["transactions"]

在Featuretools中,每一张表都称为一个实体,3个表的结构如表4-4~表4-6所示。

表4-4 实体1

表4-5 实体2

表4-6 实体3

(4)创建实体间的关系

由于Featuretools需要对实体进行操作,所以我们要构建适合Featuretools的输入数据的格式,根据这些表,构建一个实体构成的字典:


entities = {"customers" : (customers_df, "customer_id"),
            "sessions" : (sessions_df, "session_id", "session_start"),
            "transactions" : (transactions_df, "transaction_id", "transaction_time")}

再由各个表的关系构建关于实体间的关系列表:


relationships = [("sessions", "session_id", "transactions", "session_id"),
                 ("customers", "customer_id", "sessions", "customer_id")]

(5)运行dfs

对于dfs函数来说,必须输入实体字典、实体之间的关系以及需要生成特征的实体。上述创建的实体和实体关系可以直接输入到dfs函数当中。函数的输出值是一个特征矩阵和有关各个特征的定义。


feature_matrix_customers, features_defs = ft.dfs(entities=entities,
                                     relationships=relationships,
                                               target_entity="customers")

通过参数的设定,就可以生成一系列有关“customers”的行为描述的特征,这些特征可以用到后续的模型中。

接着查看特征矩阵,就可以发现生成了一系列的新特征。图4-5是特征生成的结果。

图4-5 特征生成

(6)改变目标实体

DFS的强大之处在于其可以对任意的实体目标,通过实体之间的关联,从数据中生成特征矩阵,只需要改变目标的实体,就可以针对不同的实体生成对应的特征矩阵。

4.5.3 基于时序数据的自动化特征工程

1.时序数据

时序数据即时间序列数据,是同一指标按时间顺序记录的数据列。在同一数据列中的各个数据必须是同口径的,要求具有可比性。时序数据可以是时期数,也可以是时点数。时间序列分析的目的是通过找出样本内时间序列的统计特性和发展规律性,构建时间序列模型,进行样本外预测。

在建立模型时要求时间序列是平稳的,但实际进行分析的时间序列尤其是来自经济领域的时间序列大多是非平稳的。这些非平稳的时间序列往往具有某些典型的数据特征。在建立模型时,往往根据序列表现出的数据特征考虑合适的时间序列模型。

2.TSFRESH

(1)TSFRESH(时序特征提取与选择)介绍

时序数据在数据分析和机器学习中具有很重要的意义,从时序数据中提取特征也是数据预处理中的关键一步。假设我们需要从时序数据中提取想要的数据,例如最大值和最小值等,一般都会采取手工计算的方法得到值。如果需要计算更为复杂的时序数据特征,往往会造成时间的浪费,间接影响建模的效果,如图4-6所示。

图4-6 复杂时序数据

采取传统的手工计算时序数据的特征通常会用到滑动平均等方法,这样会浪费大量的时间,并且在特征的选取上可能会产生一定的困扰。通过使用TSFRESH包则可以高效准确地自动提取时序数据的特征,从而节省出更多的时间用于构建更好的模型。

TSFRESH是一种兼容于Pandas和scikit-learn接口的Python包,用于提取时序数据特征,TSFRESH具有以下特点:

·减少特征工程的时间。TSFRESH通过自动提取构建特征。

·自动提取超过100种特征。这些特征包含了描述时间序列的基本特征,例如峰值的数量、平均值和最大值等,也包含了更复杂的特征,例如反转对称统计量等。只需一次操作即可提取这些特征。这些提取的特征可以用于后续统计和机器学习模型的构建。

·过滤无关的特征。时间序列通常会包含噪声、冗余或者无关信息。这些信息提取出的特征对于机器学习往往是没用的,有时甚至会对模型的效果产生负面影响。TSFRESH包有一个内置的过滤程序,这个过滤程序用于评估每个特征对于当前任务的解释能力与重要性。过滤程序基于成熟的假设检验理论,采用了多重检验的方法,在数学上控制了不相关比例的百分比。将没有意义的特征去掉,保留更为重要的特征,这样也可以降低数据的维度。

(2)TSFRESH的使用规则与原理

①数据的输入格式

TSFRESH的3种格式的数据输入都是pandas.DataFrame,其拥有如下4种属性:

·column_id:时间序列所属实体。

·column_value:时间序列的实际值。

·column_sort:对时间序列排序的值,不需要具有等步长或相同的时间标度。如果省略则默认按照递增顺序排列。

·column_kind:不同类型的时间序列的名称。

其中column_id和column_value为必备属性。

TSFRESH的3种输入格式如下所示:

1)扁平数据表(Flat DataFrame):这一类的输入column_value和column_kind设置为None。假设对于不同类别的时间序列数据x和y,在不同实体A和B的值的数据结构如表4-7所示。

表4-7 扁平数据表

TSFRESH会分别为所有的id、x和y类提取特征。

2)堆数据表(Stacked DataFrame):通过设置column_value和column_kind值,这一类数据的优点在于不同时间序列的时间不必对齐,不同类型的时间戳不必对齐,如表4-8所示。

表4-8 堆数据表

3)扁平数据表字典(Dictionary of Flat DataFrame):输入也可以是一种字典映射,字典的key是时间序列的类型,字典的value即只含该类型时间序列数据的DataFrame。

②数据的输出格式

无论采取哪种输入格式,最终的输出格式都是相同的,如表4-9所示。

表4-9 数据输出格式

其中x特征使用所有x值计算(独立于A和B),y特征使用所有y值计算,以此类推。

③特征提取

TSFRESH库可以提取数据集的完整全面的特征,也可以通过调整参数来选取模型所需的特征。

·使用tsfresh.extract_features()函数即可提取数据集的完整特征。

·设置不同的参数可以提取不同类别的特征。

通过default_fc_parameters字典,调用参数作为字典的键值对,不同的参数组合都会在调用过程中产生一个特征。另外,也可以使用kind_to_fc_parameters={"kind":fc_parameters}字典,对不同类型的时间序列分别提取特征进行控制。

④特征过滤

特征选择的重要问题是强相关和弱相关属性的区分,在预测维修或者生产线优化等应用中,对多个时间序列关联的label进行分类和回归时尤为困难,为了解决这一问题,TSFRESH使用fresh算法,由tsfresh.feature_select.relevant.calculate_relevant_table()函数调用,这是一种高效、可伸缩的特征提取算法,可以用于特征过滤,同时可以控制不相关特征的百分比。

TSFRESH的特征过滤分为如下3步:

1)提取特征:利用完备的特征映射刻画时间,考虑用于描述元信息附加特征,并计算派生特征,从原始数据中提取聚合特征。

2)特征显著性测试:根据每个特征对目标的预测意义进行单独评估,测试结果是一个p值向量,量化了每个目标对预测结果的重要性。

3)多重测试:通过Benjamini-Yekutieli procedure对p值向量进行评估,用于确定要保留哪些重要的特征。

(3)使用实例

①TSFRESH的安装

编译后的TSFRESH位于PyPI,所以直接使用pip就可以安装:


pip install tsfresh

②数据的输入

此处使用一个机器人的故障数据集作为测试用例:


from tsfresh.examples.robot_execution_failures import 
download_robot_execution_failures, \
    load_robot_execution_failures
download_robot_execution_failures()
timeseries, y = load_robot_execution_failures()

读取数据后,时序数据便会读入变量timeseries中,以DataFrame的形式保存。数据格式如表4-10所示。

表4-10 时序数据格式

分别查看不同类型的数据集,通过画图可以清楚地分辨出现故障情况和未出现故障情况下的时序数据图,其中id=3为未出现故障,id=20为出现故障,通过TSFRESH可以将差异量化,从而提取6个类别的时序特征,如图4-7和图4-8所示。

图4-7 未出现故障时序图

图4-8 出现故障时序图

③提取特征

提取全部特征。通过extract_features函数可以将有关timeseries的全部特征提取出来。此处设置column_id参数为机器人的id参数,column_sort为时间参数。


from tsfresh import extract_features
extracted_features = extract_features(timeseries, column_id="id", column_sort="time")

最终会返回一个不同id的机器人的4764个特征的DataFrame,如图4-9所示。

图4-9 不同id机器人的特征

④特征过滤

得到的特征数量过多,需要过滤掉其中统计量低且不能用于给定数据的特征。


from tsfresh import select_features
from tsfresh.utilities.dataframe_functions import impute 

impute(extracted_features)
features_filtered = select_features(extracted_features, y)

经过特征过滤后,只留下了631个特征,剩下的特征可以用于后续的模型训练和分类,如图4-10所示。

图4-10 过滤后的特征

3.梯度提升决策树(GDBT)

GDBT虽然是用于机器学习的回归或者分类的算法,但是可以将其中间树节点的值作为特征,从而得到更准确、性能更好的特征。

(1)GBDT概述

梯度提升决策树(Gradient Boosting Decision Tree,GBDT)是提升(Boosting)家族的成员,是一种迭代的决策树算法,通过多棵决策树的累加结论得到最终的答案,属于泛化能力较强的算法。其核心在于,每一棵决策树通过之前学习的全部决策树得到结论和残差,加上预测值后得到真实值的累加量。GBDT的思想使其在发现多种有区分性的特征和在特征组合上具有天然的优势。

GBDT也是一种重要的机器学习算法,可以用于大多数的回归问题。

(2)GBDT算法原理

理解GBDT需要理解3个概念:回归决策树(Regression Decision Tree)、梯度提升(Gradient Boosting)和缩减(Shrinkage)。这3个基本原理也是GBDT的工作原理。

①回归决策树(Regression Decision Tree)

决策树是已知各项事件发生的概率,对不同的特征单独处理,以信息熵构建一棵信息熵下降幅度最大的树形结构,通过决策树结构的预测,使得最终熵值为0,并以此作为回归预测。

决策树由根节点、非叶节点和叶节点组成。

根节点代表的是整个样本中最重要的特征,不同的决策树模型判定特征重要的方法也不同,ID3根据信息增益来判断,C4.5根据信息增益率来判断,CART则采用的是基尼系数来判断。

非叶节点是对某个特征的测试,每个节点根据属性测试将结果划分到不同的子节点当中。

叶节点表明最终分类的标签,每一个叶节点都是通过一系列的分类得到的预测结果。

每一个根节点到叶节点都是一个决策树预测的过程,从根节点开始,对于样本中的不同特征,按照其值来选择不同的输出分支,一直达到叶节点。

GBDT中用到的决策树都是回归决策树,虽然可以通过一些调整使其成为分类回归树,但是其本质还是回归的决策树。

②梯度提升(Gradient Boosting)

Boosting是一种集成学习,通过若干个弱分类器组成强分类器。GBDT采用的则是多棵决策树共同决策。当然这里的迭代不是简单的投票产生的决策,如果使用相同的数据集,每次训练得到的决策树就一定会相同。GBDT的核心就在于,将所有的树的结论累加得到最终结果。每次决策树得到的结果并不是预测的真实结果,而是与之前所有的树的结论和的残差。

GBDT虽然提到了梯度,但是梯度(Gradient)的概念并没有用到算法当中,这里使用了残差作为全局最优的方向,所以没有用到梯度的求导计算。梯度的提升在于,只要前一棵树的损失函数是把误差作为衡量目标的话,残差向量就可以作为全局最优的方向,这样就类似于梯度的计算,也体现了梯度的思想。

这里可以举一个简单的例子来说明GBDT的迭代过程。

假设我们要预测一个人的年龄,他的真实年龄是30岁,第一棵决策树预测出来的结果是25岁,与真实年龄差了5岁,于是残差就是5岁。这个时候第二棵决策树就以5岁为目标进行学习,若果学习得到的结果是3岁,则残差变为了2岁,然后继续学习。

③缩减(Shrinkage)

缩减是GBDT的重要优化的方法。它的核心思想在于,为了防止过拟合,GBDT每次都通过更小的逼近来接近结果。在一般的机器学习中,前一棵树学习到的结果并不是百分之百准确的,所以在进行累加的时候,只累加前面树的一部分,通过更多的决策树来弥补前面所有学习树的不足。

具体的实现方法是:再次以残差作为下一棵树的学习目标,但是给学习出来的结果增加了一个权重,每次累加的时候只累加一小部分,这个权重一般在0.001~0.01,这样的操作也能使各个树的残差不至于陡变,是一种减少过拟合的方法。

(3)GBDT的算法流程

GBDT算法也是基于上述3个重要概念构成的。和传统的机器学习算法一样,GBDT也分为回归算法和分类算法。

①对于回归算法

输入:训练样本D={(x 1 ,y 1 ),(x 2 ,y 2 ),…(x m ,y m )}(其中x为样本的特征,y为样本的标签)

最大迭代次数T

损失函数L

输出:强学习器f(x)

算法流程如下:

1)初始化弱分类器

2)对于每轮迭代首先计算出负梯度

然后利用(x 1 ,r ti )(i=1,2,…m)来拟合回归树,以此作为第t棵回归树。回归树对应的子节点区域为R tj ,j=1,2,…J,J为第t棵回归树的子节点个数。

最后通过对叶子区域的节点,计算出最佳拟合值c tj ,并以此更新强学习器。

3)得到的强学习器的表达式为

如果对于上述的梯度计算难以理解的话,可以将负梯度考虑为残差向量,决策树始终朝着残差为训练目标,最后得到一个强分类器,就是GBDT得到的最终结果,这会有助于理解回归的GBDT算法。

②对于分类算法

虽然分类算法和回归算法的思想类似,但是回归输出的是连续值,而分类输出的是离散的值,这就导致很难从类别上去拟合,所以用对数似然函数的方法,用概率的形式来表示预测值和真实值。

二分类算法需要将损失函数改成类似于逻辑回归的损失函数,此时损失函数为:

这里运用到逻辑回归的意义在于回归的算法可以将回归问题转换为简单的二分类方法。

计算出负梯度误差为:

各个叶节点的最佳负梯度的拟合值为:

由于负梯度的拟合值比较难优化,一般用近似值代替即可:

对于多分类算法,根据多元逻辑回归,k分类的对数似然函数为:

如果样本输出的类别是第k类,则y k, =1,而对于其他的类别来说,

第k类的概率为:

对于第i个样本来说,第t轮的负梯度误差为:

各个叶节点的最佳负拟合梯度为:

多元分类的负梯度比二元分类的梯度更加复杂,所以用近似值代替可以进行简化优化:

GBDT的回归和分类算法的主要思想大致相同,除了在负梯度的计算以及在各个叶节点的梯度拟合不同。

(4)GBDT生成特征

GBDT不仅可以用于回归和分类算法,还可以用来构造新的特征。在实际问题中,我们获得的数据集中的特征可能不太适合直接用于机器学习,所以需要从数据集中挖掘可以使用的特征。用GBDT构建特征的思路是,先用已有特征训练GBDT模型,然后通过训练得到的GBDT模型的决策树来构建新的特征。Facebook发表的一篇论文中提到了通过GBDT和RL结合,可以构建出新的特征。

对于连续值来说,通过非线性变换,可以使用分箱的方法,将连续的特征分为不同的阶段,再用这些阶段的值进行学习,这样有利于将信息最大化。

对离散值来说,通过元组组合,构建特征最简单的方法就是通过笛卡儿积,将不同的特征组合创建一个新的特征,所有创建的特征并不是全部都有意义的,可以去除无意义的特征,保留下有用的特征。

GBDT是实现非线性转换和元组组合这两种方法的有效又方便的方法。GBDT构建新特征的思想在于,用原始数据训练GBDT模型,再将训练得到的每棵单独的树视为一个分类特征,最终将落入的叶节点作为索引,然后使用1-k编码作为特征,如图4-11所示。

图4-11 决策树模型

从图4-11中可以看出这是有两棵子树的决策树模型,两棵决策树结构都有3个叶节点,如果一个实例最后分配到第1棵子树的第3个叶节点和第2棵子树的第1个叶节点,那么它的二进制向量为[0,0,1,0,1,0],其中前3项对应的是第1棵子树的叶节点,后3项是第2棵子树的叶节点。将其输入线性分类器。每一轮的迭代都会创建新的树来学习先前的树的残差。从树的根节点到叶节点的遍历可以表示某些特征的规则,将二元向量通过一定的权重进行线性回归,就可以得到新的特征值。

基于GBDT构建转换特征的思想,对于不同的决策树进行特征提取,也是可以达到实现自动化特征工程的目的。 fMyLctcmNUKGvONEiD78ZRXRt/WuIZ0M8+glBHjV9lgA/gKG0m5x8qYXAaAZNX7i

点击中间区域
呼出菜单
上一章
目录
下一章
×