找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1378

积分

0

好友

186

主题
发表于 3 天前 | 查看: 8| 回复: 0

在现实世界的机器学习项目中,数据的维度常常很高(例如上百至上千个特征),而样本量可能有限。高维数据会带来一系列挑战:维度灾难导致样本稀疏、模型过拟合风险增加、计算开销庞大,并且会降低模型的可解释性与鲁棒性。因此,特征选择的目标变得至关重要——在保持或提升预测性能的同时,减少特征数目,从而提升模型的稳定性与效率。

形式化定义与优化问题

设数据集为 ( D = {(\mathbf{x}_i, yi)}{i=1}^n ),其中 ( \mathbf{x}_i \in \mathbb{R}^p ) 为 ( p ) 维特征向量,( y_i ) 为响应变量(可以是分类标签或连续值)。我们希望从 ( p ) 个特征中选出一个子集 ( S \subset {1, \dots, p} ),使得基于该子集训练的模型泛化性能最佳。

形式上,这可以表达为一个约束优化问题:

最优化目标(经验风险最小化):
[
\min{\theta, S} \frac{1}{n} \sum{i=1}^n \mathcal{L}(f(\mathbf{x}_i^S; \theta), y_i) + \lambda R(\theta)
]
其中 ( \mathbf{x}_i^S ) 是 ( \mathbf{x}_i ) 在特征子集 ( S ) 上的投影,( \mathcal{L} ) 为损失函数(如分类中的 logistic 损失、回归中的平方损失),( R(\theta) ) 是正则项(如 ( l_1 ) 或 ( l_2 ))。

特征子集大小约束:
[
|S| \leq k
]
或者等价地引入 ( l_0 ) 约束(稀疏性约束):
[
|\theta|_0 \leq k
]

具有 ( l_0 ) 约束的优化问题是 NP 难问题,在一般情况下难以直接高效求解。因此,在工程实践与理论方法中,我们通过以下策略近似求解:

  1. 使用 ( l_1 ) 正则(LASSO)替代 ( l_0 ) 约束,在凸优化框架中获得稀疏解;
  2. 使用贪心搜索(如前进/后退/双向选择等)近似最优子集;
  3. 通过滤波法先筛除无关特征,再在较小候选集上做更复杂的选择;
  4. 使用嵌入式方法,将特征选择融入模型训练(如树模型重要性、稀疏线性模型)。

特征选择的三大类方法

特征选择方法通常分为三大类:

第一,滤波法:不依赖具体学习模型,使用统计准则(如相关系数、互信息、卡方检验、F检验等)对每个特征进行独立评分与筛选。其优点是计算速度快、结果稳健,不易过拟合;缺点是没有考虑特征间的交互作用以及后续模型的结构。

第二,包裹法:将特征选择过程“包裹”在模型训练与评估之中,例如前向选择、后向消除、递归特征消除(RFE)。这类方法通常能获得更好的模型性能,但计算成本高昂,且容易在小数据集上过拟合,必须严格依赖交叉验证。

第三,嵌入法:在模型训练过程中直接产生特征重要性或诱导稀疏性,例如 LASSO/Elastic Net 回归、基于树模型(如随机森林、梯度提升树)的特征重要性。这类方法在性能与效率之间取得了较好的平衡,适合大规模数据集。

此外,还有稳定性选择等方法,通过从重复抽样或子集训练中衡量特征被选择的频率,来控制假阳性风险,提升选择的鲁棒性。这是人工智能算法优化中常用的策略。

滤波法详解

皮尔逊相关系数(适用于回归问题):
对于连续型目标 ( y ) 与连续特征 ( xj ):
[
\rho
{xj, y} = \frac{\sum{i=1}^n (x_{ij} - \bar{x}_j)(yi - \bar{y})}{\sqrt{\sum{i=1}^n (x_{ij} - \bar{x}j)^2 \sum{i=1}^n (y_i - \bar{y})^2}}
]
该值衡量线性关系,绝对值越大说明线性相关越强。

ANOVA F检验(适用于分类问题):
对于分类目标 ( y )(假设有 ( C ) 个类别)与连续特征 ( xj ),单因素方差分析的 F 统计量为:
组间方差 ( SS
{between} = \sum_{c=1}^C n_c (\bar{x}_j^{(c)} - \bar{x}j)^2 )
组内方差 ( SS
{within} = \sum{c=1}^C \sum{i: yi=c} (x{ij} - \bar{x}j^{(c)})^2 )
[
F = \frac{SS
{between} / (C-1)}{SS_{within} / (n-C)}
]
F 统计量越大,说明特征在不同类别间的差异越显著。

互信息:
互信息衡量特征 ( X ) 与目标 ( Y ) 之间的总体依赖关系(包括非线性):
[
I(X; Y) = \sum{x \in \mathcal{X}} \sum{y \in \mathcal{Y}} p(x, y) \log \frac{p(x, y)}{p(x)p(y)}
]
互信息为 0 表示独立,值越大表示依赖越强。对于连续变量,常用核密度估计或 k 近邻法进行估计。

mRMR(最小冗余最大相关):
mRMR 方法试图在最大化特征与目标相关性的同时,最小化特征之间的冗余度。构造的优化目标为:
[
\max_{x_j \in S} \left[ I(xj; y) - \beta \sum{x_k \in S} I(x_j; x_k) \right]
]
其中 ( \beta ) 为权衡参数。由于直接求解复杂,常采用贪心算法进行近似。

包裹法与嵌入法

包裹法:递归特征消除(RFE)
RFE 首先用模型(如逻辑回归、SVM)在所有特征上训练,根据模型提供的特征权重(如系数绝对值)进行排序,移除权重最小的一个或一部分特征,然后在剩余特征上重复此过程,直至达到预设的特征数量。

嵌入法:LASSO 回归
对于回归问题,LASSO 在损失函数中加入 ( l1 ) 正则项:
[
\min
{\theta} \frac{1}{n} \sum_{i=1}^n (y_i - \theta^T \mathbf{x}_i)^2 + \lambda |\theta|_1
]
( l_1 ) 正则项具有诱导稀疏解的性质,使得部分系数恰好为 0,从而实现特征选择。

嵌入法:树模型的特征重要性
随机森林、梯度提升树等模型天然能提供特征重要性评估,常见的有两种:

  1. 基于不纯度下降:计算每个特征在所有树上进行分裂时所带来的不纯度(基尼系数或信息熵)下降总量。
  2. 基于置换:在验证集上随机打乱某一特征的值,观察模型性能(如准确率)的下降程度,下降越多表明该特征越重要。

实战案例:综合数据集的特征选择评估

我们设计一个包含多种特征类型的二分类数据集,并使用多种方法进行特征选择与评估。

数据集构成:

  • 强信号特征:10个,与目标变量有显著线性关系。
  • 非线性交互特征:5个,如特征乘积、平方项,单独看相关性弱,组合后对预测有贡献。
  • 冗余特征:15个,是强信号特征的线性组合或加噪版本。
  • 纯噪声特征:20个,与目标变量无关。
  • 类别型特征:3个,经过 One-Hot 编码后扩展维度。

评估方法:
我们使用Python的Scikit-learn库,对比以下方法:

  1. 滤波法:互信息(MI)、ANOVA F检验。
  2. 嵌入法:L1逻辑回归(诱导稀疏性)、随机森林特征重要性。
  3. 包裹法:带交叉验证的递归特征消除(RFECV)。
  4. 稳定性选择:在多次数据子样本上执行L1逻辑回归,统计特征被选中的频率。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import make_classification
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.feature_selection import mutual_info_classif, f_classif, SelectKBest
from sklearn.feature_selection import RFE, RFECV
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import roc_auc_score
from sklearn.manifold import TSNE
import warnings
warnings.filterwarnings('ignore')

np.random.seed(42)

# 1. 生成复杂数据集
def make_complex_dataset(n_samples=2000, random_state=42):
    # ... (数据生成代码与原文一致)
    return X, y_new

X, y = make_complex_dataset(n_samples=2000, random_state=42)

# 2. 数据预处理:连续特征标准化 + 类别特征One-Hot编码
continuous_cols = [c for c in X.columns if c.startswith('cont_') or c.startswith('nl_') or c.startswith('noise_')]
categorical_cols = [c for c in X.columns if c.startswith('cat_')]

preprocess = ColumnTransformer(
    transformers=[
        ('num', StandardScaler(), continuous_cols),
        ('cat', OneHotEncoder(handle_unknown='ignore', sparse_output=False), categorical_cols)
    ]
)

# 获取预处理后的特征名称
def get_feature_names(preprocess, X):
    preprocess.fit(X)
    num_features = preprocess.named_transformers_['num'].get_feature_names_out(continuous_cols)
    cat_features = preprocess.named_transformers_['cat'].get_feature_names_out(categorical_cols)
    feature_names = np.concatenate([num_features, cat_features])
    return feature_names

feature_names = get_feature_names(preprocess, X)
X_trans = preprocess.fit_transform(X)

# 3. 应用多种特征选择方法并评估
# 计算滤波法分数
mi_scores = mutual_info_classif(X_trans, y, random_state=42)
F_scores, _ = f_classif(X_trans, y)

# 嵌入法:L1逻辑回归
l1_clf = LogisticRegression(penalty='l1', solver='saga', C=0.5, max_iter=2000, random_state=42)
l1_clf.fit(X_trans, y)
l1_coef_abs = np.abs(l1_clf.coef_.ravel())

# 嵌入法:随机森林重要性
rf = RandomForestClassifier(n_estimators=300, random_state=42, n_jobs=-1)
rf.fit(X_trans, y)
rf_importances = rf.feature_importances_

# 包裹法:RFECV
base_lr = LogisticRegression(penalty='l2', solver='lbfgs', C=1.0, max_iter=2000, random_state=42)
rfecv = RFECV(estimator=base_lr, step=1, cv=5, scoring='roc_auc', min_features_to_select=5)
rfecv.fit(X_trans, y)
rfecv_ranking = rfecv.ranking_

# 稳定性选择
def stability_selection(X_trans, y, B=50, subsample_ratio=0.6, C=0.5):
    n, p = X_trans.shape
    freq = np.zeros(p)
    rng = np.random.RandomState(123)
    for b in range(B):
        idx = rng.choice(n, size=int(n*subsample_ratio), replace=False)
        clf = LogisticRegression(penalty='l1', solver='saga', C=C, max_iter=2000, random_state=rng.randint(10000))
        clf.fit(X_trans[idx], y[idx])
        freq += (clf.coef_.ravel() != 0).astype(int)
    return freq / B

stab_freq = stability_selection(X_trans, y)

# 4. 性能评估:绘制AUC随特征数量变化的曲线
def evaluate_auc_curve(X_trans, y, feature_names, ranking_list, k_values, base_model=None):
    if base_model is None:
        base_model = LogisticRegression(penalty='l2', solver='lbfgs', C=1.0, max_iter=1000)
    results = []
    for k in k_values:
        selected = ranking_list[:k]
        mask = np.array([f in selected for f in feature_names])
        X_sel = X_trans[:, mask]
        cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
        auc = cross_val_score(base_model, X_sel, y, cv=cv, scoring='roc_auc').mean()
        results.append((k, auc))
    return pd.DataFrame(results, columns=['k', 'auc'])

# 根据各方法得到的特征重要性进行排序
mi_ranking = [feature_names[i] for i in np.argsort(mi_scores)[::-1]]
l1_ranking = [feature_names[i] for i in np.argsort(l1_coef_abs)[::-1]]
rf_ranking = [feature_names[i] for i in np.argsort(rf_importances)[::-1]]
rfe_ranking = [feature_names[i] for i in np.argsort(rfecv_ranking)]

k_values = list(range(5, min(100, X_trans.shape[1]), 5))
auc_mi = evaluate_auc_curve(X_trans, y, feature_names, mi_ranking, k_values)
auc_l1 = evaluate_auc_curve(X_trans, y, feature_names, l1_ranking, k_values)
auc_rf = evaluate_auc_curve(X_trans, y, feature_names, rf_ranking, k_values)
auc_rfe = evaluate_auc_curve(X_trans, y, feature_names, rfe_ranking, k_values)

# 5. 可视化分析
# ... (可视化代码与原文一致,生成对比柱状图、AUC曲线、稳定性热图、t-SNE图)

可视化分析结果:

1. Filter/Embedded 重要性对比(Top-15特征)
图片
该图展示了互信息(MI)、L1逻辑回归系数绝对值(L1)和随机森林重要性(RF)三种方法对同一组Top-15特征的评分对比(已归一化)。可以检验不同方法在评估特征重要性时的一致性与差异。若某特征在多种方法上均得分靠前,则其预测价值更稳定可靠。

2. 性能-特征数曲线(AUC vs k)
图片
该曲线展示了基于四种不同特征排序方法,随着所选特征数量(k)增加,模型5折交叉验证AUC的变化情况。曲线通常在某个k值达到峰值后趋于平缓或下降,这为选择最佳特征数量提供了直观依据。

3. 稳定性选择频率热图(Top-30特征)
图片
热图展示了在多次数据子样本上,各特征被L1逻辑回归选中的频率。颜色越深表示特征越稳定。通过设定频率阈值(如≥0.6),可以筛选出对数据扰动不敏感的鲁棒性特征,有效降低假阳性风险。

4. t-SNE 可视化(基于L1排名Top-20特征)
图片
此图展示了使用L1方法选出的Top-20个特征,经过t-SNE降维后的数据分布。清晰的类间分离表明所选特征子集具有良好的信息表达能力。

总结与最佳实践

通过本案例的综合分析,我们可以得出以下关于特征选择策略的见解:

  1. 方法特性:滤波法(如MI)能有效捕捉非线性关系但可能保留冗余;嵌入法(如L1)善于得到稀疏的线性解但可能遗漏未显式构造的非线性交互;包裹法(如RFE)性能通常较好但计算成本高;树模型重要性对非线性交互友好。
  2. 组合策略:在实际项目中,推荐采用组合策略:滤波法进行初步快速筛选 → 嵌入法或包裹法进行精细选择 → 稳定性选择进行最终鲁棒性校验
  3. 严格验证:在整个特征选择过程中,必须严格使用交叉验证,并注意防止数据泄露(例如,拟合过程必须在训练折叠内进行)。
  4. 多维度决策:不应只依赖单一指标。应结合性能曲线(AUC vs k)确定最佳特征数量,并利用稳定性分析确保所选特征集合的鲁棒性。
  5. 任务导向:根据具体任务的数据结构(线性/非线性主导、特征类型、冗余程度、样本量)选择最匹配的特征选择方法。



上一篇:Google Jupiter DCN架构解析:Apollo OCS光交换如何重构CLOS网络支撑百万卡AI集群
下一篇:美股AI电力与算力板块周度复盘:产业映射与出海逻辑解析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-24 19:01 , Processed in 0.249486 second(s), 37 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表