高级特征处理方法
立即解锁
发布时间: 2025-09-10 01:24:41 阅读量: 12 订阅数: 18 AIGC 


表格数据机器学习实战
# 高级特征处理方法
在机器学习领域,特征处理是构建有效模型的关键步骤。本文将深入探讨一些高级特征处理方法,包括处理缺失数据、目标编码以及数值数据转换等内容。
## 1. 用 GBDT 处理缺失数据
### 1.1 XGBoost 和 LightGBM 的处理方式
XGBoost 和 LightGBM 算法(以及 Scikit-learn 的 HistGradientBoosting)处理缺失值的方式类似,它们在每次分裂时,会将缺失值分配到使损失函数最小化的一侧。
XGBoost 通过其稀疏感知分裂查找算法引入了这种技术,该算法为缺失数据提供了默认的处理方向。需要注意的是,XGBoost 会将稀疏矩阵中的零视为缺失值,并应用其特定算法进行处理。在训练过程中,算法会根据分裂点的增益,学习将缺失值样本分配到左分支还是右分支;在预测时,会相应地将缺失值样本分配到合适的子节点。
你可以使用 `missing` 参数指定 XGBoost 认为的缺失值,该参数默认设置为 `NaN`。另外,XGBoost 的 `gblinear` 增强器使用线性模型作为基学习器,会将缺失值视为零。如果对数值特征进行标准化,`gblinear` 增强器会将缺失值视为该特征的平均值。
LightGBM 采用了类似的方法,使用特定参数进行配置:
- 默认情况下,LightGBM 启用缺失值处理,可通过设置 `use_missing=false` 关闭。
- 默认使用 `NA (NaN)` 表示缺失值,可通过设置 `zero_as_missing=true` 将零视为缺失值。
当 `zero_as_missing=false`(默认)时,稀疏矩阵(和 LightSVM)中未记录的值被视为零;当 `zero_as_missing=true` 时,`NA` 和零(包括稀疏矩阵中未记录的值)被视为缺失值。
### 1.2 不同缺失机制下的处理策略
这种处理缺失数据的策略在数据为完全随机缺失(MCAR)时效果较好,即缺失实例的模式完全随机,与其他特征或隐藏的潜在过程无关。但在数据为随机缺失(MAR)和非随机缺失(NMAR)的情况下,情况有所不同。在 MAR 中,缺失与其他特征的值有关,但与该特征本身的值无关;在 NMAR 中,缺失值存在与该特征本身和其他特征相关的系统模式。在这些情况下,最好尝试通过其他方法填充这些值,因为 XGBoost 和 LightGBM 的缺失数据处理策略可能表现不佳。
除了填充缺失数据,还有其他替代方法:
- 创建缺失数据指示器,这是一种二进制特征,对应变量中的缺失实例取值。如果数据不是完全随机缺失,缺失数据指示器可能非常有价值,并且可以与任何经典机器学习算法一起使用。
- 对于决策树,将缺失值分配给数据集中任何变量都未使用的极端值(通常是负极端值)。如果使用精确分裂而不是基于直方图的分裂(将值缩减为区间),用极端值替换缺失数据可能是一种高效且简单的解决方案。
## 2. 目标编码
### 2.1 分类特征编码概述
分类特征通常在数据集中以字符串形式表示,可以通过不同策略进行有效处理。常见的编码方法包括独热编码(One-Hot Encoding)和顺序编码(Ordinal Encoding)。Scikit-learn 包提供了相应的编码解决方案:
- `OneHotEncoder`:用于独热编码,将每个唯一的字符串值转换为二进制特征。
- `OrdinalEncoder`:用于顺序编码,将特征中的字符串值转换为有序的数值。
一般来说,独热编码适用于线性模型和基于树的模型,顺序编码适用于更复杂的基于树的模型,如随机森林和 GBDT。但在处理高基数分类特征时,独热编码和顺序编码会出现问题。高基数分类特征通常包括 ID、邮政编码、产品或地理名称等具有许多唯一值的特征。
### 2.2 目标编码原理
目标编码(Target Encoding)是一种将分类特征中的值转换为相应预期目标值的方法。在回归问题中,目标编码使用数据集中对应值的平均目标值;在分类问题中,使用条件概率或优势比。为了减轻模型过拟合的风险,会使用该类别预期值(目标的后验概率)和整个数据集的平均预期值(目标在所有训练数据上的先验概率)的加权平均值。
目标编码可以通过 `category-encoders` 包中的 `TargetEncoder` 类实现,你可以通过以下命令进行安装:
```bash
pip install category_encoders
```
在 `TargetEncoder` 类中,需要指定一个平滑参数(值应大于零)来平衡目标的后验概率和整个训练数据的先验概率。最佳平滑参数需要通过实验确定,也可以使用 James Steiner 编码器,它会根据要编码的类别条件方差来猜测最佳平滑方式。
### 2.3 示例代码
以下是一个创建高基数分类特征并使用目标编码的示例代码:
```python
def bin_2_cat(feature, bins=100):
min_value = feature.min()
bin_size = (feature.max() - min_value) / bins
bin_values = (feature - min_value) / bin_size
return bin_values.astype(int)
data['coordinates'] = (
bin_2_cat(data['latitude']) * 1000
+ bin_2_cat(data['longitude'])
)
high_card_categorical = []
high_card_categorical += ['coordinates']
print(data[high_card_categorical].nunique())
from category_encoders.target_encoder import TargetEncoder
from xgboost import XGBClassifier
from sklearn.model_selection import KFold, cross_validate
from sklearn.metrics import accuracy_score, make_scorer
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
import numpy as np
target_encoder = TargetEncoder(cols=high_card_categorical,
smoothing=0.5)
accuracy = make_scorer(accuracy_score)
cv = KFold(5, shuffle=True, random_state=0)
xgb = XGBClassifier(booster='gbtree',
objective='reg:logistic',
n_estimators=300,
max_depth=4,
min_child_weight=3)
column_transform = ColumnTransformer(
[
('low_card_categories',
None,
[]),
('high_card_categories',
target_encoder,
high_card_categorical),
('numeric',
None,
[])
],
remainder='drop',
verbose_feature_names_out=True,
sparse_threshold=0.0)
model_pipeline = Pipeline(
[('processing', column_transform),
('model', xgb)])
cv_scores = cross_validate(estimator=model_pipeline,
X=data,
y=target_median,
scoring=accuracy,
cv=cv,
return_train_score=True,
return_estimator=True)
mean_cv = np.mean(cv_scores['test_score'])
std_cv = np.std(cv_scores['test_score'])
fit_time = np.mean(cv_scores['fit_time'])
score_time = np.mean(cv_scores['score_time'])
print(f"{mean_cv:0.3f} ({std_cv:0.3f})",
f"fit: {fit_time:0.2f}",
f"secs pred: {score_time:0.2f} secs")
```
### 2.4 目标编码的优缺点及其他处理选项
目标编码虽然可以快速将任何分类特征转换为数值特征,但它会使特征之间的交互建模变得不可能。在处理高基数分类特征时,在采用目标编码之前,可以考虑以下几种经典机器学习算法和梯度提升的处理选项:
- 直接删除有问题的分类特征。
- 使用 `OneHotEncoder`。
- 使用 `OrdinalEncoder` 并将
0
0
复制全文
相关推荐









