HyperGBM¶
DataCanvas¶
HyperGBM is an open source project created by DataCanvas .
内容:¶
概览¶
关于HyperGBM¶
HyperGBM是一款全Pipeline自动机器学习工具,可以端到端的完整覆盖从数据清洗、预处理、特征加工和筛选以及模型选择和超参数优化的全过程,是一个真正的结构化数据AutoML工具包。
大部分的自动机器学习工具主要解决的是算法的超参数优化问题,而HyperGBM是将从数据清洗到算法优化整个的过程放入同一个搜索空间中统一优化。这种端到端的优化过程更接近于SDP(Sequential Decision Process)场景,因此HyperGBM采用了强化学习、蒙特卡洛树搜索等算法并且结合一个meta-leaner来更加高效的解决全Pipeline优化的问题,并且取得了非常出色的效果。
正如名字中的含义,HyperGBM中的机器学习算法使用了目前最流行的几种GBM算法(更准确的说是梯度提升树模型),目前包括XGBoost、LightGBM、CatBoost和HistGridientBoosting。同时,HyperGBM也引入了Hypernets的CompeteExperiment在数据清洗、特征工程、模型融合等环节的很多高级特性。
HyperGBM中的优化算法和搜索空间表示技术以及CompeteExperiment由 Hypernets项目提供支撑。
功能特性¶
HyperGBM有3中运行模式,分别为:
单机模式:在一台服务器上运行,使用Pandas和Numpy数据结构
单机分布式:在一台服务器上运行,使用Dask数据结构,在运行HyperGBM之前需要创建运行在单机上的Dask集群
多机分布式:在多台服务器上运行,使用Dask数据结构,在运行HyperGBM之前需要创建能管理多台服务器资源的Dask集群
不同运行模式的功能特性支持稍有差异,HyperGBM的功能特性清单及各种的运行模式的支持情况如下表:
功能特性 |
单机模式 |
单机分布式 |
多机分布式 |
|
---|---|---|---|---|
数据清洗 |
特殊空值字符处理 |
√ |
√ |
√ |
自动识别类别列 |
√ |
√ |
√ |
|
列类型校正 |
√ |
√ |
√ |
|
常量列清理 |
√ |
√ |
√ |
|
重复列清理 |
√ |
√ |
√ |
|
删除标签列为空的样本 |
√ |
√ |
√ |
|
非法值替换 |
√ |
√ |
√ |
|
id列清理 |
√ |
√ |
√ |
|
数据集拆分 |
按比例拆分 |
√ |
√ |
√ |
对抗验证 |
√ |
√ |
√ |
|
特征工程 |
特征衍生 |
√ |
√ |
√ |
特征降维 |
√ |
√ |
√ |
|
数据预处理 |
SimpleImputer |
√ |
√ |
√ |
SafeOrdinalEncoder |
√ |
√ |
√ |
|
SafeOneHotEncoder |
√ |
√ |
√ |
|
TruncatedSVD |
√ |
√ |
√ |
|
StandardScaler |
√ |
√ |
√ |
|
MinMaxScaler |
√ |
√ |
√ |
|
MaxAbsScaler |
√ |
√ |
√ |
|
RobustScaler |
√ |
√ |
√ |
|
数据不平衡处理 |
ClassWeight |
√ |
√ |
√ |
降采样(Nearmiss,Tomekslinks,Random) |
√ |
|||
过采样(SMOTE,ADASYN,Random) |
√ |
|||
搜索算法 |
蒙特卡洛树算法 |
√ |
√ |
√ |
进化算法 |
√ |
√ |
√ |
|
随机搜索 |
√ |
√ |
√ |
|
历史回放 |
√ |
√ |
√ |
|
提前停止策略 |
最大用时间提前停止 |
√ |
√ |
√ |
n次搜索都不再提升,提前停止 |
√ |
√ |
√ |
|
expected_reward |
√ |
√ |
√ |
|
trail discriminator |
√ |
√ |
√ |
|
建模算法 |
XGBoost |
√ |
√ |
√ |
LightGBM |
√ |
√ |
√ |
|
CatBoost |
√ |
√ |
||
HistGridientBoosting |
√ |
|||
评估方法 |
交叉验证(Cross-Validation) |
√ |
√ |
√ |
Train-Validation-Holdout验证 |
√ |
√ |
√ |
|
高级特性 |
自动任务类型推断 |
√ |
√ |
√ |
共线性特征检测 |
√ |
√ |
√ |
|
数据漂移检测 |
√ |
√ |
√ |
|
特征筛选 |
√ |
√ |
√ |
|
特征筛选(二阶段) |
√ |
√ |
√ |
|
伪标签(二阶段) |
√ |
√ |
√ |
|
通过降采样进行预搜索 |
√ |
√ |
√ |
|
模型融合 |
√ |
√ |
√ |
安装HyperGBM¶
推荐使用pip
命令来安装HyperGBM;如果您有Docker环境,也可以在Docker容器中安装并运行HyperGBM。
使用pip¶
安装HyperGBM之前,您需要准备Python3.6
或以上版本的运行环境并保证 pip
命令可正常运行。 使用pip安装HyperGBM:
pip install hypergbm
可选的, 如果您希望在JupyterLab中使用HyperGBM, 可通过如下命令安装HyperGBM:
pip install hypergbm[notebook]
可选的, 如果您希望在特征衍生时支持中文字符中, 可通过如下命令安装HyperGBM:
pip install hypergbm[zhcn]
可选的, 如果您希望安装HyperGBM以及所有依赖包,则可通过如下形式安装:
pip install hypergbm[all]
使用Docker¶
HyperGBM支持在Docker容器中运行,您可在Dockerfile中通过 pip
安装HyperGBM,然后使用。
我们在Docker Hub中发布了一个参考镜像,可直接下载使用,该镜像中包括:
Python3.7
HyperGBM及其依赖包
JupyterLab
下载镜像:
docker pull datacanvas/hypergbm
运行镜像:
docker run -ti -e NotebookToken="your-token" -p 8888:8888 datacanvas/hypergbm
打开浏览器,访问http://<your-ip>:8888
,输入您设置的token即可开始使用。
快速开始¶
本章介绍HyperGBM主要功能,假设您已经知道机器学习的基本知识(加载数据、模型训练、预测、评估等),如果您还没安装请参照[安装文档](installation.md)来安装HyperGBM。 您可以通过Python和命令行工具来使用HyperGBM。
通过Python使用HyperGBM¶
HyperGBM基于Python开发,推荐利用Python工具 make_experiment 创建实验并进行训练得到模型。
通过 make_experiment 训练模型的基本步骤:
准备数据集(pandas 或 dask DataFrame)
通过工具 make_experiment 创建实验
执行实验 .run() 方法进行训练得到模型
利用模型进行数据预测或Python工具 pickle 存储模型
准备数据集¶
可以根据实际业务情况通过pandas或dask加载数据,得到用于模型训练的DataFrame。
以sklearn内置数据集 breast_cancer 为例,可如下处理得到数据集:
import pandas as pd
from sklearn import datasets
from sklearn.model_selection import train_test_split
X,y = datasets.load_breast_cancer(as_frame=True,return_X_y=True)
X_train,X_test,y_train,y_test = train_test_split(X,y,train_size=0.7,random_state=335)
train_data = pd.concat([X_train,y_train],axis=1)
其中 train_data 用于模型训练(包括目标列),X_test 和 y_test 用于模型评价。
创建实验并进行训练¶
假设希望最终模型有比较好的precision,为前面准备的训练数据集创建实验并开始训练模型如下:
from hypergbm import make_experiment
experiment = make_experiment(train_data, target='target', reward_metric='precision')
estimator = experiment.run()
其中 estimator 就是训练所得到的模型。
输出模型¶
推荐利用 pickle 存储HyperGBM模型,如下:
import pickle
with open('model.pkl','wb') as f:
pickle.dump(estimator, f)
评价模型¶
可利用sklearn提供的工具进行模型评价,如下:
from sklearn.metrics import classification_report
y_pred=estimator.predict(X_test)
print(classification_report(y_test, y_pred, digits=5))
输出:
precision recall f1-score support
0 0.96429 0.93103 0.94737 58
1 0.96522 0.98230 0.97368 113
accuracy 0.96491 171
macro avg 0.96475 0.95667 0.96053 171
weighted avg 0.96490 0.96491 0.96476 171
更多信息¶
关于 make_experiment 的更多信息,您可以查看该工具的docstring,如:
print(make_experiment.__doc__)
如果您正在Notebook或IPython中使用HyperGBM, 可以通过如下方式获取 make_experiment 的更多信息:
make_experiment?
通过命令行使用HyperGBM¶
HyperGBM提供了命令行工具 hypergbm
进行模型训练、评估和预测数据,查看命令行帮助:
hypergm -h
usage: hypergbm [-h] [--log-level LOG_LEVEL] [-error] [-warn] [-info] [-debug]
[--verbose VERBOSE] [-v] [--enable-dask ENABLE_DASK] [-dask]
[--overload OVERLOAD]
{train,evaluate,predict} ...
hypergbm
提供三个子命令:train
、evaluate
、predict
,可通过hypergbm <子命令> -h
获取更多信息,如:
hypergbm train -h
usage: hypergbm train [-h] --train-data TRAIN_DATA [--eval-data EVAL_DATA]
[--test-data TEST_DATA]
[--train-test-split-strategy {None,adversarial_validation}]
[--target TARGET]
[--task {binary,multiclass,regression}]
[--max-trials MAX_TRIALS] [--reward-metric METRIC]
[--cv CV] [-cv] [-cv-] [--cv-num-folds NUM_FOLDS]
[--pos-label POS_LABEL]
...
准备数据¶
使用命令行工具训练模型时,训练数据必须是csv或parquet格式的文件,并以 .csv
或.parquet
结尾;输出模型是pickle格式,以.pkl
结尾。
以训练数据Bank Marketing为例子,可准备数据如下:
from hypernets.tabular.datasets import dsutils
from sklearn.model_selection import train_test_split
df = dsutils.load_bank().head(10000)
df_train, df_test = train_test_split(df, test_size=0.3, random_state=9527)
df_train.to_csv('bank_train.csv', index=None)
df_test.to_csv('bank_eval.csv', index=None)
df_test.pop('y')
df_test.to_csv('bank_to_pred.csv', index=None)
其中:
bank_train.csv:用于模型训练
bank_eval.csv:用于模型评价
bank_to_pred.csv:是没有目标列的数据,用于模拟待预测数据
模型训练¶
在准备好训练数据之后,可通过命令进行模型训练:
hypergbm train --train-data bank_train.csv --target y --model-file model.pkl
等待命令结束,可看到模型文件:model.pkl
ls -l model.pkl
rw-rw-r-- 1 xx xx 9154959 17:09 model.pkl
模型评价¶
在模型训练之后,可利用评价数据对所得到的模型进行评价:
hypergbm evaluate --model model.pkl --data bank_eval.csv --metric f1 recall auc
{'f1': 0.7993779160186626, 'recall': 0.7099447513812155, 'auc': 0.9705420982746849}
数据预测¶
在模型训练之后,可利用所得到的模型进行数据预测:
hypergbm predict --model model.pkl --data bank_to_pred.csv --output bank_output.csv
预测结果会保存到文件bank_output.csv
中。
如果您希望将预测数据的某一列数据(如”id”)与预测结果一起写到输出文件,则可通过参数 --with-data
指定,如:
hypergbm predict --model model.pkl --data bank_to_pred.csv --output bank_output.csv --with-data id
head bank_output.csv
id,y
1563,no
124,no
218,no
463,no
...
如果,您希望输出文件除了包含预测结果之外,还希望有预测数据的所有列,则可将参数 --with-data
设置为”*”,如:
hypergbm predict --model model.pkl --data bank_to_pred.csv --output bank_output.csv --with-data '*'
head bank_output.csv
id,age,job,marital,education,default,balance,housing,loan,contact,day,month,duration,campaign,pdays,previous,poutcome,y
1563,55,entrepreneur,married,secondary,no,204,no,no,cellular,14,jul,455,13,-1,0,unknown,no
124,51,management,single,tertiary,yes,-55,yes,no,cellular,11,may,281,2,266,6,failure,no
218,49,blue-collar,married,primary,no,305,yes,yes,telephone,10,jul,834,10,-1,0,unknown,no
463,35,blue-collar,divorced,secondary,no,3102,yes,no,cellular,20,nov,138,1,-1,0,unknown,no
2058,50,management,divorced,tertiary,no,201,yes,no,cellular,24,jul,248,1,-1,0,unknown,no
...
使用示例¶
基础应用¶
本节通过示例讲解如何使用实验进行模型训练,示例中使用数据集blood
,该数据集中的目标列Class
,数据如下:
Recency,Frequency,Monetary,Time,Class
2,50,12500,98,1
0,13,3250,28,1
1,16,4000,35,1
2,20,5000,45,1
1,24,6000,77,0
4,4,1000,4,0
...
本节示例从hypernets.tabular
中加载该数据集。
以缺省配置创建并运行实验¶
利用工具make_experiment
可快速创建一个可运行的实验对象,执行该实验对象的run
方法即可开始训练并得到模型。使用该工具时只有实验数据train_data
是必须的,其它都是可选项。数据的目标列如果不是y
的话,需要通过参数target
设置。
示例代码:
from hypergbm import make_experiment
from hypernets.tabular.datasets import dsutils
train_data = dsutils.load_blood()
experiment = make_experiment(train_data, target='Class')
estimator = experiment.run()
print(estimator)
输出:
Pipeline(steps=[('data_clean',
DataCleanStep(...),
('estimator',
GreedyEnsemble(...)])
可以看出,训练得到的是一个Pipeline,最终模型是由多个模型构成的融合模型。
如果您的训练数据是csv或parquet格式,而且数据文件的扩展名是“.csv”或“.parquet”的话,可以直接使用文件路径创建实验,make_experiment会自动将数据加载为DataFrame,如:
from hypergbm import make_experiment
train_data = '/path/to/mydata.csv'
experiment = make_experiment(train_data, target='my_target')
estimator = experiment.run()
print(estimator)
设置最大搜索次数(max_trials)¶
缺省情况下,make_experiment
所创建的实验最多搜索10种参数便会停止搜索。实际使用中,建议将最大搜索次数设置为30以上。
from hypergbm import make_experiment
train_data = ...
experiment = make_experiment(train_data, max_trials=50)
...
交叉验证¶
可通过参数cv
指定是否启用交叉验证。当cv
设置为False
时表示禁用交叉验证并使用经典的train_test_split方式进行模型训练;当cv
设置为True
(缺省)时表示开启交叉验证,折数可通过参数num_folds
设置(默认:3)。
启用交叉验证的示例代码:
from hypergbm import make_experiment
from hypernets.tabular.datasets import dsutils
train_data = dsutils.load_blood()
experiment = make_experiment(train_data, target='Class', cv=True, num_folds=5)
estimator = experiment.run()
print(estimator)
指定验证数据集(eval_data)¶
在禁用交叉验证时,模型训练除了需要训练数据集,还需要评估数据集,您可在make_experiment
时通过eval_data指定评估集,如:
from hypergbm import make_experiment
from hypernets.tabular.datasets import dsutils
from sklearn.model_selection import train_test_split
train_data = dsutils.load_blood()
train_data,eval_data=train_test_split(train_data,test_size=0.3)
experiment = make_experiment(train_data, target='Class', eval_data=eval_data, cv=False)
estimator = experiment.run()
print(estimator)
在禁用交叉验证时,如果您未指定eval_data
,实验对象将从train_data
中拆分部分数据作为评估集,拆分大小可通过eval_size
设置,如:
from hypergbm import make_experiment
from hypernets.tabular.datasets import dsutils
train_data = dsutils.load_blood()
experiment = make_experiment(train_data, target='Class', cv=False, eval_size=0.2)
estimator = experiment.run()
print(estimator)
指定模型的评价指标¶
使用make_experiment
创建实验时,分类任务默认的模型评价指标是accuracy
,回归任务默认的模型评价指标是rmse
,可通过参数reward_metric
指定,如:
from hypergbm import make_experiment
from hypernets.tabular.datasets import dsutils
train_data = dsutils.load_blood()
experiment = make_experiment(train_data, target='Class', reward_metric='auc')
estimator = experiment.run()
print(estimator)
设置搜索次数和早停(Early Stopping)策略¶
使用make_experiment
时,可通过参数early_stopping_round
、early_stopping_time_limit
、early_stopping_reward
设置实验的早停策略。
将搜索时间设置为最多3小时的示例代码:
from hypergbm import make_experiment
from hypernets.tabular.datasets import dsutils
train_data = dsutils.load_blood()
experiment = make_experiment(train_data, target='Class', max_trials=300, early_stopping_time_limit=3600 * 3)
estimator = experiment.run()
print(estimator)
指定搜索算法(Searcher)¶
HyperGBM通过Hypernets中的搜索算法进行参数搜索,包括:EvolutionSearcher(缺省)、MCTSSearcher、RandomSearch,在make_experiment
时可通过参数searcher
指定,可以指定搜索算法的类名(class)、搜索算法的名称(str)。
示例代码:
from hypergbm import make_experiment
from hypernets.tabular.datasets import dsutils
train_data = dsutils.load_blood()
experiment = make_experiment(train_data, target='Class', searcher='random')
estimator = experiment.run()
print(estimator)
您也可以自己创建searcher对象,然后用所创建的对象创建实验,如:
from hypergbm import make_experiment
from hypergbm.search_space import search_space_general
from hypernets.searchers import MCTSSearcher
from hypernets.tabular.datasets import dsutils
my_searcher = MCTSSearcher(lambda: search_space_general(n_estimators=100),
max_node_space=20,
optimize_direction='max')
train_data = dsutils.load_blood()
experiment = make_experiment(train_data, target='Class', searcher=my_searcher)
estimator = experiment.run()
print(estimator)
模型融合¶
为了获取较好的模型效果,make_experiment
创建实验时默认开启了模型融合的特性,并使用效果最好的20个模型进行融合,可通过参数ensemble_size
指定参与融合的模型的数量。当ensemble_size
设置为0
时则表示禁用模型融合。
调整参与融合的模型数量的示例代码:
train_data = ...
experiment = make_experiment(train_data, ensemble_size=10, ...)
调整日志级别¶
如果希望在训练过程中看到使用进度信息的话,可通过log_level指定日志级别,可以是str
或int
。关于日志级别的详细定义可参考python的logging
包。 另外,如果将verbose
设置为1
的话,可以得到更详细的信息。
将日志级别设置为INFO
的示例代码如下:
from hypergbm import make_experiment
from hypernets.tabular.datasets import dsutils
train_data = dsutils.load_blood()
experiment = make_experiment(train_data, target='Class', log_level='INFO', verbose=1)
estimator = experiment.run()
print(estimator)
输出:
14:24:33 I hypernets.tabular.u._common.py 30 - 2 class detected, {0, 1}, so inferred as a [binary classification] task
14:24:33 I hypergbm.experiment.py 699 - create experiment with ['data_clean', 'drift_detection', 'space_search', 'final_ensemble']
14:24:33 I hypergbm.experiment.py 1262 - make_experiment with train data:(748, 4), test data:None, eval data:None, target:Class
14:24:33 I hypergbm.experiment.py 716 - fit_transform data_clean
14:24:33 I hypergbm.experiment.py 716 - fit_transform drift_detection
14:24:33 I hypergbm.experiment.py 716 - fit_transform space_search
14:24:33 I hypernets.c.meta_learner.py 22 - Initialize Meta Learner: dataset_id:7123e0d8c8bbbac8797ed9e42352dc59
14:24:33 I hypernets.c.callbacks.py 192 -
Trial No:1
--------------------------------------------------------------
(0) estimator_options.hp_or: 0
(1) numeric_imputer_0.strategy: most_frequent
(2) numeric_scaler_optional_0.hp_opt: True
...
14:24:35 I hypergbm.experiment.py 716 - fit_transform final_ensemble
14:24:35 I hypergbm.experiment.py 737 - trained experiment pipeline: ['data_clean', 'estimator']
Pipeline(steps=[('data_clean',
DataCleanStep(...),
('estimator',
GreedyEnsemble(...)
高级应用¶
HyperGBM make_experiment 所创建的是 Hypernets 的 CompeteExeriment 实例,CompeteExeriment 具备很多建模的高级特性,本章逐一介绍。
数据清洗¶
CompeteExeriment 的第一步就是利用Hypernets的DataCleaner进行数据清洗,此步骤不可禁用,但可通过参数对DataCleaner的行为进行调整,包括:
nan_chars: value or list, (default None), 将哪些值字符替换为np.nan
correct_object_dtype: bool, (default True), 是否尝试修正数据类型
drop_constant_columns: bool, (default True), 是否删除常量列
drop_duplicated_columns: bool, (default False), 是否删除重复列
drop_idness_columns: bool, (default True), 是否删除id列
drop_label_nan_rows: bool, (default True), 是否删除目标列为np.nan的行
replace_inf_values: (default np.nan), 将np.inf替换为什么值
drop_columns: list, (default None), 强行删除哪些列
reserve_columns: list, (default None), 数据清洗时保留哪些列不变
reduce_mem_usage: bool, (default False), 是否尝试降低对内存的需求
int_convert_to: bool, (default ‘float’), 将int列转换为何种类型,None表示不转换
调用 make_expperiment 时,可通过参数 data_cleaner_args 对DataCleaner的配置进行调整。
假设,训练数据中用字符’\N’表示nan,希望在数据清洗阶段将其替换为np.nan,则可如下设置:
from hypergbm import make_experiment
train_data = ...
experiment = make_experiment(train_data, target='...',
data_cleaner_args={'nan_chars': r'\N'})
...
特征衍生¶
CompeteExeriment 中提供了特征衍生的能力, 在通过 make_experiment 创建实验时设置 feature_generation=True 即可,与之匹配的选项包括:
feature_generation_continuous_cols:list (default None)), 参与特征衍生的初始连续型特征,如果为None则依据训练数据的特征类型自行推断。
feature_generation_categories_cols:list (default None)), 参与特征衍生的初始类别型特征,需要明确指定,CompeteExeriment 不会自行推断参与特征衍生的初始类别型特征。
feature_generation_datetime_cols:list (default None), 参与特征衍生的初始日期型特征,如果为None则依据训练数据的特征类型自行推断。
feature_generation_latlong_cols:list (default None), 参与特征衍生的经纬度特征,如果为None则依据训练数据自行推断。说明:经纬度特征列的数据格式必须是 tuple(lat,long)。
feature_generation_text_cols:list (default None), 参与特征衍生的初始文本性特征,如果为None则依据训练数据自行推断。
feature_generation_trans_primitives:list (default None), 用于特征衍生的算子,如果为None则依据特征类型自行推断所采用的算子。
当feature_generation_trans_primitives=None时,CompeteExeriment 依据参与特征衍生的初始特征自行推断所采用的算子,针对不同类型的特征采取不同算子,如下:
continuous_cols: 无(需自行指定)。
categories_cols: cross_categorical。
datetime_cols: month、week、day、hour、minute、second、weekday、is_weekend。
latlong_cols: haversine、geohash
text_cols:tfidf
启用特征衍生的示例代码:
from hypergbm import make_experiment
train_data = ...
experiment = make_experiment(train_data,
feature_generation=True,
...)
...
关于特征衍生的更多信息请参考 [featuretools](https://docs.featuretools.com/).
共线性检测¶
有时训练数据中会出现一些相关度很高的特征,这些并没有提供太多的信息量,相反,数据集拥有更多的特征意味着更容易收到噪声的影响,更容易收到特征偏移的影响等等。
CompeteExeriment 中提供了删除发生共线性的特征的能力, 在通过 make_experiment 创建实验时设置 collinearity_detection=True 即可。
启用共线性检测的示例代码:
from hypergbm import make_experiment
train_data = ...
experiment = make_experiment(train_data, target='...', collinearity_detection=True)
...
漂移检测¶
数据漂移是建模过程中的一个主要挑战。当数据的分布随着时间在不断的发现变化时,模型的表现会越来越差,CompeteExeriment 中引入了对抗验证的方法专门处理数据漂移问题。这个方法会自动的检测是否发生漂移,并且找出发生漂移的特征并删除他们,以保证模型在真实数据上保持良好的状态。
为了开启飘逸检测,使用 make_experiment 创建实验时需要设置 drift_detection=True (缺省)并提供测试集 test_data 。
漂移检测相关的参数包括:
drift_detection_remove_shift_variable : bool, (default=True),是否首先检查每一列数据的稳定性。
drift_detection_variable_shift_threshold : float, (default=0.7),稳定性指标高于该阈值的列将被删除
drift_detection_threshold : float, (default=0.7),检测指标高于该阈值的列将被删除。
drift_detection_remove_size : float, (default=0.1),每一轮检测所删除的列占总列数的比例。
drift_detection_min_features : int, (default=10),至少保留多少列。
drift_detection_num_folds : int, (default=5),在漂移检测阶段训练模型时的cv折数。
需要注意的是,启用漂移检测时必须指定 test_data (不包含目标列), 示例代码:
from io import StringIO
import pandas as pd
from hypergbm import make_experiment
from hypernets.tabular.datasets import dsutils
test_data = """
Recency,Frequency,Monetary,Time
2,10,2500,64
4,5,1250,23
4,9,2250,46
4,5,1250,23
4,8,2000,40
2,12,3000,82
11,24,6000,64
2,7,1750,46
4,11,2750,61
1,7,1750,57
2,11,2750,79
2,3,750,16
4,5,1250,26
2,6,1500,41
"""
train_data = dsutils.load_blood()
test_df = pd.read_csv(StringIO(test_data))
experiment = make_experiment(train_data, test_data=test_df,
drift_detection=True,
...)
...
特征筛选¶
进行特征筛选也是建模过程中的一个重要环节,CompeteExeriment 通过训练一个常规模型对训练数据的特征重要性进行评估,进而筛选出最重要的特征参与到后续模型训练中。
在通过 make_experiment 创建实验时设置 feature_selection=True 可开启特征筛选,与之匹配的选项包括:
feature_selection_strategy:str, 筛选策略(default threshold), 可用的策略包括 threshold、number 、 quantile。
feature_selection_threshold:float, (default 0.1), 当策略为 threshold 时的筛选阈值,重要性高于该阈值的特征会被选择。
feature_selection_quantile:float, (default 0.2), 当策略为 quantile 时的筛选阈值,重要性分位高于该阈值的特征会被选择。
feature_selection_number:int or float, (default 0.8), 当策略为 number 时,筛选的特征数量。
启用特征筛选的示例代码:
from hypergbm import make_experiment
train_data=...
experiment = make_experiment(train_data,
feature_selection=True,
feature_selection_strategy='quantile',
feature_selection_quantile=0.3,
...)
降采样预搜索¶
通常,在进行模型参数优化搜索时是使用全部训练数据进行模型训练的,当数据量较大时使用全部训练数据进行模型训练会消耗较长的时间,为此可通过降采样减少参与模型训练的数据量,进行预搜索,以便在相同的时间内尝试更多的模型参数;然后从预搜索结果中挑选表现较好的参数再利用全量数据进行训练和评估,进一步筛选最佳的模型参数。
通过 make_experiment 创建实验时,设置 down_sample_search=True 可开启预搜索,与之相关的选项包括:
down_sample_search_size:int, float(0.0~1.0) or dict (default 0.1), 参与预搜索的样本数量。对于分类任务,可通过dict指定每个类别数据的采样数量。
down_sample_search_time_limit:int, (default early_stopping_time_limit*0.33), 预搜索的时间限制。
down_sample_search_max_trials:int, (default max_trials*3), 预搜索的最大尝试次数。
启用预搜索的示例代码:
from hypergbm import make_experiment
train_data=...
experiment = make_experiment(train_data,
down_sample_search=True,
down_sample_search_size=0.2,
...)
二阶段特征筛选¶
CompeteExperiment 支持在模型参数优化搜索之后,利用得到的模型对训练数据进行处理,然后再次进行模型参数优化搜索,即 二阶段搜索。目前 CompeteExperiment 支持的第二阶段数据处理方式包括二阶段特征筛选和伪标签,本章余下的两个小节中分别介绍。
在 CompeteExperiment 中,二阶段特征筛选是指从第一阶段选择若干表现较好的模型,进行 permutation_importance 评估,然后筛选出重要的特征。
通过 make_experiment 创建实验时,设置 feature_reselection=True 可开启二阶段特征筛选,与之相关的配置项包括:
feature_reselection_estimator_size:int, (default=10), 用于评估特征重要性的模型数量(在一阶段搜索中表现最好的n个模型)。
feature_reselection_strategy:str, 筛选策略(default threshold), 可用的策略包括 threshold、number 、 quantile。
feature_reselection_threshold:float, (default 1e-5), 当策略为 threshold 时的筛选阈值,重要性高于该阈值的特征会被选择。
feature_reselection_quantile:float, (default 0.2), 当策略为 quantile 时的筛选阈值,重要性分位高于该阈值的特征会被选择。
feature_reselection_number:int or float, (default 0.8), 当策略为 number 时,筛选的特征数量。
启用二阶段特征筛选的示例代码:
from hypergbm import make_experiment
train_data=...
experiment = make_experiment(train_data,
feature_reselection=True,
...)
关于 permutation_importance 的更多信息请参考 [scikit-learn](https://scikit-learn.org/stable/modules/permutation_importance.html)
伪标签¶
伪标签是一种半监督学习技术,将测试集中未观测标签列的特征数据通过一阶段训练的模型预测标签后,将置信度高于一定阈值的样本添加到训练数据中重新训练模型,有时候可以进一步提升模型在新数据上的拟合效果。
在通过 make_experiment 创建实验时设置 pseudo_labeling=True 可开启伪标签训练,与之相关的配置项包括:
pseudo_labeling_strategy:str, 筛选策略(default threshold), 可用的策略包括 threshold、number 、 quantile。
pseudo_labeling_proba_threshold:float(default 0.8), 当策略为 threshold 时的筛选阈值,置信度高于该阈值的样本会被选择。
pseudo_labeling_proba_quantile:float(default 0.8), 当策略为 quantile 时的筛选阈值,置信度分位高于该阈值的样本会被选择。
pseudo_labeling_sample_number:float(0.0~1.0) or int (default 0.2), 当策略为 number 时,对样本按置信度高低排序后选择的样本数(top n)。
pseudo_labeling_resplit:bool(default=False), 添加新的伪标签数据后是否重新分割训练集和评估集. 如果为False, 直接把所有伪标签数据添加到训练集中重新训练模型,否则把训练集、评估集及伪标签数据合并后重新分割。
启用伪标签技术的示例代码:
from hypergbm import make_experiment
train_data=...
test_data=...
experiment = make_experiment(train_data,
test_data=test_data,
pseudo_labeling=True,
...)
说明: 伪标签 仅对分类任务有效。
处理不平衡数据¶
数据不平衡也是业务建模过程中的一个重要挑战,数据的不平衡往往会导致建模效果不理想。HyperGBM 在建模时支持两种类型的不平衡数据处理方式,下面分别介绍。
利用ClassWeight建模¶
在利用底层建模算法(如lightgbm等)建模时,首先计算样本分布比例,然后利用底层算法对模型进行优化。
为了利用ClassWeight建模,在调用make_experiment
时,设置参数class_balancing=‘ClassWeight’
即可,示例如下:
from hypergbm import make_experiment
train_data = ...
experiment = make_experiment(train_data,
class_balancing='ClassWeight',
...)
欠采样或过采样¶
在建模之前,通过欠采样或过采样技术调整样本数据,然后再利用调整后的数据进行建模,以得到表现较好的模型。目前支持的采样策略包括:RandomOverSampler 、SMOTE 、ADASYN 、RandomUnderSampler 、NearMiss 、TomekLinks 、EditedNearestNeighbours。
为了利用欠采样或过采样技建模,在调用make_experiment
时,设置参数class_balancing=‘<采用策略>’
即可,示例如下:
from hypergbm import make_experiment
train_data = ...
experiment = make_experiment(train_data,
class_balancing='SMOTE',
...)
关于欠采样或过采样技术的更多信息,请参考 imbalanced-learn。
自定义SearchSpace¶
make_experiment
缺省使用的搜索空间是search_space_general
,定义如下:
search_space_general = GeneralSearchSpaceGenerator(n_estimators=200)
自定义搜索空间(SearchSpace)¶
在调用make_experiment
时可通过参数search_space
指定自定义的搜索空间。如:指定xgboost
的max_depth=20
:
from hypergbm import make_experiment
from hypergbm.search_space import GeneralSearchSpaceGenerator
my_search_space = \
GeneralSearchSpaceGenerator(n_estimators=200, xgb_init_kwargs={'max_depth': 20})
train_data = ...
experiment = make_experiment(train_data,
search_space=my_search_space,
...)
如果您希望自定义的参数是可搜索的,推荐定义GeneralSearchSpaceGenerator
的一个子类,比如:指定xgboost
的max_depth
在10、20、30之间搜索:
from hypergbm import make_experiment
from hypergbm.search_space import GeneralSearchSpaceGenerator
from hypernets.core.search_space import Choice
class MySearchSpace(GeneralSearchSpaceGenerator):
@property
def default_xgb_init_kwargs(self):
return { **super().default_xgb_init_kwargs,
'max_depth': Choice([10, 20 ,30]),
}
my_search_space = MySearchSpace()
train_data = ...
experiment = make_experiment(train_data,
search_space=my_search_space,
...)
自定义建模算法¶
HyperGBM实现了对XGBoost、LightGBM、CatBoost和HistGridientBoosting的支持,并作为SearchSpace的一部分在建模优化时进行搜索。如果您需要增加对其他算法的支持,则需要:
将您选择的算法封装为HyperEstimator的子类
将封装后的算法增加到SearchSpace中,并定义搜索参数
在make_experiment中年使用您自定义的SearchSpace
示例:
from sklearn import svm
from hypergbm import make_experiment
from hypergbm.estimators import HyperEstimator
from hypergbm.search_space import GeneralSearchSpaceGenerator
from hypernets.core.search_space import Choice, Int, Real
from hypernets.tabular.datasets import dsutils
class SVMEstimator(HyperEstimator):
def __init__(self, fit_kwargs, C=1.0, kernel='rbf', gamma='auto', degree=3, random_state=666, probability=True,
decision_function_shape=None, space=None, name=None, **kwargs):
if C is not None:
kwargs['C'] = C
if kernel is not None:
kwargs['kernel'] = kernel
if gamma is not None:
kwargs['gamma'] = gamma
if degree is not None:
kwargs['degree'] = degree
if random_state is not None:
kwargs['random_state'] = random_state
if decision_function_shape is not None:
kwargs['decision_function_shape'] = decision_function_shape
kwargs['probability'] = probability
HyperEstimator.__init__(self, fit_kwargs, space, name, **kwargs)
def _build_estimator(self, task, kwargs):
if task == 'regression':
hsvm = SVMRegressorWrapper(**kwargs)
else:
hsvm = SVMClassifierWrapper(**kwargs)
hsvm.__dict__['task'] = task
return hsvm
class SVMClassifierWrapper(svm.SVC):
def fit(self, X, y=None, **kwargs):
return super().fit(X, y)
class SVMRegressorWrapper(svm.SVC):
def fit(self, X, y=None, **kwargs):
return super().fit(X, y)
class GeneralSearchSpaceGeneratorPlusSVM(GeneralSearchSpaceGenerator):
def __init__(self, enable_svm=True, **kwargs):
super(GeneralSearchSpaceGeneratorPlusSVM, self).__init__(**kwargs)
self.enable_svm = enable_svm
@property
def default_svm_init_kwargs(self):
return {
'C': Real(0.1, 5, 0.1),
'kernel': Choice(['rbf', 'poly', 'sigmoid']),
'degree': Int(1, 5),
'gamma': Real(0.0001, 5, 0.0002)
}
@property
def default_svm_fit_kwargs(self):
return {}
@property
def estimators(self):
r = super().estimators
if self.enable_svm:
r['svm'] = (SVMEstimator, self.default_svm_init_kwargs, self.default_svm_fit_kwargs)
return r
my_search_space = GeneralSearchSpaceGeneratorPlusSVM()
train_data = dsutils.load_blood()
experiment = make_experiment(train_data, target='Class',
search_space=my_search_space)
estimator = experiment.run()
print(estimator)
分布式训练¶
快速实验¶
HyperGBM支持使用Dask进行分布式训练,在运行实验之前您需要部署Dask集群并初始化Dask客户端Client
对象;如果您的训练数据是csv或parquet格式,而且数据文件的扩展名是“.csv”或“.parquet”的话,可以直接使用文件路径创建实验,make_experiment在检测到Dask环境是会自动将数据加载为Dask的DataFrame对象并进行搜索和训练。
示例代码(以单节点为例,假设您的训练数据文件是‘/opt/data/my_data.csv’):
from dask.distributed import LocalCluster, Client
from hypergbm import make_experiment
from hypernets.tabular.datasets import dsutils
def train():
cluster = LocalCluster(processes=True)
client = Client(cluster)
train_data = '/opt/data/my_data.csv'
experiment = make_experiment(train_data, target='...')
estimator = experiment.run()
print(estimator)
if __name__ == '__main__':
train()
对于大规模数据,为了加速数据的加载过程,建议您将数据拆分为多个文件并保存在一个目录下(如:/opt/data/my_data/),然后使用目录下的文件创建实验,如:
from dask.distributed import LocalCluster, Client
from hypergbm import make_experiment
from hypernets.tabular.datasets import dsutils
def train():
cluster = LocalCluster(processes=True)
client = Client(cluster)
train_data = '/opt/data/my_data/*.parquet'
experiment = make_experiment(train_data, target='...')
estimator = experiment.run()
print(estimator)
if __name__ == '__main__':
train()
您也可以直接使用dask.dataframe
提供的方法将数据加载为Dask DataFrame然后创建实验,如:
from dask import dataframe as dd
from dask.distributed import LocalCluster, Client
from hypergbm import make_experiment
from hypernets.tabular.datasets import dsutils
def train():
cluster = LocalCluster(processes=False)
client = Client(cluster)
train_data = dd.from_pandas(dsutils.load_blood(), npartitions=1)
experiment = make_experiment(train_data, target='Class')
estimator = experiment.run()
print(estimator)
if __name__ == '__main__':
train()
关于使用Dask DataFrame的更多信息请参考Dask官方文档中的 Create DataFrames
自定义SearchSpace¶
在Dask环境下运行实验时,搜索空间中使用的Transformer和Estimator必须都支持Dask数据类型,您可以参考或基于HyperGBM内置的支持Dask的搜索空间定义自己的搜索空间。
from dask import dataframe as dd
from dask.distributed import LocalCluster, Client
from hypergbm import make_experiment
from hypergbm.dask.search_space import search_space_general
from hypernets.tabular.datasets import dsutils
def my_search_space():
return search_space_general(n_estimators=100)
def train():
cluster = LocalCluster(processes=False)
client = Client(cluster)
train_data = dd.from_pandas(dsutils.load_blood(), npartitions=1)
experiment = make_experiment(train_data, target='Class', searcher='mcts', search_space=my_search_space)
estimator = experiment.run()
print(estimator)
if __name__ == '__main__':
train()
How-To¶
如何在centos7上安装shap?¶
安装系统依赖
yum install epel-release centos-release-scl -y && yum clean all && yum make cache # llvm9.0 is in epel, gcc9 in scl yum install -y llvm9.0 llvm9.0-devel python36-devel devtoolset-9-gcc devtoolset-9-gcc-c++ make cmake
配置安装环境
whereis llvm-config-9.0-64 # find your `llvm-config` path # llvm-config-9: /usr/bin/llvm-config-9.0-64 export LLVM_CONFIG=/usr/bin/llvm-config-9.0-64 # set to your path scl enable devtoolset-9 bash
安装shap
pip -v install numpy==1.19.1 # prepare shap dependency pip -v install scikit-learn==0.23.1 # prepare shap dependency pip -v install shap==0.28.5
Release Notes¶
历史:
Version 0.2.3¶
本次发布优化及新增的特性:
数据清洗
支持从数据类型为数值型的特征中自动识别类别列
可指定在数据清洗时对某些列不做处理
特征衍生
增加对时间、文本、经纬度类型的支持
增加对分布式的支持
建模算法
XGBoost:分布式建模从
dask_xgboost
迁移到xgboost.dask
,与XGBoost官网保值一致LightGBM:增加对多机分布式的支持
模型训练
搜索过程可复现
支持低保真搜索
基于统计信息预测学习曲线
支持非侵入式超参数优化
EarlyStopping时间限制的范围调整为对整个实验的训练周期
训练时支持自定义pos_label
分布式场景下,eval-set支持Dask数据集
优化模型训练中间结果的缓存策略
搜索算法
增加GridSearch算法
增加Playback算法
高级特性
增加一阶段特征筛选并支持多种策略
二阶段特征筛选支持多种策略
伪标签支持多种数据筛选策略,并增加对多分类的支持
优化概念漂移处理的执行性能
增加对高级特性执行中间结果的缓存机制
可视化
实验信息可视化
训练过程可视化
命令行工具
模型训练时可通过命令行参数支持实验的大部分特性
支持模型评价
支持模型预测
Version 0.2.2¶
本次发布新增以下特性:
特征工程
特征衍生
特征降维
数据清洗
特殊空值字符处理
列类型校正
常量列清理
重复列清理
删除标签列为空的样本
非法值替换
id列清理
共线性特征清理
数据集拆分
对抗验证
建模算法
XGBoost
Catboost
LightGBM
HistGridientBoosting
模型训练
自动任务类型推断
命令行工具
评估方法
交叉验证(Cross-Validation)
Train-Validation-Holdout验证
搜索算法
蒙特卡洛树算法
进化算法
随机搜索算法
不平衡数据处理
类平衡(Class Weight)
降采样(Under -Samping)支持
Near miss
Tomeks links
Random
过采样(Over-Samping)支持
SMOTE
ADASYN
Random
提前停止策略
n次搜索都不再提升,提前停止
最大用时提前停止
到达预期指标提前停止
高级特性
二阶段搜索
伪标签
特征选择
概念漂移处理
模型融合