第二章: 机器学习与神经网络概述
第四部分:回归算法理论与实践
第一节:线性回归模型
内容:多重共线性、正则化方法(如Lasso和Ridge回归)。
一、线性回归基础回顾
线性回归是预测型建模的经典方法,假设因变量 y 与一组自变量 存在线性关系:
其中:
-
为待估系数
-
ε 为误差项
目标:最小化残差平方和(Ordinary Least Squares,OLS)
【第二章:机器学习与神经网络概述】04.回归算法理论与实践 -(1)线性回归模型-优快云博客
【漫话机器学习系列】061.线性回归参数计算(Finding Linear Regression Parameters)-优快云博客
【机器学习】机器学习的基本分类-监督学习-线性回归(Linear Regression)_线性回归在机器学习里要解决什么问题-优快云博客
二、多重共线性问题(Multicollinearity)
当多个自变量之间存在高度线性相关性时,会导致:
-
系数估计不稳定
-
模型解释性降低
-
预测性能变差
检测方法:
-
相关系数矩阵
-
方差膨胀因子(VIF):若 VIF > 10 通常视为强共线性
三、正则化方法:控制过拟合与共线性
为避免过拟合和共线性,可在损失函数中加入惩罚项,常见方法如下:
1. 岭回归(Ridge Regression)
在 OLS 的基础上加入 L2 正则项:
-
λ:正则化强度(超参数)
-
L2正则会压缩系数,但不会变为零
from sklearn.linear_model import Ridge
ridge = Ridge(alpha=1.0)
ridge.fit(X_train, y_train)
【漫话机器学习系列】154.岭回归(Ridge Regression)-优快云博客
【漫话机器学习系列】082.岭回归(或脊回归)中的α值(alpha in ridge regression)_岭回归的alpha参数-优快云博客
【机器学习】机器学习的基本分类-监督学习-岭回归(Ridge Regression)_岭回归闭式解-优快云博客
2. Lasso 回归(Lasso Regression)
在 OLS 中加入 L1 正则项:
-
L1正则具有稀疏性,可将部分系数压为 0,实现特征选择
from sklearn.linear_model import Lasso
lasso = Lasso(alpha=0.1)
lasso.fit(X_train, y_train)
【机器学习】机器学习的基本分类-监督学习-Lasso 回归(Least Absolute Shrinkage and Selection Operator)_lasso回归 机器学习-优快云博客
【漫话机器学习系列】101.特征选择法之Lasso(Lasso For Feature Selection)_lasso特征选择-优快云博客
3. 弹性网(Elastic Net)
结合 L1 与 L2 正则的优点:
适合特征多且部分相关的情况。
from sklearn.linear_model import ElasticNet
enet = ElasticNet(alpha=0.1, l1_ratio=0.5)
enet.fit(X_train, y_train)
【漫话机器学习系列】046.弹性网络(Elastic Net)-优快云博客
四、线性回归与正则化方法对比
项目 | 普通线性回归 | 岭回归(Ridge) | Lasso 回归 | 弹性网 |
---|---|---|---|---|
正则方式 | 无 | L2 | L1 | L1 + L2 |
抑制共线性 | ❌ | ✅ | ⚠️ 部分有效 | ✅ |
特征选择能力 | ❌ | ❌ | ✅ | ✅ |
稀疏性 | ❌ | ❌ | ✅ | ⚠️ 视参数而定 |
代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import train_test_split
# 1. 构造非线性数据(sin曲线 + 噪声)
np.random.seed(0)
X = np.sort(np.random.rand(40))
y = np.sin(2 * np.pi * X) + np.random.randn(40) * 0.1
X = X.reshape(-1, 1)
# 2. 拆分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 3. 定义三种回归模型:普通线性回归、Ridge、Lasso
degree = 10 # 多项式回归阶数
models = {
"Linear Regression": make_pipeline(PolynomialFeatures(degree), LinearRegression()),
"Ridge (alpha=1)": make_pipeline(PolynomialFeatures(degree), Ridge(alpha=1)),
"Lasso (alpha=0.01)": make_pipeline(PolynomialFeatures(degree), Lasso(alpha=0.01, max_iter=10000))
}
# 4. 可视化
plt.figure(figsize=(10, 6))
x_plot = np.linspace(0, 1, 100).reshape(-1, 1)
# 5. 拟合并绘图
for name, model in models.items():
model.fit(X_train, y_train)
y_plot = model.predict(x_plot)
plt.plot(x_plot, y_plot, label=name)
# 6. 原始数据点
plt.scatter(X, y, color="black", label="Data", s=20)
plt.rcParams['font.sans-serif'] = ['SimHei']
# 解决负号'-'显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
plt.title("模型拟合曲线图:普通线性回归 vs 正则化方法")
plt.xlabel("X")
plt.ylabel("y")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
图示
上图展示了模型拟合效果的对比:
-
普通线性回归(Linear Regression)在高阶多项式下容易产生过拟合,曲线剧烈波动。
-
Ridge回归(L2正则化)在保留部分复杂度的同时抑制了系数过大,使得模型更平滑。
-
Lasso回归(L1正则化)在压缩部分特征系数为0的同时提升了模型的稀疏性,有助于特征选择。
该图直观说明了正则化在控制过拟合方面的优势。
五、Python 示例与模型评估
from sklearn.model_selection import cross_val_score, train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.linear_model import Ridge, Lasso, ElasticNet
from sklearn.datasets import make_regression
# 生成模拟回归数据
X, y = make_regression(n_samples=1000, n_features=10, noise=0.1, random_state=42)
# 划分训练集和测试集(此处仅用训练集做演示)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 初始化和训练Ridge模型
ridge = Ridge(alpha=1.0)
ridge.fit(X_train, y_train)
# 初始化和训练Lasso模型
lasso = Lasso(alpha=0.1)
lasso.fit(X_train, y_train)
# 初始化和训练ElasticNet模型
enet = ElasticNet(alpha=0.1, l1_ratio=0.5)
enet.fit(X_train, y_train)
# 比较模型交叉验证分数
for model in [ridge, lasso, enet]:
scores = cross_val_score(model, X_train, y_train, cv=5, scoring='neg_mean_squared_error')
print(f"{model.__class__.__name__} 平均MSE: {-scores.mean():.4f}")
运行结果
Ridge 平均MSE: 0.0587
Lasso 平均MSE: 0.1149
ElasticNet 平均MSE: 46.9568