Skip to content

参考

基于 scikit-learn 1.9.0 + feature-engine 1.x + category_encoders 官方文档整理

速查

  • 缩放选型一句话:默认 StandardScaler;有异常值用 RobustScaler;要 [0,1] 用 MinMaxScaler;稀疏用 MaxAbsScaler;按样本归一用 Normalizer
  • 谁需缩放:KNN / SVM / SGD / 神经网络(基于距离或梯度);树模型(随机森林/GBDT)不需缩放
  • 类别编码一句话:低基数(<10)OneHot;有序类别 OrdinalEncoder;高基数 TargetEncoder;超高基数/在线 HashingEncoder
  • TargetEncoder 防泄漏:用 fit_transform(交叉拟合),不用 fit().transform()smooth='auto' 自动平滑
  • 版本:scikit-learn 1.9.0(2025,TargetEncoder 1.3+ 引入)/ feature-engine 1.x / category_encoders 2.x
  • 安装pip install scikit-learn feature-engine category_encoders
  • Pipeline 防泄漏:所有预处理 + 模型用 Pipeline 包裹,GridSearchCV 自动在 CV 折内 fit
  • 三大工具分工:scikit-learn preprocessing(通用统一 API)/ feature-engine(按列名、可读性强)/ category_encoders(编码最全)

缩放工具对照表

工具机制公式适用稀疏支持
StandardScaler标准化(x-μ)/σ默认首选with_mean=False 才行
MinMaxScaler归一化到 [0,1](x-min)/(max-min)神经网络、固定范围
MaxAbsScaler缩放到 [-1,1]`x/maxx`
RobustScaler鲁棒标准化(x-中位数)/IQR有异常值
Normalizer样本归一化(按行)x/‖x‖文本向量

类别编码策略矩阵

编码器基数有序监督防泄漏适用
OneHotEncoder无需低基数(<10 类),线性/树皆可
OrdinalEncoder无需有序类别(低/中/高)
TargetEncoderfit_transform 交叉拟合高基数(sklearn 1.3+)
CatBoostEncoderOrdered 机制高基数(category_encoders)
LeaveOneOutEncoder留一法高基数,相对简单
JamesSteinEncoder收缩估计高基数,贝叶斯收缩
GLMMEncoder广义线性混合模型高基数,最严谨
WOEEncoder二分类需 CV信用评分(Weight of Evidence)
HashingEncoder超高无需在线学习、新类别不断出现
CountEncoder无需高基数,用频次替代
BaseNEncoder无需OneHot 的紧凑版(二进制)

特征选择方法对照

类别方法原理速度模型依赖sklearn
FilterVarianceThreshold剔除低方差特征极快
FilterSelectKBest / SelectPercentile统计检验打分
WrapperRFE / RFECV递归剔除最不重要需 coef_/importances_
WrapperSequentialFeatureSelector贪心前向/后向最慢任意模型
EmbeddedSelectFromModel(L1)L1 正则系数归零需 L1 模型
EmbeddedSelectFromModel(树)树 feature_importances_需树模型

Filter 打分函数f_classif(分类,线性依赖)/ mutual_info_classif(分类,任意依赖,非参数)/ chi2(分类,仅非负特征)/ f_regression(回归)/ mutual_info_regression(回归)。

核心 API 速查

scikit-learn preprocessing

python
from sklearn.preprocessing import (
    StandardScaler, MinMaxScaler, MaxAbsScaler, RobustScaler, Normalizer,
    KBinsDiscretizer, Binarizer,
    OneHotEncoder, OrdinalEncoder, TargetEncoder,   # TargetEncoder 1.3+
    PowerTransformer, QuantileTransformer, FunctionTransformer,
    PolynomialFeatures, SplineTransformer,
)

# 缩放
StandardScaler().fit_transform(X)
MinMaxScaler(feature_range=(0,1)).fit_transform(X)
RobustScaler(quantile_range=(25,75)).fit_transform(X)

# 变换
PowerTransformer(method='yeo-johnson', standardize=True)   # method: 'box-cox'(仅正) / 'yeo-johnson'(通用)
QuantileTransformer(output_distribution='normal', n_quantiles=100)
FunctionTransformer(func=np.log1p, inverse_func=np.expm1)

# 分箱
KBinsDiscretizer(n_bins=5, encode='ordinal', strategy='quantile')  # strategy: uniform/quantile/kmeans

# 类别
OneHotEncoder(drop='first', handle_unknown='ignore', sparse_output=True)
OrdinalEncoder(categories=[['low','medium','high']])
TargetEncoder(smooth='auto')   # 必用 fit_transform 防泄漏

# 交叉
PolynomialFeatures(degree=2, interaction_only=False, include_bias=False)

scikit-learn impute

python
from sklearn.impute import SimpleImputer, KNNImputer
from sklearn.experimental import enable_iterative_imputer  # 必须导入启用
from sklearn.impute import IterativeImputer

SimpleImputer(strategy='median')                          # mean/median/most_frequent/constant
SimpleImputer(strategy='constant', fill_value='missing')
KNNImputer(n_neighbors=5)
IterativeImputer(max_iter=10, random_state=42)            # 类似 MICE

scikit-learn feature_selection

python
from sklearn.feature_selection import (
    VarianceThreshold, SelectKBest, SelectPercentile, SelectFromModel,
    RFE, RFECV, SequentialFeatureSelector,
    chi2, f_classif, f_regression, mutual_info_classif, mutual_info_regression,
)

VarianceThreshold(threshold=0.0)                                   # 剔除零方差
SelectKBest(mutual_info_classif, k=20)                             # top-k
SelectFromModel(RandomForestClassifier(), threshold='median')      # 树重要性
SelectFromModel(LogisticRegression(penalty='l1', solver='liblinear'))  # L1 稀疏
RFE(estimator, n_features_to_select=20)                            # 递归剔除
RFECV(estimator, cv=5)                                             # 自动定特征数
SequentialFeatureSelector(estimator, direction='forward')          # 贪心选择

feature-engine(按列名操作)

python
from feature_engine.encoding import (
    OneHotEncoder, OrdinalEncoder, MeanEncoder, CountFrequencyEncoder,
    RareLabelEncoder, WoEEncoder, DecisionTreeEncoder,
)
from feature_engine.imputation import (
    MeanMedianImputer, ArbitraryNumberImputer, EndTailImputer,
    CategoricalImputer, RandomSampleImputer, AddMissingIndicator, DropMissingData,
)
from feature_engine.discretisation import (
    EqualFrequencyDiscretiser, EqualWidthDiscretiser, DecisionTreeDiscretiser,
)
from feature_engine.transformation import (
    LogTransformer, LogCpTransformer, BoxCoxTransformer, YeoJohnsonTransformer, PowerTransformer,
)
from feature_engine.outliers import Winsorizer, OutlierTrimmer, ArbitraryOutlierCapper
from feature_engine.creation import (
    MathFeatures, RelativeFeatures, CyclicalFeatures, DecisionTreeFeatures,
)
from feature_engine.selection import (
    DropFeatures, DropConstantFeatures, DropDuplicateFeatures,
    DropCorrelatedFeatures, SmartCorrelatedSelection,
    RecursiveFeatureElimination, RecursiveFeatureAddition,
    SelectByShuffling, SelectBySingleFeaturePerformance,
)

# 按列名操作示例(feature-engine 的核心优势)
MeanMedianImputer(imputation_method='median', variables=['age', 'income'])
OneHotEncoder(top_categories=10, variables=['city'])   # 只编码 top-10 类别
RareLabelEncoder(tol=0.05, n_categories=5, variables=['city'])  # 合并稀有类
Winsorizer(capping_method='iqr', tail='both', variables=['income'])
CyclicalFeatures(variables=['hour', 'month'], max_val={'hour': 24, 'month': 12})

feature-engine 的优势:按列名(variables)精确指定处理的列,输出仍是 DataFrame(保留列名),与 sklearn Pipeline 完全兼容。sklearn 的转换器默认输出 ndarray,列名丢失(需 set_config(transform_output='pandas') 恢复)。

category_encoders(编码最全)

python
import category_encoders as ce

ce.OneHotEncoder(use_cat_names=True)
ce.OrdinalEncoder()
ce.TargetEncoder(smoothing=1.0)        # 监督编码
ce.CatBoostEncoder()                    # Ordered 思路
ce.LeaveOneOutEncoder()                 # 留一法防泄漏
ce.JamesSteinEncoder()                  # 贝叶斯收缩
ce.GLMMEncoder()                        # 广义线性混合模型
ce.WOEEncoder()                         # Weight of Evidence(二分类)
ce.HashingEncoder(n_components=64)      # 哈希
ce.CountEncoder()                       # 频次
ce.BaseNEncoder(base=2)                 # Base-N(二进制即 Base2)
ce.BinaryEncoder()                      # BaseNEncoder(base=2) 别名

完整防泄漏 Pipeline 模板

python
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder, TargetEncoder
from sklearn.impute import SimpleImputer
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV, StratifiedKFold

num_cols = ['age', 'income', 'orders_30d']
cat_low = ['device', 'channel']          # 低基数
cat_high = ['city', 'user_segment']      # 高基数

preprocessor = ColumnTransformer([
    ('num', Pipeline([
        ('imp', SimpleImputer(strategy='median')),
        ('scl', StandardScaler()),
    ]), num_cols),
    ('cat_low', Pipeline([
        ('imp', SimpleImputer(strategy='constant', fill_value='missing')),
        ('ohe', OneHotEncoder(handle_unknown='ignore')),
    ]), cat_low),
    ('cat_high', TargetEncoder(smooth='auto'), cat_high),  # fit_transform 防泄漏
])

pipe = Pipeline([
    ('pre', preprocessor),
    ('sel', SelectFromModel(RandomForestClassifier(n_estimators=100), threshold='median')),
    ('clf', RandomForestClassifier(random_state=42)),
])

grid = GridSearchCV(
    pipe,
    {'clf__n_estimators': [200, 500]},
    cv=StratifiedKFold(5),
    scoring='f1_macro',
    n_jobs=-1,
)
grid.fit(X_train, y_train)   # 所有预处理在 CV 折内自动重新 fit,零泄漏

官方资源