机器学习模型ElasticNet弹性网络回归在房价预测中的应用
聊一个关于弹性网络回归的案例:ElasticNet 回归模型在房价预测中的应用。
回归分析是一种常用的监督学习方法,主要用于预测连续型目标变量。线性回归是最基本的回归分析方法,但在处理高维数据或多重共线性问题时,往往效果不佳。因此,正则化技术应运而生。Lasso 回归和 Ridge 回归是两种常用的正则化方法,分别通过 L1 和 L2 正则化来控制模型复杂度。然而,单独使用 L1 或 L2 正则化可能并不能解决所有问题。弹性网络回归(ElasticNet Regression)通过结合 Lasso 和 Ridge 正则化的优势,提供了一个灵活的正则化框架,能够有效应对高维数据和共线性问题。
弹性网络回归原理
弹性网络回归的基本概念
弹性网络回归(ElasticNet Regression)是一种线性回归模型,结合了 Lasso 和 Ridge 回归的正则化方法。其损失函数包含 L1 范数(Lasso)和 L2 范数(Ridge)的惩罚项,这使得它能够处理具有高相关性特征的数据集。
弹性网络回归的损失函数为:

其中:
-
为样本数量; -
为实际值, 为预测值; -
为回归系数; -
和 分别为 Lasso 和 Ridge 的正则化参数。
弹性网络回归结合了两种正则化方法的优点:
-
L1 正则化(Lasso)通过缩减系数可以产生稀疏解,使得一些系数为零,从而实现特征选择; -
L2 正则化(Ridge)通过缩减系数的平方和,减少了模型过拟合的可能性,尤其适用于多重共线性问题。
通过调整 和 ,可以实现两者之间的平衡。
弹性网络回归的优点
-
特征选择和缩减维度:通过 L1 正则化,弹性网络可以自动选择出重要特征,从而简化模型。 -
多重共线性处理:弹性网络能够应对特征高度相关的情况,这在房价预测等实际问题中很常见。 -
提高模型的泛化能力:通过正则化项,减少了模型过拟合的可能性。
案例数据集
本案例中,我们使用虚拟生成的房价数据集进行弹性网络回归的应用。数据集中包含了房屋面积、房龄、卧室数量、浴室数量、距离市中心的距离、学区评分等多个特征,我们的目标是预测房屋的销售价格。
数据集描述:
特征变量(X):
-
house_size
: 房屋面积(平方英尺) -
num_bedrooms
: 卧室数量 -
num_bathrooms
: 浴室数量 -
house_age
: 房龄(年) -
distance_to_city
: 到市中心的距离(英里) -
school_rating
: 学校评分(1-10)
目标变量(y):
-
price
: 房屋价格(美元)
我们将首先生成虚拟数据集,然后使用弹性网络回归模型对数据进行训练和预测,最后通过绘制分析图展示模型效果。
代码实现
数据生成与处理
首先,我们使用 numpy
和 pandas
生成虚拟数据集。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
# 设置随机种子,保证结果可复现
np.random.seed(42)
# 生成虚拟数据集
n_samples = 1000
house_size = np.random.normal(1500, 500, n_samples)
num_bedrooms = np.random.randint(1, 6, n_samples)
num_bathrooms = np.random.randint(1, 4, n_samples)
house_age = np.random.randint(1, 50, n_samples)
distance_to_city = np.random.normal(10, 5, n_samples)
school_rating = np.random.randint(1, 11, n_samples)
# 房价由多个特征加权组合而成,添加噪声
price = (house_size * 300) + (num_bedrooms * 10000) + (num_bathrooms * 5000) + \
(50 - house_age) * 200 + (10 - distance_to_city) * 1500 + \
(school_rating * 10000) + np.random.normal(0, 20000, n_samples)
# 创建数据框
data = pd.DataFrame({
'house_size': house_size,
'num_bedrooms': num_bedrooms,
'num_bathrooms': num_bathrooms,
'house_age': house_age,
'distance_to_city': distance_to_city,
'school_rating': school_rating,
'price': price
})
# 查看前几行数据
print(data.head())
# 分离特征和目标变量
X = data[['house_size', 'num_bedrooms', 'num_bathrooms', 'house_age', 'distance_to_city', 'school_rating']]
y = data['price']
# 拆分训练集和测试集
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)
模型训练与调参
使用 ElasticNet
模型进行训练,并利用网格搜索法调整超参数。
from sklearn.linear_model import ElasticNet
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import mean_squared_error, r2_score
# 定义弹性网络模型
elastic_net = ElasticNet()
# 定义参数网格
param_grid = {
'alpha': [0.1, 0.5, 1, 5, 10],
'l1_ratio': [0.1, 0.3, 0.5, 0.7, 0.9]
}
# 网格搜索
grid_search = GridSearchCV(estimator=elastic_net, param_grid=param_grid, cv=5, scoring='neg_mean_squared_error')
grid_search.fit(X_train_scaled, y_train)
# 最佳参数
best_params = grid_search.best_params_
print("Best parameters: ", best_params)
# 使用最佳参数训练模型
best_model = grid_search.best_estimator_
# 预测
y_pred_train = best_model.predict(X_train_scaled)
y_pred_test = best_model.predict(X_test_scaled)
# 评估模型性能
train_mse = mean_squared_error(y_train, y_pred_train)
test_mse = mean_squared_error(y_test, y_pred_test)
train_r2 = r2_score(y_train, y_pred_train)
test_r2 = r2_score(y_test, y_pred_test)
print(f"Train MSE: {train_mse}, Test MSE: {test_mse}")
print(f"Train R2: {train_r2}, Test R2: {test_r2}")
数据可视化
我们将绘制两个图形:
-
预测值与实际值的散点图,用于评估模型的预测效果。 -
不同正则化参数对模型性能的影响图,用于观察正则化参数的调整对模型的影响。
# 散点图:预测值 vs 实际值
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_pred_test, color='red', label='Predicted Price', alpha=0.6)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], color='blue', label='Ideal Line')
plt.xlabel('Actual Price')
plt.ylabel('Predicted Price')
plt.title('Actual vs Predicted Price')
plt.legend()
plt.grid(True)
plt.show()
# 不同正则化参数对模型性能的影响
alphas = [0.1, 0.5, 1, 5, 10]
l1_ratios = [0.1, 0.3, 0.5, 0.7, 0.9]
train_mse_scores = []
test_mse_scores = []
for alpha in alphas:
for l1_ratio in l1_ratios:
model = ElasticNet(alpha=alpha, l1_ratio=l1_ratio)
model.fit(X_train_scaled, y_train)
y_pred_test = model.predict(X_test_scaled)
test_mse = mean_squared_error(y_test, y_pred_test)
test_mse_scores.append(test_mse)
# 绘制MSE随正则化参数的变化图
plt.figure(figsize=(10, 6))
plt.plot(range(len(test_mse_scores)), test_mse_scores, color='green', marker='o', label='Test MSE')
plt.xlabel('Regularization Parameters (Alpha, L1 Ratio)')
plt.ylabel('Mean Squared Error')
plt.title('Effect of Regularization Parameters on Model Performance')
plt.legend()
plt.grid(True)
plt.show()
散点图分析:从散点图中可以看出,预测的房价与实际房价较为接近,点落在理想直线周围,表明模型在测试集上的表现良好。然而,部分数据点偏离较大,可能是由于特定特征对价格的非线性影响未被完全捕捉。
正则化参数图分析:正则化参数( 和 )对模型性能有显著影响。随着正则化强度的增加,模型的误差先减小后增大,表明适当的正则化有助于提高模型的泛化能力,但过强的正则化会导致欠拟合。
弹性网络通过结合 Lasso 和 Ridge 正则化的优点,能够有效处理特征相关性和过拟合问题。通过模型的训练与调参,验证了正则化参数对模型效果的显著影响。
来源: