机器学习基础:从泛化、过拟合到特征工程的实战避坑指南

1次阅读
没有评论

共计 2378 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

从房价预测看泛化能力

假设我们要建立一个预测房价的模型。用历史数据训练后,模型在训练集上误差很低,但实际预测新房子价格时却偏差很大——这就是典型的 泛化能力差。好比学生死记硬背例题却不会举一反三,机器学习模型也需要学会从训练数据中提取通用规律。

机器学习基础:从泛化、过拟合到特征工程的实战避坑指南

过拟合 vs 欠拟合:模型的两难困境

  1. 过拟合(高方差):模型复杂到连训练数据中的噪声都记住了。表现为训练误差极低但测试误差高,就像用显微镜看数据反而看不清全貌。数学上对应模型权重值过大。

  2. 欠拟合(高偏差):模型过于简单,连基本规律都没学会。训练和测试误差都较高,好比用老花眼看数据——模糊一片。

# 可视化示例
import matplotlib.pyplot as plt
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression

# 生成演示数据
X = np.linspace(0, 10, 20)
y = np.sin(X) + np.random.normal(0, 0.2, 20)

# 不同复杂度模型对比
models = [make_pipeline(PolynomialFeatures(1), LinearRegression()),  # 欠拟合
    make_pipeline(PolynomialFeatures(3), LinearRegression()),  # 适中
    make_pipeline(PolynomialFeatures(15), LinearRegression())  # 过拟合
]

plt.figure(figsize=(12, 4))
for i, model in enumerate(models, 1):
    model.fit(X[:, None], y)
    plt.subplot(1, 3, i)
    plt.scatter(X, y, s=20)
    plt.plot(X_test, model.predict(X_test[:, None]), c='r')
    plt.title(f'Degree {model.steps[0][1].degree}')

正则化实战:Ridge 回归示例

通过 L2 正则化(权重衰减)控制过拟合,让模型权重不会变得过大:

from sklearn.linear_model import Ridge

# 带类型注解的工业级实现
def train_ridge(X: np.ndarray, y: np.ndarray, alpha: float = 1.0) -> Ridge:
    """
    :param alpha: 正则化强度,越大表示惩罚越重
    :return: 训练好的 Ridge 模型
    """
    model = Ridge(alpha=alpha)
    model.fit(X, y)
    return model

# 对比不同 alpha 值的影响
alphas = [0, 1, 100]
coefs = []
for a in alphas:
    ridge = train_ridge(X_train, y_train, alpha=a)
    coefs.append(ridge.coef_)

# 绘制权重变化
plt.plot(alphas, coefs)
plt.xscale('log')
plt.xlabel('Alpha (log scale)')
plt.ylabel('Coefficients')

特征工程两大核心技巧

1. One-Hot 编码处理类别特征

直接将字符串类别转为数值会导致模型误判顺序关系:

from sklearn.preprocessing import OneHotEncoder

# 错误示范:直接 LabelEncoder
# encoder = LabelEncoder()  # 会生成 0,1,2... 的伪数值关系

# 正确做法
encoder = OneHotEncoder(sparse=False)
housing_type = encoder.fit_transform(df[['house_type']])

2. 特征缩放提升 SVM 性能

不同量纲的特征会导致距离计算失衡:

from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler

# 注意防止数据泄漏!先拆分再缩放
X_train, X_test = train_test_split(X, test_size=0.2)
scaler = StandardScaler().fit(X_train)  # 只用训练集统计量

svm = SVR(kernel='rbf').fit(scaler.transform(X_train), y_train)
# 测试集同样用训练集的 scaler
y_pred = svm.predict(scaler.transform(X_test))  

生产环境最佳实践

  1. 数据划分:小数据按 6:2:2(训练: 验证: 测试),大数据可调整验证集比例

  2. 早停法实现:监控验证集损失,提前终止训练

from tensorflow.keras.callbacks import EarlyStopping

es = EarlyStopping(
    monitor='val_loss',
    patience=5,  # 允许 5 轮不提升
    restore_best_weights=True
)

model.fit(X_train, y_train,
          validation_data=(X_val, y_val),
          callbacks=[es],
          epochs=100)

思考与进阶

当特征维度(如 1000 维)远大于样本量(如 100 个)时:
– 优先选择L1 正则化(Lasso),因为它会产生稀疏解自动做特征选择
– 此时 L2 正则化会使所有特征都保留微小权重,反而降低可解释性

下次可以试试用 Lasso 回归处理高维基因数据,观察权重矩阵的稀疏性变化!

正文完
 0
评论(没有评论)