简介
featuretools是一个可以实现单表的转换操作和多表的跨表连接操作的框架。它擅长于将时间和关系数据集转换为机器学习的特征矩阵。 特征工程常见的方法分为两种:1、针对单表的transform操作,例如log变换,特征编码等,都是在一张表上进行的;2、groupby聚合操作,一般是跨表进行的,比如groupby min max mean等等。 官方文档 参考博客 知乎 知乎
多表操作
定义实体集
实体(entity,多个实体则称为实体集entityset)。实体就是一张表或者一个dataframe,多张表的集合就叫实体集。
- 字典定义实体集
定义一个包含数据集中所有 DataFrame 的字典,同时指定DataFrame中的索引列和时间列,DataFrame中的索引列的数据类型要一致,且数据唯一不重复。
df = {
"glass": (glass, "substrateid"),
"data": (data, 'ID', 'time')
}
定义的字典中的DataFrame通常为父子关系。
- entityset定义实体集:官方更推荐使用entityset来进行实体集(其实就是多张有关联的表)管理。
index用于指定主键;time_index用于指定时间特征,便于featuretools自动统计各种滑窗统计的特征等;dataframe即传入的表数据;entity_id是为这个表数据进行命名;logical_types指定product_id为分类类型数据,区分连续特征和类别特征,可以不填。
import featuretools as ft
es = ft.EntitySet(id='glass_data')
es.entity_from_dataframe(entity_id='glass',
dataframe=glass,
index='substrateid',
time_index="time",
logical_types={
"product_id": Categorical,
"zip_code": PostalCode,
},
make_index=True)
es.entity_from_dataframe(entity_id='data',
dataframe=data,
index='ID',
make_index=True)
也可以在对象上使用设置器来添加数据帧EntitySet。
es["glass"] = glass
-
如果数据帧没有初始化 Woodwork,则第一列将是索引列 -
如果 DataFrame 未初始化 Woodwork,则所有列都将由 Woodwork 推断。 -
如果需要控制时间索引列和逻辑类型,则应在添加数据帧之前初始化 Woodwork。
定义表关系:指定父子关系
- 父子关系定义:(parent_dataframe, parent_column, child_dataframe, child_column)
当两个 DataFrame 具有一对多关系时,我们称一个DataFrame为“父 DataFrame”,另一个DataFrame则为“子 DataFrame”。
- 自定义
relationships = [("glass", "substrateid", "data", "substrateid")]
- 官方ft对象定义
以下代码指定了两张表之间的共同的关联键substrateid。
relation = ft.Relationship(es['glass']['substrateid'], es['data']['substrateid'])
es = es.add_relationship(relation)
特征基元
特征基元(Feature Primitives)分为聚合和转换两类,相当于构造新特征的方法。 官方文档:目前支持的所有基元
ft.list_primitives()
- 聚合函数中支持22个方法:
- 转换函数支持80个方法:
DFS(Deep Feature Synthesis)深度特征合成
深度特征合成:根据实体集里的实体和特征基元创造新特征。 特征基元的顺序会影响构建的特征个数。
DFS 的输出是一个特征矩阵和相应的特征定义列表。
举例:定义 加减乘除 转换基元
trans_primitives=['add_numeric', 'subtract_numeric', 'multiply_numeric', 'divide_numeric']
agg_primitives=['sum', 'median']
fm, features = ft.dfs(entityset=es,
target_entity='data',
max_depth=1,
trans_primitives=trans_primitives,
agg_primitives=agg_primitives,
cutoff_time=pd.Timestamp("2022-1-1 04:00"),
instance_ids=[1,2,3],
cutoff_time_in_index=True,
training_window="2 hour")
另一种输入:DFS 的最小输入是 DataFrame 的字典(dataframes)、关系列表(relationships)以及我们要计算其特征的目标 DataFrame 的名称(target_dataframe_name)。
feature_matrix_customers, features_defs = ft.dfs(dataframes=df,
relationships=relationships,
target_dataframe_name="data",
max_depth=1,
trans_primitives=trans_primitives)
-
max_depth越大生成的特征越多,越复杂,一般取max_depth=1 选择特征基元并自动进行特征工程,我们这里采用加减乘除4个基元,max_depth控制“套娃”的深度,如果是1的话只在原特征上进行,大于1的话不仅会在原来的特征上,还会在其他基元生成的新特征上创造特征,数值越大,允许越深的“套娃”。 -
target_entity主表名字 这里target_entity是主表的名字,最终得到的表是主表,进行的是left join的操作,也就是主表如果有1000行,生成的表最终也是1000行,即使附表可能数据更多,另外,指定的时间的index featuretools自动进行年月日和weekday的分解,原始数据不保留。 -
agg_primitive 聚合函数 默认按这些方法聚合:“sum”, “std”, “max”, “skew”, “min”, “mean”, “count”, “percent_true”, “num_unique”, “mode” -
trans_primitives 转换函数 默认按这些方法转换:“day”, “year”, “month”, “weekday”, “haversine”, “num_words”, “num_characters” -
cutoff_time按时间截取数据 截取时间(cutoff time):指定行数据可用于特征计算的最后一个时间点。在此时间点之后的任何数据都将在特征计算或者操作之前过滤掉。
注:时间索引在截取时间后面的行将自动忽略。
- DFS时间序列特征工程
单表操作
import featuretools as ft
es = ft.EntitySet(id='trace_data')
es.entity_from_dataframe(entity_id='data',
dataframe=data,
index='ID',
make_index=True)
trans_primitives=['add_numeric', 'subtract_numeric', 'multiply_numeric', 'divide_numeric']
feature_matrix, feature_names = ft.dfs(entityset=es,
target_entity='data',
max_depth=1,
verbose=1,
trans_primitives=trans_primitives
)
|