跳到主要内容

Scikit-learn 回归算法

回归是监督学习的重要任务,用于预测连续数值型目标变量。与分类问题预测离散类别不同,回归关注的是预测具体的数值。

回归问题概述

回归的目标是预测连续值:

  • 简单线性回归:预测单个数值(如房价预测)
  • 多元回归:使用多个特征预测(如基于面积、房间数预测房价)
  • 多项式回归:捕捉非线性关系

线性回归

1. 普通最小二乘法(OLS)

线性回归是最基础的回归方法,它试图找到一条直线(或超平面)使得预测值与真实值之间的误差平方和最小。

数学原理

线性回归要最小化以下目标函数:

minwXwy22\min_{w} || X w - y||_2^2

其中 ww 是系数向量,XX 是特征矩阵,yy 是目标变量。

为什么是最小二乘法?

最小二乘法选择使残差平方和最小的直线。从统计角度看,当误差服从均值为零的正态分布时,最小二乘估计是最优的(最大似然估计)。

from sklearn.linear_model import LinearRegression
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np

# 生成回归数据
X, y = make_regression(
n_samples=200,
n_features=1,
noise=10,
random_state=42
)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)

# 创建并训练模型
model = LinearRegression()
model.fit(X_train, y_train)

# 预测
y_pred = model.predict(X_test)

# 评估
print(f"斜率 (系数): {model.coef_[0]:.4f}")
print(f"截距: {model.intercept_:.4f}")
print(f"R² 分数: {r2_score(y_test, y_pred):.4f}")
print(f"均方误差: {mean_squared_error(y_test, y_pred):.4f}")

参数说明

  • fit_intercept:是否计算截距,默认为 True
  • copy_X:是否复制 X,默认为 True
  • n_jobs:用于计算的 CPU 核心数

2. 岭回归(Ridge Regression)

岭回归在普通线性回归的基础上添加了 L2 正则化项,用于处理多重共线性问题和防止过拟合。

数学原理

minwXwy22+αw22\min_{w} || X w - y||_2^2 + \alpha ||w||_2^2

其中 α\alpha 是正则化参数,控制系数收缩的程度。

为什么要用岭回归?

  1. 处理多重共线性:当特征之间高度相关时,普通线性回归的系数会变得不稳定
  2. 防止过拟合:正则化项会惩罚大的系数,使模型更简单
  3. 处理特征数多于样本数的情况:普通线性回归在这种情况下无法求解
from sklearn.linear_model import Ridge

# 创建岭回归模型
ridge = Ridge(alpha=1.0)
ridge.fit(X_train, y_train)

# 预测和评估
y_pred = ridge.predict(X_test)
print(f"R² 分数: {r2_score(y_test, y_pred):.4f}")

参数说明

  • alpha:正则化强度,必须是非负浮点数,值越大,正则化越强
  • solver:求解方法,可选 'auto', 'svd', 'cholesky', 'lsqr', 'sparse_cg', 'sag', 'saga'

3. Lasso 回归

Lasso(Least Absolute Shrinkage and Selection Operator)使用 L1 正则化,它的一个重要特性是可以将一些系数压缩为零,从而实现特征选择。

数学原理

minw12nsamplesXwy22+αw1\min_{w} \frac{1}{2n_{samples}} ||X w - y||_2^2 + \alpha ||w||_1

Lasso 的独特优势

  1. 特征选择:自动将不重要的特征系数变为零
  2. 稀疏性:产生的模型更稀疏,便于解释
  3. 处理高维数据:在特征数多于样本数时依然有效
from sklearn.linear_model import Lasso

# 创建 Lasso 模型
lasso = Lasso(alpha=0.1)
lasso.fit(X_train, y_train)

# 预测和评估
y_pred = lasso.predict(X_test)
print(f"R² 分数: {r2_score(y_test, y_pred):.4f}")
print(f"非零系数数量: {np.sum(lasso.coef_ != 0)}")

4. 弹性网络(ElasticNet)

弹性网络结合了 L1 和 L2 正则化,兼顾 Lasso 的特征选择能力和 Ridge 的稳定性。

数学原理

minw12nsamplesXwy22+αρw1+α(1ρ)2w22\min_{w} \frac{1}{2n_{samples}} ||X w - y||_2^2 + \alpha \rho ||w||_1 + \frac{\alpha(1-\rho)}{2} ||w||_2^2

其中 ρ\rho 是 l1_ratio 参数,控制 L1 和 L2 的混合比例。

from sklearn.linear_model import ElasticNet

# 创建弹性网络模型
elastic = ElasticNet(alpha=0.1, l1_ratio=0.5)
elastic.fit(X_train, y_train)

y_pred = elastic.predict(X_test)
print(f"R² 分数: {r2_score(y_test, y_pred):.4f}")

非线性回归

1. 多项式回归

当数据呈现非线性关系时,可以使用多项式回归来拟合。

from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
import numpy as np

# 创建一个非线性数据集
X = np.sort(np.random.rand(50, 1) * 5, axis=0)
y = np.sin(X).ravel() + np.random.normal(0, 0.1, X.shape[0])

# 创建多项式回归管道
poly_model = Pipeline([
('poly', PolynomialFeatures(degree=3)),
('linear', LinearRegression())
])

poly_model.fit(X, y)
y_pred = poly_model.predict(X)

print(f"R² 分数: {r2_score(y, y_pred):.4f}")

2. 核岭回归(Kernel Ridge Regression)

核岭回归结合了岭回归和核技巧,可以处理非线性问题。

from sklearn.kernel_ridge import KernelRidge

# 使用 RBF 核
krr = KernelRidge(alpha=1.0, kernel='rbf', gamma=0.1)
krr.fit(X_train, y_train)

y_pred = krr.predict(X_test)
print(f"R² 分数: {r2_score(y_test, y_pred):.4f}")

决策树回归

决策树

决策树可以用于回归任务,通过划分特征空间来预测连续值。

from sklearn.tree import DecisionTreeRegressor

# 创建决策树回归模型
tree = DecisionTreeRegressor(max_depth=5, random_state=42)
tree.fit(X_train, y_train)

y_pred = tree.predict(X_test)
print(f"R² 分数: {r2_score(y_test, y_pred):.4f}")

参数说明

  • max_depth:树的最大深度
  • min_samples_split:节点分裂所需的最小样本数
  • min_samples_leaf:叶节点的最小样本数

随机森林回归

随机森林是集成多棵决策树的回归模型,通常能提供更好的预测性能。

from sklearn.ensemble import RandomForestRegressor

# 创建随机森林回归模型
rf = RandomForestRegressor(
n_estimators=100,
max_depth=10,
random_state=42
)
rf.fit(X_train, y_train)

y_pred = rf.predict(X_test)
print(f"R² 分数: {r2_score(y_test, y_pred):.4f}")

# 查看特征重要性
print("特征重要性:", rf.feature_importances_)

梯度提升回归(Gradient Boosting)

梯度提升是一种强大的集成方法,通过逐步训练弱学习器来减少残差。

from sklearn.ensemble import GradientBoostingRegressor

# 创建梯度提升回归模型
gb = GradientBoostingRegressor(
n_estimators=100,
learning_rate=0.1,
max_depth=5,
random_state=42
)
gb.fit(X_train, y_train)

y_pred = gb.predict(X_test)
print(f"R² 分数: {r2_score(y_test, y_pred):.4f}")

模型评估指标

回归问题有多种评估指标:

1. 均方误差(MSE)

MSE=1ni=1n(yiy^i)2\text{MSE} = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2

from sklearn.metrics import mean_squared_error

mse = mean_squared_error(y_test, y_pred)
print(f"均方误差: {mse:.4f}")

2. 均方根误差(RMSE)

RMSE 是 MSE 的平方根,与目标变量的单位相同,更容易解释。

import numpy as np
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
print(f"均方根误差: {rmse:.4f}")

3. 决定系数(R²)

R² 表示模型解释目标变量方差的比例,取值范围通常是 0 到 1。

R2=1i=1n(yiy^i)2i=1n(yiyˉ)2R^2 = 1 - \frac{\sum_{i=1}^{n}(y_i - \hat{y}_i)^2}{\sum_{i=1}^{n}(y_i - \bar{y})^2}

from sklearn.metrics import r2_score

r2 = r2_score(y_test, y_pred)
print(f"R² 分数: {r2:.4f}")

4. 平均绝对误差(MAE)

MAE=1ni=1nyiy^i\text{MAE} = \frac{1}{n}\sum_{i=1}^{n}|y_i - \hat{y}_i|

from sklearn.metrics import mean_absolute_error

mae = mean_absolute_error(y_test, y_pred)
print(f"平均绝对误差: {mae:.4f}")

完整示例:房价预测

from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.metrics import mean_squared_error, r2_score
import pandas as pd

# 加载糖尿病数据集
data = load_diabetes()
X = data.data
y = data.target
feature_names = data.feature_names

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

# 特征标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 比较多个模型
models = {
"线性回归": LinearRegression(),
"岭回归": Ridge(alpha=1.0),
"Lasso": Lasso(alpha=0.1),
"随机森林": RandomForestRegressor(n_estimators=100, random_state=42),
"梯度提升": GradientBoostingRegressor(n_estimators=100, random_state=42)
}

results = []
for name, model in models.items():
model.fit(X_train_scaled, y_train)
y_pred = model.predict(X_test_scaled)

mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

# 交叉验证
cv_scores = cross_val_score(
model, X_train_scaled, y_train,
cv=5, scoring='r2'
)

results.append({
"模型": name,
"测试 MSE": mse,
"测试 R²": r2,
"交叉验证 R² (均值)": cv_scores.mean()
})

# 显示结果
df = pd.DataFrame(results)
print(df)

算法选择建议

场景推荐算法
简单基线模型线性回归
特征相关性强岭回归
需要特征选择Lasso
特征既相关又需要选择弹性网络
非线性关系多项式回归、核岭回归
需要可解释性线性回归、决策树
追求预测精度随机森林、梯度提升
大规模数据随机梯度下降(SGDRegressor)

下一步