技术介绍

自动化机器学习(一)超参数自动优化

自动化机器学习就是能够自动建立机器学习模型的方法,其主要包含三个方面:方面一,超参数优化;方面二,自动特征工程与机器学习算法自动选择;方面三,神经网络结构搜索。本文侧重于方面二,我们将使用TPOT完成自动特征工程与机器学习算法自动选择。

在机器学习中,模型本身的参数是可以通过训练数据来获取的,这些参数属于算法的普通参数,通过数据训练获得算法合适的参数,构建强大的模型本身就是机器学习的核心目标。但是机器学习算法本身还存在在超参数,超参数就是那些需要科学家手动设置的参数,如SVM的核函数,Lasso的alpha,决策树的最大深度与分支条件,随机森林的子采样率和决策树类型等等等等。如何对这些超参数进行自动优化,而非手动调节正是自动化机器学习的第一步。对于超参数的优化我们可以将其视作特殊的非凸函数来进行优化,不顾我们也可以更进一步从更高的层次了来审视机器学习。

正常的机器学习流程应该包括数据读取-数据处理-特征构建-特征选择-模型选择-超参数优化-(集成学习)等等部分,而且大部分情况下其中的多个部分都需要循环往替,不断更新,最终得到一个不错的机器学习流水线(或者说管道),而本文侧重的的就是这一点,本文的主要使用工具则是tpot。

TPOT是一种基于遗传算法优化机器学习管道(pipeline)的Python自动机器学习工具。简单来说,就是TPOT可以智能地探索数千个可能的pipeline,为数据集找到最好的pipeline,从而实现机器学习中最乏味的部分。而总的来说,TPOT可以自动地完成特征工作(特征选择,特征预处理,特征构建等),同时也可以进行模型的选择和参数的调优。

核心技术栈

  • tpot
  • xgboost
  • lughtgbm
  • scikit-learn

实现

数据

这里我们的数据集使用的是
该数据的下载可以前往http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv

该数据为UCI的红酒质量数据集,标签为分数(整数),因此既可可用于回归,也可用于分类。

AutoML算法并不像在数据集中拟合一个模型那样简单。他们正在考虑在具有多个预处理步骤(缺失值插补,缩放,PCA,特征选择等)的管道中使用多种机器学习算法(随机森林,线性模型,SVM等),所有模型的超参数和预处理步骤,以及在管道中集成或堆叠算法的多种方法。

因此,TPOT需要花费一些时间才能在较大的数据集上运行,但重要的是要弄清原因。使用默认的TPOT设置(100个世代,人口总数为100),TPOT将在完成之前评估10,000个管道配置。为了将这个数字放在上下文中,请考虑针对机器学习算法的10,000个超参数组合进行网格搜索,以及该网格搜索将花费多长时间。这是10,000个模型配置,需要进行10倍交叉验证才能进行评估,这意味着可以在一个网格搜索中对训练数据进行拟合并评估大约100,000个模型。即使对于像决策树这样的简单模型,这也是一个耗时的过程。

典型的TPOT运行将需要数小时至数天才能完成(除非这是一个很小的数据集),但是您始终可以在运行过程中中途中断运行,并查看迄今为止的最佳结果。TPOT还提供了一个warm_start参数,可让您从中断处重新开始TPOT运行。不过由于此处更重在演示,因此将不会运行过长的时间。

实现

类库加载与数据读取
from tpot import TPOTClassifier
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np

# NOTE: Make sure that the outcome column is labeled 'target' in the data file
tpot_data = pd.read_csv('/home/fonttian/Data/dataset/wine/wine.csv', dtype=np.float64)
labels = tpot_data['quality']
tpot_data = tpot_data.drop('quality', axis=1)

X_train, X_test, y_train, y_test = \
            train_test_split(tpot_data.values, labels.values, train_size=0.75, test_size=0.25,random_state=42)
/home/fonttian/anaconda3/envs/keras/lib/python3.8/site-packages/tpot/builtins/__init__.py:36: UserWarning: Warning: optional dependency `torch` is not available. - skipping import of NN models.
  warnings.warn("Warning: optional dependency `torch` is not available. - skipping import of NN models.")

在我们执行玩代码之后会出现一个提示,大体意思为由于没有安装PyTorch因此将不会调用神经网络模块进行自动化机器学习。

而在代码的最后我们使用了skleran中的数据分割算法,将数据集分给为3:1两份,前者用于训练,后者用于测试。

参数

TPOT接口设计时目标为与scikit-learn尽可能相似。TPOT可以像任何常规Python模块一样导入。要使用TPOT,只需要下列简单的代码即可。
而由于tpot是基于遗传算法编写的自动化机器学习项目,因此我们在创建tpot模型时,需要传入的参数全部都是遗传算法所需的参数。下列参数的具体解释如下:

  • generations: int, optional (default=100),运行管道优化过程的迭代次数。一定是正数。
  • population_size: int, optional (default=100),在每一代遗传中保留的个体数。一定是正数。
  • cv: 交叉验证的折数。一定是正数。
  • random_state: 随机数种子,用于控制随机数
  • verbosity: 打印的详细程度,0,完全不打印,1,少量,2,更多信息以及进度条,3,所有信息以及进度条

除此之外还有几个比较重要的参数,如warm_start,是否调用之前fit的结果,继续进行训练。以及其他几个常用参数:

  • offspring_size:默认一百,每次遗传中产生的后代数量。一定是正数。
  • mutation_rate:变异率,默认0.9,一般不需要改动。
  • crossover_rate:交叉率,默认0.1,一般不需要改动。
  • scoring:评价函数,内部使用
  • subsample: 训练过程中的采样比,默认为1,即百分之百。
  • n_jobs:使用线程数,,默认为1。-1表示使用尽可能多的内容,-2表示将使用出一个以外的所有CPU
  • max_time_mins:多少分钟优化管道,默认None。设置为None,则不进行时间限制。
  • max_eval_time_mins:多少分钟评估管道,默认5,也就是五分钟。
  • early_stop:早停,比较常见的参数,当多少个回合损失基本不变时,停止训练。
  • config_dict: Python dictionary, string, or None, optional (default=None),用于定制TPOT在优化过程中搜索的操作符和参数的配置字典。不过由于基本上都是直接用自带的,这个参数意义不大。如果需要使用可以参考该链接:https://epistasislab.github.io/tpot/using/#built-in-tpot-configurations
方法:

至于方法则更为简单,其只有四个方法可以调用:

  • fit(features, target, sample_weight=None, groups=None),在给定的训练数据上运行TPOT优化过程。
  • predict(features),使用优化的管道来预测测试集的目标值。
  • score(testing_features, testing_target),使用用户指定的评分函数在给定的测试数据上返回优化的管道的得分。
  • export(output_file_name),将优化后的最佳机器学习管道导出为Python代码。
pipeline_optimizer = TPOTClassifier(generations=5, population_size=20, cv=5, random_state=42, verbosity=2)

pipeline_optimizer.fit(X_train, y_train)

print(pipeline_optimizer.score(X_test, y_test))
HBox(children=(FloatProgress(value=0.0, description='Optimization Progress', max=120.0, style=ProgressStyle(de…



Generation 1 - Current best internal CV score: 0.6430648535564853
Generation 2 - Current best internal CV score: 0.6430648535564853
Generation 3 - Current best internal CV score: 0.6430648535564853
Generation 4 - Current best internal CV score: 0.6822838214783822
Generation 5 - Current best internal CV score: 0.6822838214783822
Best pipeline: ExtraTreesClassifier(RandomForestClassifier(ExtraTreesClassifier(PCA(input_matrix, iterated_power=5, svd_solver=randomized), bootstrap=False, criterion=entropy, max_features=0.7500000000000001, min_samples_leaf=4, min_samples_split=16, n_estimators=100), bootstrap=True, criterion=gini, max_features=0.15000000000000002, min_samples_leaf=7, min_samples_split=15, n_estimators=100), bootstrap=False, criterion=entropy, max_features=0.9500000000000001, min_samples_leaf=9, min_samples_split=15, n_estimators=100)
0.665

从上面的执行结果我们可以看到,tpot确实在训练过程中展示出来对应的结果,以及有一个进度条。但是也正如其文档所说,当时间较短时,tpot得到的结果往往会很差,连续训练几个小时甚至几天都是非常正常的情况。同时要注意的是,虽然训练之后会默认打印最佳参数,按时很显然这并不是能够接受的最好方式。因此我们还是使用export方法将优化后的最佳结果直接输出为Python代码比较好。下面就是输出的结果:

# export code
pipeline_optimizer.export('tpot_exported_pipeline.py')
import numpy as np
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.ensemble import ExtraTreesClassifier, RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline, make_union
from tpot.builtins import StackingEstimator
from tpot.export_utils import set_param_recursive

# NOTE: Make sure that the outcome column is labeled 'target' in the data file
tpot_data = pd.read_csv('PATH/TO/DATA/FILE', sep='COLUMN_SEPARATOR', dtype=np.float64)
features = tpot_data.drop('target', axis=1)
training_features, testing_features, training_target, testing_target = \
            train_test_split(features, tpot_data['target'], random_state=42)

# Average CV score on the training set was: 0.6822838214783822
exported_pipeline = make_pipeline(
    PCA(iterated_power=5, svd_solver="randomized"),
    StackingEstimator(estimator=ExtraTreesClassifier(bootstrap=False, criterion="entropy", max_features=0.7500000000000001, min_samples_leaf=4, min_samples_split=16, n_estimators=100)),
    StackingEstimator(estimator=RandomForestClassifier(bootstrap=True, criterion="gini", max_features=0.15000000000000002, min_samples_leaf=7, min_samples_split=15, n_estimators=100)),
    ExtraTreesClassifier(bootstrap=False, criterion="entropy", max_features=0.9500000000000001, min_samples_leaf=9, min_samples_split=15, n_estimators=100)
)
# Fix random state for all the steps in exported pipeline
set_param_recursive(exported_pipeline.steps, 'random_state', 42)

exported_pipeline.fit(training_features, training_target)
results = exported_pipeline.predict(testing_features)

除此之外还有一个比较常用的算法为回归器:TPOTRegressor,参数和效果与分类器的差不多,具体内容就不再赘述。

总结

tpot作为一种完全的自动化机器学习工具,其能够从特征构建,特征处理,模型选择,超参数优化等多个方面进行数据的优化,并最终给予我们一个最佳的机器学习管道,但是同样其存在一定的问题,那就是效果比较差,必须训练几个小时甚至几天的时间,其才能对可鞥的组合进行较好的探究,最终获得一个较好的结果。对于专业人士而言,这时间确实有些过长了。但是极低的操作性又意味着其使用的容易,同时如果时间充裕,tpot又确实能够做出比一般工程师更好地结果。所以其必然还是存在很大的使用空间的。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐