1.说明

此文为翻译转载
- 项目文献
- 原文代码

2.正文

机器学习模型只能从我们给定的数据中学习,所以构造一个和任务相关的特征是至关重要的,参见优质论文《A Few Useful Things to Know about Machine Learning》。

然而,人工特性工程是一项冗长乏味的任务,并且受到人类想象力的限制——我们可以思考创建的特性只有这么多,而且随着时间的推移,创建新特性需要大量的时间。理想情况下,应该有一个客观的方法来创建一系列不同的候选新特性,然后我们可以将这些特性用于机器学习任务。这个过程的目的不是替换数据科学家,而是使她的工作更容易,并允许她使用自动工作流补充领域知识。
本文,我们将介绍使用Featuretools(一个开源的Python库)实现自动创建特性(数据位于结构化表中)。

数据

clients: 客户的基本信息。
loans: 客户历史贷款记录。
payments:客户历史还款记录。

import pandas as pd
import numpy as npfrom datetime import datetime
import randomrand_dates = []for _ in range(1000):year = random.choice(range(2000, 2015))month = random.choice(range(1, 13))day = random.choice(range(1, 29))rdate = datetime(year, month, day)rand_dates.append(rdate)clients = pd.DataFrame(columns = ['client_id', 'joined', 'income', 'credit_score'])
for _ in range(25):clients = clients.append(pd.DataFrame({'client_id': np.random.randint(25000, 50000, size = 1)[0], 'joined': random.choice(rand_dates),'income': np.random.randint(30500, 240000, size = 1)[0], 'credit_score': np.random.randint(500, 850, size = 1)[0]},index = [0]), ignore_index = True)clients.head()loans = pd.DataFrame(columns = ['client_id', 'loan_type', 'loan_amount', 'repaid','loan_id', 'loan_start', 'loan_end', 'rate'])for client in clients['client_id'].unique():for _ in range(20):time_created = pd.datetime(np.random.randint(2000, 2015, size = 1)[0],np.random.randint(1, 13, size = 1)[0],np.random.randint(1, 30, size = 1)[0])time_ended = time_created + pd.Timedelta(days = np.random.randint(500, 1000, size = 1)[0])loans = loans.append(pd.DataFrame({'client_id': client, 'loan_type': random.choice(['cash', 'credit', 'home', 'other']),'loan_amount': np.random.randint(500, 15000, size = 1)[0],'repaid': random.choice([0, 1]), 'loan_id': np.random.randint(10000, 12000, size = 1)[0],'loan_start': time_created,'loan_end': time_ended,'rate': round(abs(4 * np.random.randn(1)[0]), 2)}, index = [0]), ignore_index = True)payments = pd.DataFrame(columns = ['loan_id', 'payment_amount', 'payment_date', 'missed'])for _, row in loans.iterrows():time_created = row['loan_start']payment_date = time_created + pd.Timedelta(days = 30)loan_amount = row['loan_amount']loan_id = row['loan_id']payment_id = np.random.randint(10000, 12000, size = 1)[0]for _ in range(np.random.randint(5, 10, size = 1)[0]):payment_id += 1payment_date += pd.Timedelta(days = np.random.randint(10, 50, size = 1)[0])payments = payments.append(pd.DataFrame({'loan_id': loan_id, 'payment_amount': np.random.randint(int(loan_amount / 10), int(loan_amount / 5), size = 1)[0],'payment_date': payment_date, 'missed': random.choice([0, 1])}, index = [0]), ignore_index = True)clients = clients.drop_duplicates(subset = 'client_id')
loans = loans.drop_duplicates(subset = 'loan_id')clients.to_csv('clients.csv', index = False)
loans.to_csv('loans.csv', index = False)
payments.to_csv('payments.csv', index = False)   
数据导入
import pandas as pd
import numpy as np
import featuretools as ft# Read in the data
clients = pd.read_csv('data/clients.csv', parse_dates = ['joined'])
loans = pd.read_csv('data/loans.csv', parse_dates = ['loan_start', 'loan_end'])
payments = pd.read_csv('data/payments.csv', parse_dates = ['payment_date'])
clinets.head(5)
index client_id joined income credit_score
0 46109 2002-04-16 172677 527
1 49545 2007-11-14 104564 770
2 41480 2013-03-11 122607 585
3 46180 2001-11-06 43851 562
4 25707 2006-10-06 211422 621
loans.head(5)
index client_id loan_type loan_amount repaid loan_id loan_start loan_end rate
0 46109 home 13672 0 10243 2002-04-16 2003-12-20 2.15
1 46109 credit 9794 0 10984 2003-10-21 2005-07-17 1.25
2 46109 home 12734 1 10990 2006-02-01 2007-07-05 0.68
3 46109 cash 12518 1 10596 2010-12-08 2013-05-05 1.24
4 46109 credit 14049 1 11415 2010-07-07 2012-05-21 3.13
payments.sample(5)
index loan_id payment_amount payment_date missed
258 10425 1448 2002-03-16 1
2104 10116 937 2001-10-06 1
2280 11546 1149 2003-02-03 0
2123 10198 1709 2012-11-07 0
2703 11481 1660 2009-04-24 1

使用pandas对loans进行变量衍生,然后和clients合并

# Groupby client id and calculate mean, max, min previous loan size
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
clients.merge(stats, left_on = 'client_id', right_index=True, how = 'left').head(5)
index client_id joined income credit_score mean_loan_amount max_loan_amount min_loan_amount
0 46109 2002-04-16 172677 527 8951.60 14049 559
1 49545 2007-11-14 104564 770 10289.30 14971 3851
2 41480 2013-03-11 122607 585 7894.85 14399 811
3 46180 2001-11-06 43851 562 7700.85 14081 1607
4 25707 2006-10-06 211422 621 7963.95 13913 1212

同样,我们可以对payments进行做变量衍生,然后合并到clients中。
很明显,这个手工特性工程的过程会因为有许多列和多个表而变得非常乏味,我当然不希望必须手工完成这个过程!幸运的是,featuretools可以自动执行整个过程,并且会创建比我们想象的更多的特性。

Featuretools

Featuretools要理解的第一部分是entity。entity可以是一个表:DataFrame。将多个entity合并到一个名为EntitySet的单一对象中,这是一个由许多单独的实体以及它们之间的关系组成的大型数据结构。

EntitySet
#创建一个空的实体集
es = ft.EntitySet(id="clients")

entity

一个entity就是一个表,如:dataframe。
每个entity必须有一个唯一标识列,称为索引。对于clients,索引就是client_id,因为每个client_id只在数据中出现一次。
在贷款dataframe中,client_id不是索引,因为每个id可能出现不止一次,它索引是loan_id。
在featuretools中创建entity时,我们必须标识dataframe的哪个列是索引。如果数据没有唯一的索引,我们可以通过传入make_index = True并为索引指定名称来创建索引。如果数据也有唯一的标识时间索引,我们可以将其作为time_index参数传入。
Featuretools将自动推断数据中列的变量类型(数字、类别、日期时间),但我们也可以传入特定的数据类型以覆盖此行为。举个例子,尽管payments中的 repaid 被表示为一个整数,但是我们可以告诉featuretools这是一个类别特性,因为它只能接受两个离散值。这是使用一个整数实现的,变量作为键,特征类型作为值。
在下面的代码中,我们创建了三个entity并将它们添加到EntitySet中。语法相对简单,只有几条注释:对于payments,我们需要建立一个索引,对于loans,我们指定repaid是一个类别特性,对于payments,我们指定missed是一个类别特性。

#clients指定索引为client_id,时间索引为joined
es = es.entity_from_dataframe(entity_id = 'clients', dataframe = clients, index = 'client_id', time_index = 'joined')#payments建议一个索引payment_id,指定missed是一个类别特性,时间索引为payment_date。
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')
#loans指定索引为loan_id,repaid是一个类别特性,时间索引为loan_start
es = es.entity_from_dataframe(entity_id = 'loans', dataframe = loans, variable_types = {'repaid': ft.variable_types.Categorical},index = 'loan_id', time_index = 'loan_start')

Relationships

在定义了EntitySet中的entity之后,我们现在需要告诉featuretools,entity是如何关联的。
最直观的理解关系的方法是使用父类对子类的类比:父类对子类的关系是一对多关系,因为对于每个父类,可能有多个子类。因此,clients是loans的父类,因为clients中每个client_id只有一行,但每个client在loans可能有多个贷款。同样,loans是payments的父类,因为每个贷款都有多笔支付。

这些关系允许我们使用aggregation(聚合)对数据池进行分组,然后创建新的特性。例如,我们可以将与一个客户相关的所有贷款进行分组,并找到平均贷款金额。

要定义关系,我们需要指定父变量和子变量。这个变量将两个实体连接在一起。在我们的示例中,clients和loans由client_id连接在一起。
我们通过用featuretools语言编写关系,来指定父类和子类。在创建关系之后,我们将它添加到EntitySet中。

#前是父类,后为子类
es=es.add_relationship(ft.Relationship(es["clients"]["client_id"],es["loans"]["client_id"]))r_payments = ft.Relationship(es['loans']['loan_id'],
                                      es['payments']['loan_id'])es = es.add_relationship(r_payments)

现在我们在EntitySet有了entity以及Relationships。现在,我们可以开始从所有表中创建新特性。

Feature Primitives

特征基元:对数据进行操作来创建特性。这些非常简单的计算,也可以叠加在一起创建出复杂的特性。
特征基元分为两类:
Aggregation(聚合):对每个父类的子类数据进行分组,然后计算统计数据(如平均值、最小值、最大值或标准差)的函数。
如:计算每个客户的最大贷款额。
Transformation(转换):应用于单个表中的一个或多个列的操作。例如,从日期中提取日期,或者在一个表中找出两列之间的差异。

我们可以查看Feature Primitives:

primitives = ft.list_primitives()
pd.options.display.max_colwidth = 100
primitives[primitives['type'] == 'aggregation'].head(10)
index name type description
0 mode aggregation Finds the most common element in a categorical feature.
1 any aggregation Test if any value is ‘True’.
2 last aggregation Returns the last value.
3 all aggregation Test if all values are ‘True’.
4 median aggregation Finds the median value of any feature with well-ordered values.
5 min aggregation Finds the minimum non-null value of a numeric feature.
6 avg_time_between aggregation Computes the average time between consecutive events.
7 max aggregation Finds the maximum non-null value of a numeric feature.
8 n_most_common aggregation Finds the N most common elements in a categorical feature.
9 percent_true aggregation Finds the percent of ‘True’ values in a boolean feature.

如果Feature Primitives中没有合适的工具,我们也可以自己创建。

在下面的示例中,使用创建的EntitySet,clients作为目标entity,因为我们希望用指定的一些聚合和转换工具为每个客户创建新的特性。

# Create new features using specified primitives
features, feature_names = ft.dfs(entityset = es, target_entity = 'clients', agg_primitives = ['mean', 'max', 'percent_true', 'last'],trans_primitives = ['years', 'month', 'subtract', 'divide'])
Deep Feature Synthesis

当堆叠Primitives以获得深层特性时,使用功能工具的主要好处就出现了,特性的深度仅仅是创建特性所需的Primitives的数量。
因此,一个依赖于单个聚合的特性是一个深度为1的特性,一个叠加了两个Primitives的特性的深度为2,以此类推。

要关于深度特征合成的信息,请阅读Max Kanter等人的原始论文。

在手动指定Primitives的dataframe中,也可以看到特性深度的概念。例如,MEAN(loans.loan_amount)特性的深度为1,因为它是通过应用单个Primitives来实现的。表示客户平均贷款金额。

# Show a feature with a depth of 1
pd.DataFrame(features['MEAN(loans.loan_amount)'].head(10))

深度为2的特性。例如,LAST(loans.)(MEAN(payments.payment_amount))具有深度= 2,因为它是通过叠加两个实现Primitives的,首先是aggregation,然后是Transformation。这个特性表示每个客户最近一次贷款的平均支付金额。

# Show a feature with a depth of 2
pd.DataFrame(features['LAST(loans.MEAN(payments.payment_amount))'].head(10))

我们可以通过叠加更多的Primitives来创建任意深度的特性。然而,当我使用特性工具时,我从来没有超过2的深度!
超过2层之后,要理解这些特性就变得非常复杂了。

Automated Deep Feature Synthesis

除了手动指定聚合和转换之外,还可以自动生成许多新特性。我们通过使用相同的ft.dfs函数调用来实现这一点,但是没有传递任何Primitives。我们只设置max_depth参数,featuretools将会自动地尝试多个Primitives组合到有序的深度。

当在大型数据集上运行时,这个过程可能需要相当长的时间,但是对于我们的示例数据,它将相对快速。
对于这个调用,我们只需要指定entityset、target_entity(clients)和max_depth。

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

3.总结

在这个笔记本中,我们看到了如何将featuretools应用到一个示例数据集。这是一种强大的方法,它允许我们克服人类对时间和想象力的限制,从多个数据表中创建许多新特性。特性工具基于深度特性合成的思想,将多个简单的Primitives(聚合和转换)叠加起来创建新的特性。featuretools允许我们将跨多个表的信息合并到一个单独的dataframe中,然后我们可以使用这个名称进行机器学习模型训练。创建所有这些特性后的下一步是确定哪些特性是重要的。

Feature Tools:自动特征工程(翻译)相关推荐

  1. 手把手教你用Python实现自动特征工程

    任何参与过机器学习比赛的人,都能深深体会特征工程在构建机器学习模型中的重要性,它决定了你在比赛排行榜中的位置. 特征工程具有强大的潜力,但是手动操作是个缓慢且艰巨的过程.Prateek Joshi,是 ...

  2. Auto ML自动特征工程

    Auto ML自动特征工程 特征工程是在做机器学习训练的过程中必不可少的环节,特征工程就是找出对模型结果有益的特征交叉关系,通常特征工程需要耗费算法工程师大量的精力去尝试.针对这样的场景,PAI推出智 ...

  3. 手动特征工程已经OUT了!自动特征工程才是改进机器学习的方式

    作者 | William Koehrsen 译者 | linstancy 编辑 | Jane 出品 | AI科技大本营 [导读]近年来,我们在自动模型选择和超参数调优方面取得了进展,但机器学习流程中最 ...

  4. 基于Python的自动特征工程——教你如何自动创建机器学习特征

    作者 | William Koehrsen 译者 | 王天宇 编辑 | Jane 出品 | AI科技大本营 [导读]如今机器学习正在从人工设计模型更多地转移到自动优化工作流中,如 H20.TPOT 和 ...

  5. ML之FE:基于BigMartSales数据集利用Featuretools工具实现自动特征工程之详细攻略daiding

    ML之FE:基于BigMartSales数据集利用Featuretools工具实现自动特征工程之详细攻略daiding 目录 基于BigMartSales数据集利用Featuretools工具实现自动 ...

  6. python特征工程插件_手把手教你用Python实现自动特征工程

    任何参与过机器学习比赛的人,都能深深体会特征工程在构建机器学习模型中的重要性,它决定了你在比赛排行榜中的位置. 特征工程具有强大的潜力,但是手动操作是个缓慢且艰巨的过程.Prateek Joshi,是 ...

  7. 自动特征工程在推荐系统中的研究

    在先荐推荐系统学院 | 第1期的分享中,第四范式资深研究员罗远飞针对推荐系统中的高维稀疏数据,介绍了如何在指数级搜索空间中,高效地自动生成特征和选择算法:以及如何结合大规模分布式机器学习系统,在显著降 ...

  8. python 机器学习库 —— featuretools(自动特征工程)

    文档:https://docs.featuretools.com/#minute-quick-start 所谓自动特征工程,即是将人工特征工程的过程自动化.以 featuretools 为代表的自动特 ...

  9. 特征工程与自动特征工程

    目录 1. 什么是特征工程 2. 什么是自动特征工程 2.1 自动方法有哪些 3. 文献说明 4.参考文献 1. 什么是特征工程 特征工程,是指用一系列工程化的方式从原始数据中提取出更好的数据特征,以 ...

最新文章

  1. react-antd项目中重新npm  install  导致自动升级antd版本,引发的样式问题
  2. backboneJs 导图
  3. 教你做一个优秀的项目经理
  4. VideoLAN、VLC 和 FFmpeg联合开发AV1 解码器 Dav1d
  5. 2021年了,`IEnumerator`、`IEnumerable`接口还傻傻分不清楚?
  6. vue中使用cookies和crypto-js实现记住密码和加密
  7. 损失函数一直不变_MIT 18.03 微分方程笔记 3.4 狄拉克δ函数
  8. mysql输出重定向_将MySQL输出内容写入(重定向到)文件
  9. VMware Horizon View 的内部版本号和版本 (2143853)
  10. 笔记:AIX系统/var/adm/wtmp大文件处理
  11. Mysql中key与index区别
  12. python 元编程有多强_马克的Python学习笔记#元编程 3
  13. Qt_QTableWidget用法 添加、删除、添加控件、获取控件在表格中位置
  14. android最佳投屏,Android投屏神器(scrcpy使用教程)
  15. 查看Andriod内置浏览器WebView版本
  16. 【开源访谈】ECharts 作者 林峰 访谈实录
  17. SVN打标签方法及在此过程中的问题处理
  18. 使用拦截器防止表单重复提交
  19. python 坐标轴单位标注_matlab坐标轴如何带单位标注?
  20. 怎样将腾讯视频下载到的电影传入手机_腾讯视频怎么缓存视频

热门文章

  1. ESP32-BMP180气压、气温传感器
  2. 上海某大型企业因盗版Catia被罚千万
  3. 财管毕业论文哪些题目比较好写?
  4. ISC 2022“护航数字山河·数据安全协同创新”高峰会:共议数据安全新方案
  5. 第四十天 阿乐在其中—Android小游戏的飞机(四)加入敌人
  6. 漫威java_10年漫威,到底有多少角色。
  7. 人体神经系统分布图图片,神经系统分布图片高清
  8. Rescue-Prime hash STARK
  9. 计算机运行加减乘除哪个最慢,计算机算加减乘除的时间对比
  10. doolittle分解法解线性方程