Day 4: 特征工程与模型评估——数据驱动的核心

写在前面:机器学习界有一句至理名言:“数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。” 今天我们暂时放下复杂的算法模型,回归数据本身。我们将深入探讨如何从原始数据中提炼出金子般的特征(特征工程),以及如何用科学严谨的方法来衡量模型的好坏(模型评估)。这往往是决定一个项目成败的关键细节。


目录

  1. 特征工程:数据决定上限
  2. 特征选择:做减法的艺术
  3. 特征变换:让数据更适合模型
  4. 模型评估:一把尺子量万物
  5. 调优策略:寻找最优解
  6. 总结与实战代码

1. 特征工程:数据决定上限

特征工程(Feature Engineering)是将原始数据转换为更能代表预测模型潜在问题的特征的过程。它主要包含三个子板快:

  • 特征构建:从原始数据中挖掘新特征(如从"时间戳"提取"是否周末")。
  • 特征提取/变换:改变数据的表示形式(如标准化、归一化)。
  • 特征选择:从特征集合中挑选出最有用的特征子集。

2. 特征选择:做减法的艺术

并非特征越多越好。冗余特征会增加计算负担,甚至引入噪声导致过拟合。特征选择主要有三种套路:

2.1 过滤法 (Filter)

按照发散性或相关性对各个特征进行评分,设定阈值或者选择Top K。独立于后续的机器学习模型。

  • 方差选择法:剔除方差很小的特征(几乎不变的特征)。
  • 相关系数法:计算特征与目标变量的皮尔逊相关系数。
  • 卡方检验:主要用于定性特征,检验特征与Target是否独立。
  • 互信息法:从信息论角度衡量特征与Target的相关性。

2.2 包裹法 (Wrapper)

把特征选择看作一个搜索问题,根据预测效果评分。

  • 递归特征消除 (RFE):使用一个基模型(如SVM或逻辑回归)进行多轮训练,每轮训练后剔除权值最小的特征,直到达到指定数量。
    • 优点:考虑了特征间的交互。
    • 缺点:计算量大。

2.3 嵌入法 (Embedded)

特征选择过程与模型训练过程融合,在训练过程中自动进行特征选择。

  • L1正则化 (Lasso):L1正则化倾向于使权重变为0,从而实现稀疏化,天然具有特征选择功能。
  • 树模型的特征重要性:随机森林、XGBoost等模型训练完后,可以直接输出 Feature Importance。

3. 特征变换:让数据更适合模型

3.1 无量纲化

不同特征的量纲(单位)可能差异巨大(如身高cm和体重kg,或者房价和房间数)。这会影响距离计算(KNN、K-Means)和梯度下降的收敛速度。

方法 公式 适用场景
归一化 (Min-Max) x′=x−minmax−minx' = \frac{x - min}{max - min}x=maxminxmin 数据分布有明显边界,对异常值敏感。
标准化 (Z-Score) x′=x−μσx' = \frac{x - \mu}{\sigma}x=σxμ 数据分布近似高斯分布,对异常值不敏感,最常用。

3.2 离散化与分箱

将连续变量变成离散变量(如年龄 -> 年龄段)。

  • 作用:增加模型非线性能力(对线性模型尤其重要),增强鲁棒性(减少异常值影响)。
  • 方法:等宽分箱、等频分箱、卡方分箱(基于统计学)。

3.3 类别特征编码

计算机只认识数字。

  • One-Hot Encoding (独热编码)
    • 适用于类别数较少的情况(如性别、星期)。
    • 缺点:类别多时会造成维度灾难,特征稀疏。
  • Label Encoding (标签编码)
    • 直接赋予 0, 1, 2…
    • 缺点:引入了本来不存在的顺序关系(如 红色=0, 蓝色=1, 绿色=2,模型会误以为 绿色 > 红色)。适用于树模型(树模型不敏感)。
  • Target Encoding (目标编码)
    • 原理:用该类别对应的 Target 均值来替换类别。
    • 案例:假设预测用户是否点击广告(1=点击,0=未点),特征是"城市"。
      • 训练集中有3条记录是"北京",Target分别是 1, 0, 1。
      • 那么"北京"的编码值就是 (1+0+1)/3 = 0.66。
      • 这样就把类别特征变成了连续的数值特征。
    • 风险:在训练集上计算时容易导致数据泄露 (Data Leakage),造成过拟合(比如某个城市只有1条记录且点击了,编码就是1.0,模型会认为这个城市必定点击)。通常需要配合 K-Fold 计算(用其他折的数据算当前折的编码值)或加入平滑项 (Smoothing)。

4. 模型评估:一把尺子量万物

4.1 评估指标体系

分类问题 (Classification)
  • 准确率 (Accuracy):预测对的 / 总数。样本不平衡时失效(如99%正样本,全猜正也有99%准确率)。
  • 精确率 (Precision) 与 召回率 (Recall)
    • Precision = TP / (TP + FP) (查准率:预测为正的里面,多少是真的正)
    • Recall = TP / (TP + FN) (查全率:真的正里面,被找出来多少)
  • F1-Score:P和R的调和平均数,综合衡量。
  • AUC-ROC
    • ROC曲线:以 FPR (False Positive Rate) 为横轴,TPR (True Positive Rate) 为纵轴。
      • TPR (Recall)TPR=TPTP+FNTPR = \frac{TP}{TP + FN}TPR=TP+FNTP。在所有真实为正的样本中,模型找出了多少?
      • FPRFPR=FPFP+TNFPR = \frac{FP}{FP + TN}FPR=FP+TNFP。在所有真实为负的样本中,模型误判了多少为正?
    • AUC (Area Under Curve):ROC曲线下的面积(取值0.5~1.0)。
    • 物理意义:随机抽取一个正样本和一个负样本,模型预测正样本得分 > 负样本得分的概率。
    • 优点对样本不平衡不敏感。在广告点击率预估等正负样本比例极度失衡(如1:1000)的场景下,Accuracy早已失效(全猜0就有99.9%准确率),而AUC依然能客观反映模型排序能力。
回归问题 (Regression)
  • MSE (均方误差)(y−y^)2(y - \hat{y})^2(yy^)2 的均值。对异常值敏感。
  • RMSE (均方根误差):MSE开根号,量纲与原数据一致。
  • MAE (平均绝对误差)∣y−y^∣|y - \hat{y}|yy^ 的均值。对异常值更鲁棒。
  • R2R^2R2 Score (决定系数)
    • 公式R2=1−∑(yi−y^i)2∑(yi−yˉ)2=1−模型预测误差基准模型(猜均值)误差R^2 = 1 - \frac{\sum (y_i - \hat{y}_i)^2}{\sum (y_i - \bar{y})^2} = 1 - \frac{\text{模型预测误差}}{\text{基准模型(猜均值)误差}}R2=1(yiyˉ)2(yiy^i)2=1基准模型(猜均值)误差模型预测误差
    • 含义:衡量模型比"瞎猜均值"好多少。
      • R2=1R^2 = 1R2=1:完美预测。
      • R2=0R^2 = 0R2=0:模型效果等同于直接用均值预测。
      • R2<0R^2 < 0R2<0:模型比瞎猜均值还烂(通常说明模型出大问题了)。

4.2 交叉验证 (Cross Validation)

不要把鸡蛋放在一个篮子里。只切分一次 Train/Test 可能存在偶然性。

  • K-Fold:将数据分为K份,轮流做验证集。
  • Stratified K-Fold (分层K折):保证每折中各类别的比例与原始数据一致(分类任务必备)。

5. 调优策略:寻找最优解

模型的效果很大程度上取决于超参数(Hyperparameters)。

  • 网格搜索 (Grid Search):穷举所有参数组合。慢,但能找到全局最优(在搜索空间内)。
  • 随机搜索 (Random Search):在参数空间随机采样。通常比网格搜索快,效果也不差。
  • 贝叶斯优化 (Bayesian Optimization):智能搜索,利用之前的搜索结果来指导下一次搜索(如 Hyperopt, Optuna)。

6. 总结与实战代码

Python 实战示例

下面演示一个完整的流程:特征预处理 -> 特征选择 -> 模型训练 -> 交叉验证评估。

import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, StratifiedKFold, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression, Lasso
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import roc_auc_score, classification_report
from sklearn.pipeline import Pipeline

# 1. 加载数据
data = load_breast_cancer()
X, y = data.data, data.target
feature_names = data.feature_names

print(f"原始特征维度: {X.shape}")

# 2. 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# 3. 构建 Pipeline
# 步骤: 标准化 -> 特征选择(基于L1正则化的逻辑回归) -> 分类器(随机森林)
# 注意:特征选择应该在标准化之后,否则L1正则化不公平
pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('feature_selection', SelectFromModel(LogisticRegression(penalty='l1', solver='liblinear', C=0.1))),
    ('classifier', RandomForestClassifier(n_estimators=100, random_state=42))
])

# 4. 训练模型
pipeline.fit(X_train, y_train)

# 查看被选中的特征
support = pipeline.named_steps['feature_selection'].get_support()
selected_features = feature_names[support]
print(f"被选中的特征数量: {len(selected_features)}")
print(f"部分选中特征: {selected_features[:5]}")

# 5. 模型评估 (Test Set)
y_pred_proba = pipeline.predict_proba(X_test)[:, 1]
y_pred = pipeline.predict(X_test)

auc = roc_auc_score(y_test, y_pred_proba)
print(f"\nTest AUC: {auc:.4f}")
print("\nClassification Report:")
print(classification_report(y_test, y_pred))

# 6. 交叉验证 (更为稳健的评估)
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
cv_scores = cross_val_score(pipeline, X, y, cv=cv, scoring='roc_auc')

print(f"5-Fold CV AUC: {cv_scores.mean():.4f} (+/- {cv_scores.std() * 2:.4f})")

核心总结

  1. 特征处理是基础:数值型要做标准化,类别型要做One-Hot或Target Encoding。
  2. 特征选择防过拟合:Filter法快,Wrapper法准,Embedded法性价比高。
  3. AUC是王道:在工业界二分类场景,AUC通常是最核心指标。
  4. 严谨评估:一定要用分层交叉验证(Stratified K-Fold)来评估模型性能。
Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐