第4章 特征选择与维度控制

4.1 概述

在机会评分模型开发中,初始特征空间通常包含数十到数百个变量,其中大量变量是噪声、冗余或弱相关的。特征选择与维度控制的目标是在保证预测能力的前提下,剔除无效变量、降低过拟合风险、提升模型稳定性和可解释性。本章将依次介绍四种主流方法:IV值筛选、相关性剪枝、LASSO正则化以及前向/后向选择,并给出组合使用的最佳实践。

特征选择与维度控制流程 原始特征集 IV值筛选 相关性剪枝 LASSO正则化 前向/后向选择 最终特征子集 IV>0.02 保留 剔除弱预测变量 |r|<0.7 保留 去除高度冗余对 λ 由交叉验证确定 系数压缩至零

4.2 IV值筛选(信息量)

IV(Information Value) 衡量单个自变量对二元目标变量的区分能力。在信用评分领域,IV值常按以下区间判断:

IV 区间预测力建议
< 0.02极弱剔除
0.02 – 0.10弱可考虑剔除
0.10 – 0.30中等保留
0.30 – 0.50强重点保留
> 0.50极强但可能过拟合需结合业务检验
实现要点: IV计算要求变量先进行分箱(WOE转化)。确保箱内样本数不少于总样本的5%,避免统计不稳定。
# Python 示例:计算单个变量IV
import pandas as pd
import numpy as np

def calc_iv(x, y, bins=10):
    df = pd.DataFrame({'x': x, 'y': y})
    df['bin'] = pd.qcut(df['x'], q=bins, duplicates='drop')
    grouped = df.groupby('bin', observed=False)['y'].agg(['count', 'sum'])
    grouped['event'] = grouped['sum']
    grouped['non_event'] = grouped['count'] - grouped['sum']
    total_event = grouped['event'].sum()
    total_non_event = grouped['non_event'].sum()
    grouped['event_rate'] = grouped['event'] / total_event
    grouped['non_event_rate'] = grouped['non_event'] / total_non_event
    grouped['woe'] = np.log(grouped['event_rate'] / grouped['non_event_rate'])
    grouped['iv'] = (grouped['event_rate'] - grouped['non_event_rate']) * grouped['woe']
    return grouped['iv'].sum()

4.3 相关性剪枝

剔除IV筛选后,特征之间仍可能存在高度相关(如 Pearson |r| > 0.7),导致多重共线性。剪枝策略:

  1. 计算特征相关矩阵,通常取绝对值。
  2. 对每一对高相关特征,保留 IV 较高(或业务重要性更高)的一方。
  3. 迭代直到无高相关对。
# 相关性剪枝示意:保留IV较大的特征
def prune_corr(x, y, threshold=0.7):
    import pandas as pd
    iv_scores = {col: calc_iv(x[col], y) for col in x.columns}
    corr_matrix = x.corr().abs()
    upper_tri = corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(bool))
    to_drop = set()
    for col in upper_tri.columns:
        high_corr = upper_tri[upper_tri[col] > threshold].index.tolist()
        for hc in high_corr:
            if iv_scores[col] < iv_scores[hc]:
                to_drop.add(col)
            else:
                to_drop.add(hc)
    return x.drop(columns=list(to_drop))

4.4 LASSO正则化

LASSO (L1) 通过在损失函数中加入权重绝对值之和的惩罚项,自动将不重要变量的系数压缩为零。关键参数 λ(或 sklearn 中的 C 的倒数)控制稀疏度。通常通过交叉验证选择最优 λ。LASSO 适用于高维稀疏场景,但若特征间高度相关,它可能随机选择一组。

# 使用 sklearn LogisticRegression 的 L1 惩罚
from sklearn.linear_model import LogisticRegressionCV
model = LogisticRegressionCV(
    Cs=np.logspace(-3, 2, 20),
    penalty='l1',
    solver='saga',       # 支持 L1 的求解器
    cv=5,
    scoring='roc_auc',
    max_iter=2000,
    random_state=42
)
model.fit(X_train, y_train)
selected = X_train.columns[model.coef_.flatten() != 0].tolist()
print(f"LASSO 保留特征数: {len(selected)}")

4.5 前向/后向选择

逐步回归的贪心版:

  • 前向选择:从空集开始,每一步加入使 AIC/BIC 或 AUC 提升最大的特征,直到无显著改善。
  • 后向选择:从全特征开始,每一步剔除重要性最弱的特征。
  • 双向选择:结合两者,每次操作后可重新评估已选/已剔变量。

受限于计算量,当特征数 > 50 时推荐先使用前向或与 LASSO 结合。

# 前向选择示例(基于 AUC 增量)
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score

def forward_selection(X, y, max_features=10):
    selected = []
    remaining = list(X.columns)
    best_score = 0
    while len(selected) < max_features and remaining:
        scores = {}
        for col in remaining:
            cols_test = selected + [col]
            m = LogisticRegression(max_iter=1000)
            m.fit(X[cols_test], y)
            scores[col] = roc_auc_score(y, m.predict_proba(X[cols_test])[:,1])
        best_col = max(scores, key=scores.get)
        if scores[best_col] > best_score:
            best_score = scores[best_col]
            selected.append(best_col)
            remaining.remove(best_col)
        else:
            break
    return selected

4.6 方法对比与选择策略

方法核心原理适用场景输出形式计算代价
IV 筛选单变量条件熵大样本、低基数变量IV 值排序列表低
相关性剪枝线性相关系数任意规模,减少多重共线性剔除高相关对中
LASSO 正则化L1 惩罚高维(p > n)、稀疏解非零系数集合中–高(需CV)
前向/后向选择贪心逐步搜索特征 < 50,需要可解释性有序特征列表高(尤其后向)
常见误区: 不要将 IV 筛选和相关性剪枝顺序颠倒。先做 IV 剔除弱变量,再做冗余剪枝,可减少后续 LASSO/逐步选择的搜索空间,同时避免“弱但独立”的特征被误删。

4.7 调试与评估

  • IV 稳定性:在训练集和 OOT 样本上分别计算 IV,若差异 > 20%,说明变量分布不稳定,考虑剔除。
  • LASSO 路径图:绘制不同 λ 下系数变化曲线,帮助理解哪些变量率先被压缩至零。
  • 交叉验证 AUC:每次特征选择迭代后,使用简单模型(如 Logistic Regression)评估交叉验证 AUC,防止过拟合。
  • 特征稳定性指数(PSI):对最终选择的特征集计算 PSI,检查整体分布漂移。

4.8 常见性能瓶颈与稳定性提升技巧

  • 瓶颈1: IV 分箱过多导致过拟合。解决方法:限制最小箱数(min_samples=20),或使用单调分箱。
  • 瓶颈2: LASSO 在强相关特征组中不稳定。使用 group lasso 或先做相关性剪枝。
  • 瓶颈3: 前向选择耗时且易过拟合。可在每步加入特征后执行 5 折 CV,而不是使用训练集 AUC。
  • 稳定性技巧: 对原始特征做多次随机抽样,重复执行特征选择,保留出现频率 > 80% 的特征(Bootstrap 聚合)。
# 稳定性特征选择示例:Bootstrap 筛选 50 次
from sklearn.utils import resample

stable_features = {}
for i in range(50):
    X_boot, y_boot = resample(X_train, y_train, random_state=i)
    sel = forward_selection(X_boot, y_boot, max_features=15)
    for f in sel:
        stable_features[f] = stable_features.get(f, 0) + 1
final_features = [f for f, cnt in stable_features.items() if cnt >= 40]   # 80% 标准
print(f"稳定特征: {final_features}")

4.9 本章小结

特征选择绝非一次性操作。推荐的标准流程为:IV筛选 → 相关性剪枝 → LASSO → 前向/后向精炼。每一步都应辅以业务验算和交叉验证,确保选出的特征既有统计显著性又有业务可解释性。通过本章的方法,可将原始上百维特征压缩至 10–30 维核心变量,显著提升模型鲁棒性与迭代效率。