如何在XGBoost每次提升迭代中修改数据集特征?(附论文复现场景)
回答:当然可以用XGBoost Python API实现迭代间的DMatrix特征更新
没问题!你要复现的这个特征迭代增强+基学习器堆叠的逻辑,完全可以通过XGBoost的Python API配合常规的数据处理操作实现——核心思路是每次迭代都基于更新后的特征矩阵重新构建DMatrix,因为DMatrix本身是基于输入数据(numpy数组/pandas DataFrame)创建的,只要你的特征数据更新了,重新生成DMatrix就相当于完成了特征的添加。
下面我结合你的算法步骤,给你一套可落地的代码思路和细节说明:
1. 初始训练与特征重要性提取
首先用初始数据集训练第一个XGBoost基学习器,然后提取特征重要性(你提到的「f-score(分裂次数)」对应XGBoost里的weight类型,即特征被用于分裂的次数):
import xgboost as xgb import pandas as pd import numpy as np from sklearn.model_selection import train_test_split # 假设你的初始数据集是df,标签列是'y' X_train, X_val, y_train, y_val = train_test_split(df.drop('y', axis=1), df['y'], test_size=0.2) # 初始DMatrix dtrain = xgb.DMatrix(X_train, label=y_train) dval = xgb.DMatrix(X_val, label=y_val) # 训练初始基学习器 params = {'objective': 'binary:logistic', 'eval_metric': 'auc', 'seed': 42} model = xgb.train(params, dtrain, num_boost_round=100, evals=[(dval, 'val')]) # 提取特征重要性(分裂次数) feature_importance = model.get_booster().get_score(importance_type='weight') total_splits = sum(feature_importance.values())
2. 筛选重要特征
根据你设定的阈值(比如占总分裂次数的5%),过滤掉不重要的特征:
# 计算每个特征的分裂占比,筛选占比≥5%的特征 threshold = 0.05 important_features = [ feat for feat, cnt in feature_importance.items() if cnt / total_splits >= threshold ] # 保留重要特征的数据集 X_important = X_train[important_features] X_val_important = X_val[important_features]
3. 构建特征采样概率分布
基于剩余特征的分裂次数,归一化得到采样概率:
feat_counts = [feature_importance[feat] for feat in important_features] sampling_probs = np.array(feat_counts) / sum(feat_counts)
4. 生成新特征
可放回采样两个特征,执行随机数学运算,重复若干次生成新特征:
def generate_new_features(X, features, probs, num_new_feats=10): new_features = pd.DataFrame() for i in range(num_new_feats): # 可放回采样两个特征 feat1, feat2 = np.random.choice(features, size=2, replace=True, p=probs) # 随机选择运算 op = np.random.choice(['add', 'sub', 'mul', 'div']) if op == 'add': new_feat = X[feat1] + X[feat2] elif op == 'sub': new_feat = X[feat1] - X[feat2] elif op == 'mul': new_feat = X[feat1] * X[feat2] elif op == 'div': # 避免除以0,加一个极小值 new_feat = X[feat1] / (X[feat2] + 1e-8) new_features[f'{feat1}_{op}_{feat2}_{i}'] = new_feat return new_features # 生成训练集和验证集的新特征 X_new_train = generate_new_features(X_important, important_features, sampling_probs) X_new_val = generate_new_features(X_val_important, important_features, sampling_probs)
5. 拼接特征并构建新的DMatrix
把保留的重要特征和新生成的特征拼接,然后创建新一轮的DMatrix:
# 拼接特征 X_train_next = pd.concat([X_important, X_new_train], axis=1) X_val_next = pd.concat([X_val_important, X_new_val], axis=1) # 构建新的DMatrix dtrain_next = xgb.DMatrix(X_train_next, label=y_train) dval_next = xgb.DMatrix(X_val_next, label=y_val)
6. 训练下一个基学习器
用新的DMatrix训练下一个XGBoost模型,然后重复整个迭代流程即可:
# 训练下一个基学习器 model_next = xgb.train(params, dtrain_next, num_boost_round=100, evals=[(dval_next, 'val')]) # 接下来可以重复步骤2-6:提取model_next的特征重要性,筛选,生成新特征...
关键注意点
- DMatrix本身是不可变对象,不能直接修改已有的DMatrix添加特征,但我们可以通过拼接特征后重新创建DMatrix的方式,实现迭代间的特征更新——这也是最简洁高效的做法。
- 每次迭代的特征重要性是基于当前基学习器的,所以筛选的重要特征会随着迭代动态变化,符合你论文里的逻辑。
- 生成新特征时,除法要注意避免除以0的情况,建议加一个极小的epsilon(比如1e-8)来防止报错。
内容的提问来源于stack exchange,提问作者MLearner
相关产品推荐
相关产品推荐

