大家好~
咱们今儿继续和大家聊聊岭回归~
岭回归(Ridge Regression)是一种处理线性回归问题的方法,尤其适用于数据中有高度相关(多重共线性)的自变量的情况。
核心思想是:通过对回归模型中的系数引入一定的约束,来防止模型过度拟合,进而提高预测效果。
在很多初学者的印象中,岭回归要比线性回归难理解多了。
其实,岭回归可以看成是给线性回归“加上了一个惩罚项”。普通的线性回归模型在求解时,只关注数据和模型的误差最小化,导致在处理某些复杂数据时模型容易“记住”训练数据中的噪音或异常值,造成过拟合。岭回归则通过在模型中加入一个额外的“限制”,让模型不要把某些变量的系数估计得太大,从而增加模型的稳健性。
具体做法
假设我们有一个简单的线性回归模型:
其中, 是预测值, 是自变量, 是模型中的系数, 是误差。
普通线性回归的目标是找到一组 值,使得预测值 和真实值之间的误差平方和最小化:
但岭回归在这个目标函数中加入了一个额外的项,这个额外项是系数的平方和。岭回归的目标函数变成了:
其中, 是一个超参数,控制惩罚项的强度。如果 取值很大,那么模型会“更严厉”地限制每个系数的大小;如果 很小,模型就会更接近普通的线性回归。
打个简单的比方
想象你在做一项体育测试,你需要用一些不同的项目(如跑步、跳高、仰卧起坐等)来预测一个人的体能得分。在普通线性回归中,你可能会发现,有些项目(比如跑步速度)对体能得分的影响特别大,而有些项目(比如仰卧起坐次数)可能几乎没什么影响。
普通线性回归可能会让你过分依赖那些影响大的项目,但这些项目有时候并不一定在所有情况下都能可靠预测得分。岭回归就像是在提醒你:“别太过依赖某一个项目,尽量让各个项目的影响均衡一些”。这种方式可以让你的预测更加稳健,不会因为某个项目数据有波动就产生太大的误差。
举个例子
假设你在做房价预测,你的模型中有很多特征(如房屋面积、房间数、所在区域等)。如果这些特征之间有很强的相关性,比如面积和房间数通常是相关的,那么普通的线性回归可能会给这些相关特征很大的权重,导致预测不稳定。
这时候,岭回归就派上用场了。它通过给系数的大小施加限制,防止模型过度依赖那些高度相关的特征,从而使得模型在新数据上表现得更好,也更加稳健。
总结来说,就三点:
岭回归适用于自变量之间有多重共线性的情况。
它通过对系数加上惩罚项,限制系数的大小,避免过拟合。
控制惩罚力度, 越大,模型的复杂度越小。
有了上面的解释,下面,咱们从原理方面详细的和大家说说~
为了更好地解释「岭回归」的公式推导和案例,下面我先从公式推导开始,然后通过一个虚拟的房价预测案例来展示岭回归的效果。
公式推导
假设我们有一个线性回归问题,目标是预测 :
其中:
是 的向量,表示 个样本的目标值; 是 的矩阵,表示 个样本的 个特征; 是 的系数向量; 是误差项。
在线性回归中,目标是通过最小化以下损失函数来求解 :
当自变量 存在多重共线性时,普通最小二乘法 (OLS) 求解的 可能不稳定,系数会变得非常大。这时,岭回归通过在损失函数中增加一个惩罚项来限制系数的大小,损失函数变为:
这个公式表示我们在最小化误差的同时,也希望 的平方和不要太大,其中 是惩罚系数,控制惩罚的强度。当 时,岭回归退化为普通的线性回归;当 增大时,模型会更倾向于缩小系数。
岭回归的解
岭回归的解可以通过解析解求出。普通线性回归的解是:
岭回归的解为:
其中 是单位矩阵, 控制惩罚项的强度。
案例:房价预测
接下来我们构造一个虚拟数据集,模拟房价预测的场景,并通过 Python 代码使用岭回归进行分析,并生成多个数据分析图形。
数据集说明
假设我们有以下房屋特征:
房屋面积(square footage) 卧室数量(number of bedrooms) 楼层高度(floor height) 距离市中心的距离(distance to city center)
目标是预测房价(price)。我们生成虚拟数据集,并进行岭回归建模和数据可视化。
Python 代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge, LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.preprocessing import StandardScaler
# 设置随机种子
np.random.seed(42)
# 生成虚拟数据集
n_samples = 200
square_footage = np.random.normal(1500, 300, n_samples) # 房屋面积
bedrooms = np.random.randint(1, 6, n_samples) # 卧室数量
floor_height = np.random.randint(1, 4, n_samples) # 楼层高度
distance_city = np.random.normal(10, 5, n_samples) # 距离市中心的距离
# 模拟价格:房价主要与房屋面积和卧室数量相关
price = (square_footage * 300 + bedrooms * 50000
- distance_city * 1000 + floor_height * 20000
+ np.random.normal(0, 50000, n_samples)) # 加入噪音
# 创建数据框
data = pd.DataFrame({
'Square Footage': square_footage,
'Bedrooms': bedrooms,
'Floor Height': floor_height,
'Distance to City': distance_city,
'Price': price
})
# 分割数据集
X = data[['Square Footage', 'Bedrooms', 'Floor Height', 'Distance to City']]
y = data['Price']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 标准化数据
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 创建岭回归模型
ridge_model = Ridge(alpha=1.0)
ridge_model.fit(X_train_scaled, y_train)
# 创建普通线性回归模型
linear_model = LinearRegression()
linear_model.fit(X_train_scaled, y_train)
# 预测房价
y_pred_ridge = ridge_model.predict(X_test_scaled)
y_pred_linear = linear_model.predict(X_test_scaled)
# 计算误差
ridge_mse = mean_squared_error(y_test, y_pred_ridge)
linear_mse = mean_squared_error(y_test, y_pred_linear)
print(f"岭回归均方误差: {ridge_mse}")
print(f"普通线性回归均方误差: {linear_mse}")
# 绘图
plt.figure(figsize=(14, 10))
# 图1:岭回归 vs 真实价格
plt.subplot(2, 2, 1)
plt.scatter(y_test, y_pred_ridge, color='blue', label='Ridge Predictions', alpha=0.6)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)
plt.xlabel('True Price')
plt.ylabel('Predicted Price')
plt.title('Ridge Regression: Predicted vs True Prices')
plt.legend()
# 图2:线性回归 vs 真实价格
plt.subplot(2, 2, 2)
plt.scatter(y_test, y_pred_linear, color='green', label='Linear Predictions', alpha=0.6)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)
plt.xlabel('True Price')
plt.ylabel('Predicted Price')
plt.title('Linear Regression: Predicted vs True Prices')
plt.legend()
# 图3:岭回归系数
plt.subplot(2, 2, 3)
coef_ridge = ridge_model.coef_
plt.bar(X.columns, coef_ridge, color='orange')
plt.xlabel('Features')
plt.ylabel('Coefficient')
plt.title('Ridge Regression Coefficients')
# 图4:线性回归系数
plt.subplot(2, 2, 4)
coef_linear = linear_model.coef_
plt.bar(X.columns, coef_linear, color='purple')
plt.xlabel('Features')
plt.ylabel('Coefficient')
plt.title('Linear Regression Coefficients')
plt.tight_layout()
plt.show()
数据生成:通过随机数生成了房屋面积、卧室数量、楼层高度和距离市中心的距离等特征,并通过一个简单的线性关系生成了房价。 模型训练:我们分别使用岭回归和普通线性回归对数据进行建模。 误差计算:比较了岭回归和普通线性回归的均方误差(MSE)。
岭回归的预测值与真实值对比。 普通线性回归的预测值与真实值对比。 岭回归模型的特征系数。 普通线性回归模型的特征系数。
通过整个的理论和最后的案例,我们可以看到岭回归如何通过对系数的约束来防止模型过拟合,并且从特征系数的图中可以发现,岭回归模型的系数比普通线性回归更加平滑、均衡。这表明岭回归在应对自变量高度相关或多重共线性的场景下,更加稳定且具有更好的泛化能力。