机器学习模型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)

  1. house_size: 房屋面积(平方英尺)
  2. num_bedrooms: 卧室数量
  3. num_bathrooms: 浴室数量
  4. house_age: 房龄(年)
  5. distance_to_city: 到市中心的距离(英里)
  6. 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}")

数据可视化

我们将绘制两个图形:

  1. 预测值与实际值的散点图,用于评估模型的预测效果。
  2. 不同正则化参数对模型性能的影响图,用于观察正则化参数的调整对模型的影响。
# 散点图:预测值 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 正则化的优点,能够有效处理特征相关性和过拟合问题。通过模型的训练与调参,验证了正则化参数对模型效果的显著影响。

来源:小白 机器学习实战ML

THE END