Feature Tools:可自动构造机器学习特征的Python库

目前,不少机器学习项目的模型选择开始转向自动化,而特征工程仍然主要以人工为主。这个过程的重要性可能比模型选择更重要,人工获得的特征总带有必定的局限性。在本文中做者将为咱们介绍如何使用 Feature Tools Python 库实现特征工程自动化,项目已开源。python


机器学习愈来愈多地从人工设计模型转向使用 H20、TPOT 和 auto-sklearn 等工具自动优化的工具。这些库以及随机搜索(参见《Random Search for Hyper-Parameter Optimization》)等方法旨在经过寻找匹配数据集的最优模型来简化模型选择和机器学习调优过程,而几乎不须要任何人工干预。然而,特征工程做为机器学习流程中可能最有价值的一个方面,几乎彻底是人工的。算法

特征工程也被称为特征构造,是从现有数据中构造新的特征从而训练机器学习模型的过程。这一步可能比实际上使用的模型更重要,由于一个机器学习算法只能从咱们给定的数据中学习,因此构造一个和任务相关的特征是相当重要的,参见优质论文《A Few Useful Things to Know about Machine Learning》。bash

一般,特征工程是一个冗长的人工过程,依赖于领域知识、直觉和数据操做。这个过程多是极其枯燥的,同时最终获得的特征将会受到人的主观性和时间的限制。特征工程自动化旨在经过从数据集中自动构造候选特征,并从中选择最优特征用于训练来帮助数据科学家。网络

在本文中,咱们将介绍一个使用 Feature Tools Python 库实现特征工程自动化的例子。咱们将使用一个示例数据集来讲明基本概念(继续关注以后使用真实世界数据的例子)。本文完整代码可在 Github 上找到。数据结构

特征工程基本概念dom

特征工程意味着从现有的数据中构造额外特征,这些特征一般分布在多张相关的表中。特征工程须要从数据中提取相关信息并将其存入单张表格中,而后被用来训练机器学习模型。机器学习

构造特征是一个很是耗时的过程,由于每一个新的特征一般须要几步才能构造,特别是当使用多张表的信息时。咱们能够将特征构造的操做分为两类:「转换」和「聚合」。如下经过几个例子来看看这些概念的实际应用。ide

经过从一或多列中构造新的特征,「转换」做用于单张表(在 Python 中,表是一个 Pandas DataFrame)。举个例子,如有以下的客户表:

咱们能够经过查找 joined 列中的月份或是天然对数化 income 列的数据来构造新的特征。这些都是转换操做,由于它们只用到了一张表的信息。

另外一方面,「聚合」是跨表实现的,并使用一对多的关联来对观测值分组,而后计算统计量。例如,若咱们有另一张包含客户贷款信息的表格,其中每一个客户可能有多项贷款,咱们即可以计算每一个客户贷款的平均值、最大值和最小值等统计量。

这个过程包括根据不一样客户对贷款表进行分组并计算聚合后的统计量,而后将结果整合到客户数据中。如下是咱们在 Python 中使用 Pandas 库执行此操做。

import pandas as pd

# Group loans by client id and calculate mean, max, min of loans
stats = loans.groupby('client_id')['loan_amount'].agg(['mean', 'max', 'min'])
stats.columns = ['mean_loan_amount', 'max_loan_amount', 'min_loan_amount']

# Merge with the clients dataframe
stats = clients.merge(stats, left_on = 'client_id', right_index=True, how = 'left')

stats.head(10)
复制代码


这些操做自己并不困难,可是若是有数百个变量分布在数十张表中,这个过程将没法经过人工完成。理想状况下,咱们但愿有一个解决方案可以在不一样表间自动执行转换和聚合操做,并将结果整合到一张表中。尽管 Pandas 是一个很好的资源,可是仍然有许多数据操做须要咱们人工完成!有关人工特征工程的更多信息,请查阅《Python Data Science Handbook》。

特征工具

幸运的是,Feature Tools 正是咱们正在找寻的解决方案。这个开源的 Python 库能够从一组相关的表中自动构造特征。特征工具基于名为「深度特征合成」的方法(参见《Deep Feature Synthesis: Towards Automating Data Science Endeavors》),这个方法的名字听起来比其自己更高大上(这个名字源于叠加了多重特征,而不是由于使用了深度学习方法!)。

深度特征合成叠加多个转换和聚合操做,这在特征工具的词库中被称为特征基元,以便经过分布在多张表内的数据来构造新的特征。与机器学习中的大多数方法同样,这是创建在简单概念基础之上的复杂方法。经过一次学习一个构造块,咱们能够很好地理解这个强大的方法。

首先,让咱们看一下示例数据。咱们已经看到了上面的一些数据集,而且完整的表组以下所示:

  • clients: 关于信用社客户的基本信息。每一个客户只对应数据框中的一行。

  • loans: 向用户提供的贷款。每项贷款只对应数据框中的一行,可是客户可能有多项贷款。

  • payments:贷款还本的支付。每笔支付只对应一行,可是每项贷款能够有多笔支付。

若是咱们有一个机器学习任务,例如预测客户将来是否会偿还一项贷款,咱们但愿将全部关于客户的信息整合到一张表中。这些表是相关的(经过 client_id 和 loan_id 变量),而且咱们能够经过一系列转换和聚合操做来人工实现这个过程。然而,咱们很快就可使用特征工具来自动实现这个过程。

实体和实体集

特征工具的前两个概念的是「实体」和「实体集」。一个实体就是一张表(或是 Pandas 中的一个 DataFrame(数据框))。一个实体集是一组表以及它们之间的关联。将一个实体集当作另外一种 Python 数据结构,并带有本身的方法和属性。

咱们能够经过如下操做在特征工具中建立一个空的实体集:

import featuretools as ft
# Create new entityset
es = ft.EntitySet(id = 'clients')
复制代码

如今咱们须要整合两个实体。每一个实体都必须带有一个索引,它是一个包含全部惟一元素的列。就是说,索引中的每一个值只能在表中出现一次。在 clients 数据框中的索引是 client_id,由于每一个客户在该数据框中只对应一行。咱们使用如下语法将一个带有索引的实体添加一个实体集中:

# Create an entity from the client dataframe
# This dataframe already has an index and a time index
es = es.entity_from_dataframe(entity_id = 'clients', dataframe = clients, 
                              index = 'client_id', time_index = 'joined')
复制代码

loans 数据框还有另一个惟一的索引,loan_id,同时将其添加到实体集的语法与 clients 同样。然而,payments 数据框不存在惟一索引。当咱们把 payments 数据框添加到实体集中时,咱们须要传入参数 make_index = True,同时指定索引的名字。另外,尽管特征工具能自动推断实体中每列的数据类型,可是咱们能够经过将列数据类型的字典传递给参数 variable_types 来覆盖它。

# Create an entity from the payments dataframe
# This does not yet have a unique index
es = es.entity_from_dataframe(entity_id = 'payments', 
                              dataframe = payments,
                              variable_types = {'missed': ft.variable_types.Categorical},
                              make_index = True,
                              index = 'payment_id',
                              time_index = 'payment_date')
复制代码

对于此数据框,尽管 missed 是一个整数,可是它不是一个数值变量,由于它只能取 2 个离散的数值,因此在特征工具中,将其当作一个分类变量。在将该数据框添加到实体集中后,咱们检查整个实体集:

列的数据类型已根据咱们指定的修正方案被正确推断出来。接下来,咱们须要指定实体集中表是如何关联的。

表的关联

考虑两张表之间「关联」的最好方法是类比父子之间的关联。这是一种一对多的关联:每一个父亲能够有多个儿子。对表来讲,每一个父亲对应一张父表中的一行,可是子表中可能有多行对应于同一张父表中的多个儿子。

例如,在咱们的数据集中,clients 数据框是 loans 数据框的一张父表。每一个客户只对应 clients 表中的一行,可是可能对应 loans 表中的多行。一样,loans 表是 payments 表的一张父表,由于每项贷款能够有多项支付。父亲经过共享变量与儿子相关联。当咱们执行聚合操做的时候,咱们根据父变量对子表进行分组,并计算每一个父亲的儿子的统计量。

为了形式化特征工具中的关联规则,咱们仅需指定链接两张表的变量。clients 表和 loans 表经过 client_id 变量链接,同时 loans 表和 payments 表经过 loan_id 变量链接。建立关联并将其添加到实体集中的语法以下所示:

# Relationship between clients and previous loans
r_client_previous = ft.Relationship(es['clients']['client_id'],
                                    es['loans']['client_id'])

# Add the relationship to the entity set
es = es.add_relationship(r_client_previous)

# Relationship between previous loans and previous payments
r_payments = ft.Relationship(es['loans']['loan_id'],
                                      es['payments']['loan_id'])

# Add the relationship to the entity set
es = es.add_relationship(r_payments)

es
复制代码

该实体集如今包含三个实体(表),以及将这些表链接在一块儿的关联规则。在添加实体和形式化关联规则以后,实体集就完整了并准备好从中构造新的特征。

特征基元

在咱们深刻了解深度特征合成以前,咱们须要了解特征基元的概念。咱们其实早就知道是什么了,只是咱们刚刚用不一样的名字来称呼它们!它们只是咱们用来构造新特征的操做:

  • 聚合:根据父与子(一对多)的关联完成的操做,也就是根据父亲分组并计算儿子的统计量。一个例子就是根据 client_id 对 loan 表分组并找到每一个客户的最大贷款额。

  • 转换:对一张表中一或多列完成的操做。一个例子就是取一张表中两列之间的差值或者取一列的绝对值。

在特征工具中单独使用这些基元或者叠加使用这些基元能够构造新的特征。如下是特征工具中一些特征基元的列表,也能够自定义特征基元。

特征基元

这些基元能够单独使用或是组合使用以构造新的特征。为了使用特定的基元构造新的特征,咱们使用 ft.dfs 函数(表明深度特征合成)。咱们传入 entityset 和 target_entity,这是咱们想要在其中添加特征的表,被选参数 trans_primitives(转换)和 agg_primitives(聚合)。

public class MyActivity extends AppCompatActivity {
@Override  //override the function
    protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       try {
            OkhttpManager.getInstance().setTrustrCertificates(getAssets().open("mycer.cer");
            OkHttpClient mOkhttpClient= OkhttpManager.getInstance().build();
        } catch (IOException e) {
            e.printStackTrace();
        }
}
复制代码

返回的是包含每一个客户新特征的数据框(由于咱们定义客户为 target_entity)。好比咱们有每一个客户加入的月份,这是一个转换操做的特征基元:

咱们也有许多聚合操做的基元,好比每一个客户的平均支付总额:

尽管咱们仅指定了一些特征基元,可是特征工具能够经过组合和叠加这些基元来构造新的特征。

完整的数据框包含 793 列的新特征!

深度特征合成

咱们如今具有理解深度特征合成(dfs)的一切条件。事实上,咱们已经在前面的函数调用中执行了 dfs!深度特征只是叠加多个基元构造的一个特征,而 dfs 只是构造这些特征的过程的名称。深度特征的深度是构造这个特征所需的基元数量。

例如,MEAN(payments.payment_amount)列是深度为 1 的特征,由于它是使用单个聚合操做构造的。LAST(loans(MEAN(payments.payment_amount))是一个深度为 2 的特征,它是由两个叠加的聚合操做构造的:MEAN 列之上的 LAST(最近的)列。这表示每一个客户最近的贷款平均支付额。

咱们能够叠加任意深度的特征,但在实践中,我从没有使用超过 2 个深度的特征。此外,这些特征很难解释,可是我鼓励任何对「深刻」感兴趣的人。

咱们没必要人工指定特征基元,但可让特征工具自动为咱们选取特征。为此,咱们使用相同的 ft.dfs 函数调用,可是不传入任何特征基元。

# Perform deep feature synthesis without specifying primitives
features, feature_names = ft.dfs(entityset=es, target_entity='clients', 
                                 max_depth = 2)

features.head()
复制代码

特征工具构造了不少特征供咱们使用。尽管这个过程确实能自动构造新的特征,可是它不会取代数据科学家,由于咱们仍然须要弄清楚如何处理这些特征。例如,咱们的目的是预测一位客户是否会偿还贷款,咱们能够寻找与特定结果最相关的特征。此外,若是咱们具备领域知识,咱们能够用这些知识来选择指定的特征基元或候选特征的种子深度特征合成。

下一步

特征工程自动化解决了一个问题,可是带来了另外一个问题:特征太多了。尽管在拟合一个模型以前很难说哪些特征是重要的,但极可能不是全部这些特征都与咱们想要训练的模型的任务相关。此外,拥有太多特征(参见《Irrelevant Features and the Subset Selection Problem》)可能会致使模型性能不佳,由于较无益的特征会淹没那些更重要的特征。

特征过多问题以维度灾难著称。随着特征数量的上升(数据维度增加),模型愈来愈难以学习特征与目标之间的映射关系。事实上,让模型表现良好所需的数据量与特征数量成指数关系。

维度灾难与特征降维(也叫特征选择,去除不相关特征的过程)相对。这能够采用多种形式:主成分分析(PCA)、SelectKBest、使用模型中特征的重要性或使用深度神经网络进行自编码。可是,特征降维是另外一篇文章的不一样主题。到目前为止,咱们知道咱们可使用特征工具以最小的努力从许多表中构造大量的特征!

结论

与机器学习中的许多主题同样,使用特征工具进行特征工程自动化是一个基于简单想法的复杂概念。使用实体集、实体和关联的概念,特征工具能够执行深度特征合成操做来构造新的特征。深度特征合成能够依次叠加特征基元:「聚合」,它们在多张表间的一对多关联中起做用,以及「转换」,是应用于单张表中一或多列以从多张表中构造新的特征的函数。

在以后的文章中,我将介绍如何在现实世界的问题上使用这项技术,即在 Kaggle 上举办的房屋信用违约风险竞赛(www.kaggle.com/c/home-cred…)。请继续关注那则帖子,与此同时,阅读这则说明以开始竞赛(towardsdatascience.com/machine-lea…)! 我但愿大家可使用特征工程自动化做为数据科学工做中的辅助工具。咱们的模型与咱们提供的数据同样好,而且特征工程自动化可使特征构造的过程更高效。

有关特征工具更多的信息,包括高级用法,请查看在线文档(docs.featuretools.com/)。要了解在实践中如何使用特征工具,请阅读开源库的开发公司 Feature Labs 的工做(www.featurelabs.com/)。

原文连接:
https://towardsdatascience.com/automated-feature-engineering-in-python-99baf11cc219
相关文章
相关标签/搜索