我的觉得,机器学习是朝着更高的易用性、更低的技术门槛、更敏捷的开发成本的方向去发展,且AutoML或者AutoDL的发展无疑是最好的证实。所以花费一些时间学习了解了AutoML领域的一些知识,并对AutoML中的技术方案进行概括整理。html
众所周知,一个完整的机器学习项目可归纳为以下四个步骤。python
其中,特征工程(提取)每每是决定模型性能的最关键一步。而每每机器学习中最耗时的部分也正是特性工程和超参数调优。所以,许多模型因为时间限制而过早地从实验阶段转移到生产阶段从而致使并非最优的。git
自动化机器学习(AutoML)框架旨在减小算法工程师们的负担,以便于他们能够在特征工程和超参数调优上花更少的时间,而在模型设计上花更多的时间进行尝试。github
本文将对AutoML中的自动化特征工程模块的现状展开介绍,如下是目前主流的有关AUTOML的开源包。算法
自动化特征工程旨在经过从数据集中自动建立候选特征,且从中选择若干最佳特征进行训练的一种方式。数据库
Featuretools使用一种称为深度特征合成(Deep Feature Synthesis,DFS)的算法,该算法遍历经过关系数据库的模式描述的关系路径。当DFS遍历这些路径时,它经过应用于数据的操做(包括和、平均值和计数)生成综合特征。例如,对来自给定字段client_id的事务列表应用sum操做,并将这些事务聚合到一个列中。尽管这是一个深度操做,但该算法能够遍历更深层的特征。Featuretools最大的优势是其可靠性和处理信息泄漏的能力,同时能够用来对时间序列数据进行处理。框架
例子:dom
假设有三张表,分别为clients、loans、payments。机器学习
clients :有关信用合做社客户的基本信息表。每一个客户端在此数据框中只有一行。ide
loans:向客户提供的贷款表。每笔贷款在此数据框中只有本身的行,但客户可能有多笔贷款。
payments:贷款偿还表。每笔付款只有一行,但每笔贷款都有多笔付款。
以每一个client_id为对象构造特征:
传统的特征工程方案是利用Pandas对所需特征作处理,例以下表中的获取月份、收入值的对数。
同时,也能够经过与loans表关联获取新的特征(每一个client平均贷款额度、最大贷款额度等)。
而Featuretools经过基于一种称为“ 深度特征合成 ”的方法,即经过堆叠多个特征来完成特征工程。
深度特征合成堆叠多个转换和聚合操做(在特征工具的词汇中称为特征基元),以经过分布在许多表中的数据建立特征。
Featuretools有两个主要概念:
首先,须要建立一个存放全部数据表的空实体集对象:
import featuretools as ft es = ft.EntitySet(id='clients')
如今须要添加实体:每一个实体都必须有一个索引,索引是由实体中具备惟一元素值的列构成。也就是说,索引中的每一个值必须只出如今表中一次。
es = es.entity_from_dataframe(entity_id='clients', dataframe=clients, index='client_id', time_index='joined') es = es.entity_from_dataframe(entity_id='loans', dataframe=loans, index='loans_id', time_index='joined')
而对于没有惟一索引的表:须要传入参数make_index = True并指定索引的名称。
此外,虽然featuretools会自动推断实体中每一个列的数据类型,但仍能够经过将列类型的字典传递给参数variable_types来从新定义数据类型。例如对“missed”字段咱们定义为类别型变量。
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')
在执行聚合计算时,要在featuretools中指定表之间的关系时,只需指定将两个表关联在一块儿的特征字段。clients和loans表经过client_id字段关联,loans和payments经过loan_id字段关联。
建立表之间关系并将其添加到entityset的代码以下所示:
# 'clients'表与loans表关联 r_client_previous = ft.Relationship(es['clients']['client_id'], es['loans']['client_id']) # 将关系添加到实体集 es = es.add_relationship(r_client_previous) # loans表与payments表关联 r_payments = ft.Relationship(es['loans']['loan_id'], es['payments']['loan_id']) # 将关系添加到实体集 es = es.add_relationship(r_payments)
在添加实体和形式化关系以后,entityset就完成了。
须要注意,featuretools 是经过如下两种操做进行特征构造:
在 featuretools 中,可使用这些原语自行建立新特性,也能够将多个原语叠加在一块儿。下面是featuretools中的一些功能原语列表:
此外,咱们也能够定义自定义原语,详见: https://docs.featuretools.com/guides/advanced_custom_primitives.html。
接下来是进行特征构造,这也是自动化特征工程中最重要的一步:
features, feature_names = ft.dfs(entityset=es, target_entity='clients', agg_primitives=['mean', 'max', 'percent_true', 'last'], trans_primitives=['years', 'month', 'subtract', 'divide'])
固然,也可让 featuretools 自动为咱们选择特征:
features, feature_names = ft.dfs(entityset=es, target_entity='clients', max_depth=2)
Boruta主要是用来进行特征选择。因此严格意义上,Boruta并非咱们所须要的自动化特征工程包。
Boruta-py是brouta特征约简策略的一种实现,在该策略中,问题以一种彻底相关的方式构建,算法保留对模型有显著贡献的全部特征。这与许多特征约简算法所应用的最小最优特征集相反。boruta方法经过建立由目标特征的随机重排序值组成的合成特征来肯定特征的重要性,而后在原始特征集的基础上训练一个简单的基于树的分类器,在这个分类器中,目标特征被合成特征所替代。全部特性的性能差别用于计算相对重要性。
Boruta函数经过循环的方式评价各变量的重要性,在每一轮迭代中,对原始变量和影子变量进行重要性比较。若是原始变量的重要性显著高于影子变量的重要性,则认为该原始变量是重要的;若是原始变量的重要性明显低于影子变量的重要性,则认为该原始变量是不重要的。其中,原始变量就是咱们输入的要进行特征选择的变量;影子变量就是根据原始变量生成的变量
生成规则是:
使用python来实现影子特征,相似于:
# 从训练数据集获取特征 z = train_df[f].values # Shuffle np.random.shuffle(z) # 影子特征 train_df[f + "shadow"] = z
下面是Boruta算法运行的步骤:
tsfresh是基于可伸缩假设检验的时间序列特征提取工具。该包包含多种特征提取方法和鲁棒特征选择算法。
tsfresh能够自动地从时间序列中提取100多个特征。这些特征描述了时间序列的基本特征,如峰值数量、平均值或最大值,或更复杂的特征,如时间反转对称性统计量等。
这组特征能够用来在时间序列上构建统计或机器学习模型,例如在回归或分类任务中使用。
时间序列一般包含噪声、冗余或无关信息。所以,大部分提取出来的特征对当前的机器学习任务没有用处。为了不提取不相关的特性,tsfresh包有一个内置的过滤过程。这个过滤过程评估每一个特征对于手头的回归或分类任务的解释能力和重要性。它创建在完善的假设检验理论的基础上,采用了多种检验方法。
须要注意的是,在使用tsfresh提取特征时,须要提早把结构进行转换,通常上需转换为(None,2)的结构,例以下图所示:
例子:
import matplotlib.pylab as plt from tsfresh import extract_features, select_features from tsfresh.utilities.dataframe_functions import impute from tsfresh.feature_extraction import ComprehensiveFCParameters from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report import pandas as pd import numpy as np if __name__ == '__main__': N = 500 df = pd.read_csv('UCI HAR Dataset/train/Inertial Signals/body_acc_x_train.txt', delim_whitespace=True, header=None) y = pd.read_csv('UCI HAR Dataset/train/y_train.txt', delim_whitespace=True, header=None, squeeze=True)[:N] # plt.title('accelerometer reading') # plt.plot(df.ix[0, :]) # plt.show() # extraction_settings = ComprehensiveFCParameters() master_df = pd.DataFrame({'feature': df[:N].values.flatten(), 'id': np.arange(N).repeat(df.shape[1])}) # 时间序列特征工程 X = extract_features(timeseries_container=master_df, n_jobs=0, column_id='id', impute_function=impute, default_fc_parameters=extraction_settings) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) cl = DecisionTreeClassifier() cl.fit(X_train, y_train) print(classification_report(y_test, cl.predict(X_test))) # 未进行时间序列特征工程 X_1 = df.ix[:N - 1, :] X_train, X_test, y_train, y_test = train_test_split(X_1, y, test_size=.2) cl = DecisionTreeClassifier() cl.fit(X_train, y_train) print(classification_report(y_test, cl.predict(X_test)))
此外,对于进行时间序列特征工程后的数据集进行特征选择,进一步提升模型指标。
这里,能够利用tsfresh.select_features方法进行特征选择,然而因为其仅适用于二进制分类或回归任务,因此对于6个标签的多分类,咱们将多分类问题转换为6个二元分类问题,故对于每一种分类,均可以经过二分类进行特征选择:
relevant_features = set() for label in y.unique(): y_train_binary = y_train == label X_train_filtered = select_features(X_train, y_train_binary) print("Number of relevant features for class {}: {}/{}".format(label, X_train_filtered.shape[1], X_train.shape[1])) relevant_features = relevant_features.union(set(X_train_filtered.columns)) X_train_filtered = X_train[list(relevant_features)] X_test_filtered = X_test[list(relevant_features)] cl = DecisionTreeClassifier() cl.fit(X_train_filtered, y_train) print(classification_report(y_test, cl.predict(X_test_filtered)))
注意:在Windows开发环境下,会抛出“The "freeze_support()" line can be omitted if the program is not going to be frozen to produce an executable.”多进程的错误,致使无限循环,解决方法是在代码执行时引入” if __name__ == '__main__’:“ 。可参考: https://github.com/blue-yonder/tsfresh/issues/185 。
如下是分别使用tsfresh进行特征工程、未进行特征工程以及使用tsfresh进行特征工程+特征选择后的模型效果:
自动化特征工程解决了特征构造的问题,但同时也产生了另外一个问题:在数据量必定的前提下,因为产生过多的特征,每每须要进行相应的特征选择以免模型性能的下降。事实上,要保证模型性能,其所需的数据量级须要随着特征的数量呈指数级增加。
本文完整代码位于:https://github.com/wangkangdegithub/AutoML 。