前言
- 在表格数据的建模中,特征工程至关重要,
OpenFE
框架可以帮助我们快速找到有效益的交叉特征,并且提供一定的可解释性 - 这里提供论文地址,我在博客中也对这篇论文进行了解读,OpenFE的项目地址和官方文档
- 在使用
OpenFE
时,请先安装这个库pip install openfe
使用示例
导入必要包
# 加载包
import datetime
import yaml
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.ensemble import RandomForestRegressor
# 忽略警告
import warnings
warnings.filterwarnings('ignore')
from openfe import openfe, transform, tree_to_formula
import multiprocessing
from typing import Tuple
导入训练数据
def read_csv(file_name: str) -> pd.DataFrame:
return pd.read_csv(file_name, encoding='utf-8')
df_train = read_csv('train.csv')
df_test = read_csv('test.csv')
使用OpenFE进行特征工程
- 函数参数说明:
df_train
训练数据,df_test
测试数据,target
目标列名 - 输出:
train_x
训练数据,train_y
测试数据
def open_fe(df_train: pd.DataFrame, df_test: pd.DataFrame, target: str) -> Tuple[pd.DataFrame, pd.DataFrame]:
# 实例化
ofe = openfe()
# 获取CPU最大线程数
n_jobs = multiprocessing.cpu_count()
# 分离特征
d_x = df_train.iloc[:, df_train.columns != target]
# 分离结果列
d_y = df_train[[target]]
# 训练
ofe.fit(data=d_x, label=d_y, n_jobs=n_jobs, seed=2023, verbose=False)
# 取特征分数前5的特征
train_x, test_x = transform(d_x, df_test, ofe.new_features_list[:5], n_jobs=n_jobs)
# 打印特征
for temp in ofe.new_features_list[:5]:
print(tree_to_formula(temp))
# 拼接
train_x[target] = d_y
return train_x.reset_index(drop=True), test_x
df_train, df_test = open_fe(df_train, df_test, 'Strength')
输出:
The number of candidate features is 275
Start stage I selection.
100%|██████████| 55/55 [01:03<00:00, 1.16s/it]
49 same features have been deleted.
The number of remaining candidate features is 226
Start stage II selection.
100%|██████████| 57/57 [01:09<00:00, 1.22s/it]
Finish data processing.
(SuperplasticizerComponent+AgeInDays)
(CementComponent*AgeInDays)
(WaterComponent/AgeInDays)
(FineAggregateComponent/AgeInDays)
(CementComponent+BlastFurnaceSlag)
训练随机森林模型
- 使用默认参数的随机森林,训练模型
# 分离特征
d_x = df_train.iloc[:, df_train.columns != 'Strength']
# 分离结果列
d_y = df_train[['Strength']]
rf_reg = RandomForestRegressor()
# 在训练集上训练模型
rf_reg.fit(d_x, d_y)
# 查看模型在训练集上均方误差
print('train_mes : {:.3f}'.format(mean_squared_error(d_y, rf_reg.predict(d_x))))
OpenFE.fit()参数说明
参数 | 默认值 | 描述 |
---|---|---|
data | - | 输入数据 |
label | - | 目标变量 |
task | None | 任务类型。可选值为:‘classification’ 或 ‘regression’,如果未指定,则将目标变量唯一值数小于20的标签设置为分类任务,否则为回归任务。 |
train_index | None | 用于训练的数据索引。 |
val_index | None | 用于验证的数据索引。如果train_index或val_index未指定,则将数据划分为0.8(训练)和0.2(验证)。建议在数据具有时间序列属性时传入索引。 |
candidate_features_list | None | 候选特征列表,用于过滤。如果未指定,则会自动生成,并且用户可以根据其先前知识定义候选特征列表。 |
init_scores | None | 特征增强的初始分数。请参见我们的论文以了解更多详细信息。如果未指定,则我们通过5倍交叉验证生成初始分数。 |
categorical_features | None | 分类特征列表。如果未指定,则使用数据中的非数值列。 |
metric | None | 用于评估特征增强中新特征性能的度量。目前支持[‘binary_logloss’,‘multi_logloss’,‘auc’,‘rmse’]。二元分类任务的默认度量是’binary_logloss’,多分类任务的默认度量是’multi_logloss’,回归任务的默认度量是’rmse’。 |
drop_columns | None | 在第二阶段构建LightGBM时要删除的列的列表。这些列仍将用于生成candidate_features_list。 |
n_data_blocks | 8 | 连续特征分别缩减的数据块数量。请参见我们的论文以了解更多详细信息。应为2^k(例如1、2、4、8、16、32等)。较大的值可以加快速度,但可能会损害整体性能,特别是当有许多有用的候选特征时。 |
min_candidate_features | 2000 | 连续特征分别缩减后的最小候选特征数。用于及早停止连续特征分别缩减。当候选特征数小于min_candidate_features时,连续特征分别缩减将立即停止。 |
feature_boosting | False | 是否使用特征增强。请参见我们的论文以了解更多详细信息。如果为False,则init_scores将设置为LightGBM中的默认值。 |
stage1_metric | ‘predictive’ | 用于评估第一阶段中特征性能的度量。目前支持[‘predictive’,‘corr’,‘mi’]。'predictive’是本论文中所述的方法。'corr’是特征与目标变量之间的Pearson相关系数。 |
stage2_metric | ‘gain_importance’ | 用于在第二阶段对特征进行排序的特征重要性。目前支持[‘gain_importance’, ‘permutation’]。'gain_importance’与LightGBM中的重要性相同。'permutation’是另一种特征重要性方法。它有时比增益重要性更好,但需要更多的计算时间。 |
stage2_params | None | 阶段二中训练LightGBM的参数。 |
is_stage1 | True | 是否使用连续的特征减半法来消除候选特征。如果为False,所有的候选特征都被计算出来,并在第二阶段用于训练LightGBM,这可能需要大量的内存以及计算时间。 |
n_repeats | 1 | 变化中的重复次数。只有当stage2_metric被设置为’permutation’时才有用。 |
tmp_save_path | ./openfe_tmp_data.feather’ | 为多进程保存数据的临时路径。 |
n_jobs | 1 | 用于特征计算和评估的进程数量。 |
verbose | True | 是否显示信息。 |
更快的运行速度
使用更多的CPU线程数
- 在可用的系统上,
OpenFE
使用多处理来并行计算和评估新功能。OpenFE
使用的最大线程数由参数n_jobs
控制。为获得最佳性能,请将其设置为实际可用 CPU 内核数。
增加n_data_blocks
- 此参数是一个整数,用于控制将数据拆分为连续减半的数据块数。
OpenFE
的整体复杂度为 O ( q 2 − q ⋅ m n 2 ) O(q^{2-q} \cdot mn^{2}) O(q2−q⋅mn2),其中 m m m为特征数, n n n为样本数, 2 q 2^q 2q为数据块数。尽管增加n_data_blocks
的值可以加快计算速度,但这样做可能会对整体性能产生负面影响,因为在连续的要素减半期间可能会丢弃重要的候选特征。这是效率和有效性之间的权衡。此外,设置n_data_blocks
为较大的值将导致留给 stage2 选择的候选特征很少。这可以通过将参数min_candidate_features
设置为提前停止连续的特征减半来控制
在特征生成之前执行特征选择
另一种加速方法是在特征生成之前执行特征选择并删除冗余特征。这可以减少候选要素的数量以加快速度。但是,这种加速方法也可能损害性能,因为无信息特征也可能在转换后产生信息候选特征。例如,在糖尿病数据集中,当目标是预测患者是否会再次入院时,“ID”特征是无用的。然而,“freq”,即患者入院的次数,是患者是否会再次入院的有力预测指标。
更好的性能
减少n_data_blocks
或增加min_candidate_features
- 如果候选特征池中有许多有用的候选特征,则这一点尤其重要。但是,如果没有很多有用的候选要素,则更改这两个参数可能不会产生任何影响。
对生成的要素执行特征选择
- 在我们的示例中,我们直接包含
OpenFE
推荐的顶级生成功能。用户还可以执行更精细的特征选择方法(如前向特征选择),以获得更好的性能。
设置feature_boosting
尝试将feature_boosting
设置为True
或False
,该参数决定是否在OpenFE
中使用功能提升的重要参数(请参阅我们论文中的更多详细信息)。通常,使用特征提升可以在大多数数据集上产生更好的结果。但是,在某些数据集上,我们发现禁用功能提升可以提供更好的结果。