sklearn实现弹性网络回归(Elastic Net)
💥 项目专栏:sklearn实现经典机器学习算法(附代码+原理介绍)
文章目录
- 前言
- 一、Elastic-Net回归算法背景
- 📖 起源与背景
- 🌐 应用领域
- ✨ 特点
- 💡 本篇亮点
- 二、算法原理
- 🧩 基本原理
- 📊 参数估计
- 📈 模型评估
- ⚙️ 优化
- 🧪 模型假设
- 🌐 应用价值
- 三、算法实现
- 3.1 导包
- 3.2 加载数据集
- 3.3 数据预处理
- 3.4 划分训练集、测试集
- 3.5 定义Elastic-Net回归模型
- 3.6 网格搜索
- 3.7 评估指标
- 3.8 结果可视化
- 3.8.1 训练曲线
- 3.8.2 真实值与预测值关系图
- 3.8.3 误差分布图
- 完整源码
前言
🌟 哈喽,亲爱的小伙伴们,你们知道吗?最近我们的粉丝群里有好多小可爱私信问我一些关于决策树、逻辑回归等机器学习的超级有趣的问题呢!🌈 为了让大家更轻松地理解,我决定开一个超可爱的专栏,叫做 用sklearn玩转机器学习,特别适合机器学习的小新手哦!
🍬 在这个专栏里,我们会用sklearn这个超级强大的魔法工具来实现各种闪闪发光的机器学习算法!不用担心难度哦,我会用最简单、最可爱的方式,带领大家一起探索算法的神秘世界!✨
🎈 适合哪些小伙伴加入呢?当然是对机器学习感兴趣的小新手们,还有那些刚开始接触sklearn的可爱宝宝们!我们会一起学习如何用sklearn轻松实现那些看起来好厉害的机器学习算法,让新手小白也能快快乐乐地理解它们哦!
🌸 在这个专栏里,大家可以看到用sklearn实现的机器学习算法,我们不仅仅是理论学习哦,每一篇文章都会附带 完整的代码+超级可爱的原理讲解,让大家在轻松愉快的氛围中一起学习成长呢!🌼 快来加入我们的学习大冒险吧!
🚨 我的项目环境:
- 平台:Windows11
- 语言环境:Python 3.10
- 编译器:Jupyter Lab、PyCharm
- scikit-learn:1.2.1
- Pandas:1.3.5
- Numpy:1.19.3
- Scipy:1.7.3
- Matplotlib:3.1.3
💥 项目专栏:sklearn实现经典机器学习算法(附代码+原理介绍)
一、Elastic-Net回归算法背景
🌟 Elastic-Net回归入门 🌟
在这篇文章中,我们将深入了解Elastic-Net回归——一个在统计学和机器学习领域中广泛应用的高效工具。Elastic-Net回归结合了岭回归和Lasso回归的特点,能够有效处理特征选择和正则化问题,尤其在面对包含多重共线性特征的复杂数据集时表现出色。
📖 起源与背景
- 发展历史:Elastic-Net回归由Zou和Hastie在2005年提出,目的是解决Lasso回归在某些情况下的局限性,特别是在特征数量超过样本数量的情况下。
- 核心理念:Elastic-Net结合了Lasso回归的L1正则化和岭回归的L2正则化,这使得它在进行变量选择的同时,也能处理变量之间的相关性。
🌐 应用领域
- 生物信息学:用于处理高维基因数据,识别重要的生物标记物。
- 金融分析:在资产定价、风险预测等领域发挥作用。
- 数据挖掘:在特征丰富的大型数据集中进行模式识别和预测分析。
- 图像处理:用于图像去噪和特征提取。
✨ 特点
- 特征选择与稀疏性:通过L1正则化实现特征选择,通过L2正则化处理特征间相关性。
- 抗共线性能力:Elastic-Net能够有效处理多重共线性问题,提高模型的稳定性。
- 适应性:能够应对不同规模和类型的数据集,适用于多种应用场景。
虽然Elastic-Net回归在高维数据场景中表现出色,但在选择正则化参数时需要更多的考量,以避免过拟合或欠拟合。
💡 本篇亮点
在本篇文章中,我们将利用Python中的scikit-learn库实现 Elastic-Net Regression。本文不仅深入探讨Elastic-Net的理论基础,还通过一个实际案例帮助初学者理解其应用,并掌握关键的实施步骤,从而在实际问题中有效地应用Elastic-Net回归。
二、算法原理
🌟 Elastic-Net回归:特征选择与正则化的协同优化 🌟
Elastic-Net回归是一种结合了Lasso回归和岭回归优点的强大回归分析工具,非常适用于处理具有多重共线性或者特征数量庞大的数据集。通过同时施加L1和L2类型的正则化,Elastic-Net在特征选择和模型正则化方面表现卓越。
🧩 基本原理
-
核心理念:Elastic-Net回归通过将L1和L2正则化项结合到损失函数中,实现了对模型参数的双重约束。这种结合有助于特征选择并提高模型稳定性,尤其在处理具有多重共线性的数据集时。
其数学表达为:
min β { 1 N ∑ i = 1 N ( y i − β 0 − ∑ j = 1 p β j x i j ) 2 + λ 1 ∑ j = 1 p ∣ β j ∣ + λ 2 ∑ j = 1 p β j 2 } \min_{\beta} \left\{ \frac{1}{N} \sum_{i=1}^N (y_i - \beta_0 - \sum_{j=1}^p \beta_j x_{ij})^2 + \lambda_1 \sum_{j=1}^p |\beta_j| + \lambda_2 \sum_{j=1}^p \beta_j^2 \right\} βmin{N1i=1∑N(yi−β0−j=1∑pβjxij)2+λ1j=1∑p∣βj∣+λ2j=1∑pβj2}
其中, y i y_i yi 是因变量, β 0 , β j \beta_0, \beta_j β0,βj 是模型参数, x i j x_{ij} xij 是自变量, λ 1 \lambda_1 λ1 和 λ 2 \lambda_2 λ2 分别是L1和L2正则化的系数。
📊 参数估计
- 正则化系数:Elastic-Net回归的关键在于平衡L1和L2正则化的比例(通过
λ
1
\lambda_1
λ1 和
λ
2
\lambda_2
λ2控制)。正确的平衡可以在稀疏性和模型稳定性之间找到最佳折中。
📈 模型评估
- 性能评估:使用交叉验证来评估不同正则化参数下的模型性能。
- 路径分析:通过分析不同正则化水平下的系数变化,了解特征对模型的影响。
⚙️ 优化
- 特征标准化:在应用Elastic-Net之前,对特征进行标准化是关键,以确保所有特征在相同的尺度上被评估。
- 参数选择:精确选择L1和L2正则化系数对于优化模型性能至关重要。
🧪 模型假设
- 适用性:适用于连续型因变量的回归分析。
- 假设:假设数据满足线性关系,并能够通过正则化来控制过拟合和模型复杂度。
🌐 应用价值
Elastic-Net回归因其强大的特征选择能力和抗共线性能力,在许多领域都有广泛应用。无论是在金融风险预测,生物统计的基因数据分析,还是在大数据环境下的复杂模式识别,Elastic-Net都展现出其独特的价值和实用性。
三、算法实现
3.1 导包
import warnings import matplotlib.pyplot as plt import numpy as np import seaborn as sns from sklearn.datasets import fetch_california_housing from sklearn.linear_model import ElasticNet from sklearn.metrics import mean_squared_error, r2_score from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.preprocessing import StandardScaler
3.2 加载数据集
这段代码是关于加载回归数据集的,具体来说,它执行了以下几个操作:
-
导入数据集:首先,代码中使用了 fetch_california_housing 函数。这个函数来自于 sklearn.datasets,是 scikit-learn(一个非常流行的Python机器学习库)提供的一种方法,用于获取数据集。
-
加载加利福尼亚房价数据集:fetch_california_housing() 函数调用的结果是加载了一个著名的公共数据集——加利福尼亚房价数据集(California Housing dataset)。这个数据集通常用于回归分析的学习和实践。
-
数据集结构:加载后的数据集被分为两部分:X 和 y。
- X 代表数据集中的特征矩阵。在这个矩阵中,每一行代表一个数据点(在这个场景下是加利福尼亚州的一个区域),每一列代表一个特征(例如,人均收入、房屋年龄等)。
- y 代表目标变量或响应变量,即我们试图通过模型预测的值。在加利福尼亚房价数据集中,y 通常代表房屋的中位数价格。
这段代码的主要目的是准备数据,以便进行后续的数据分析和建模工作。
# 2. 加载回归数据集 housing = fetch_california_housing() X, y = housing.data, housing.target
加利福尼亚房价数据集(California Housing dataset)是一个广泛用于回归分析的公开数据集,特别在机器学习和统计领域中应用广泛。这个数据集的特点和内容包括:
-
数据来源:这个数据集最初来源于1990年美国人口普查。
-
目的:主要用于回归分析任务,尤其是预测房价。
-
数据量:它包含了加利福尼亚州各区域(或街区群)的房屋信息,通常有约20640个样本点。
-
特征:数据集包含多个特征(或属性),通常有8个。这些特征包括:
- MedInc:街区居民的收入中位数。
- HouseAge:房屋年龄的中位数。
- AveRooms:平均房间数目。
- AveBedrms:平均卧室数目。
- Population:街区人口。
- AveOccup:平均房屋占用率。
- Latitude:街区的纬度。
- Longitude:街区的经度。
-
目标变量:数据集的目标变量是每个街区房屋的中位数价格。这是一个连续的数值,通常用于回归分析。
-
应用:这个数据集常被用于测试各种回归模型的性能,包括线性回归、Elastic-Net回归、决策树和神经网络等。
-
挑战:由于其特征的多样性和实际应用背景,这个数据集为预测模型的建立提供了一定的挑战,如如何处理非线性关系、如何解释模型结果等。
总的来说,加利福尼亚房价数据集是理解和实践回归分析的一个经典案例,它提供了丰富的信息来预测房价,并帮助初学者和专业人士理解数据在真实世界中的应用。
3.3 数据预处理
在这段代码中,我们进行了数据预处理的一个关键步骤:特征标准化。标准化是一种使数据符合标准正态分布(即均值为0,方差为1)的技术。这通常是机器学习中的一个重要步骤,因为许多算法的性能在标准化数据上会更好。具体来说,我们使用了 StandardScaler 类从 sklearn.preprocessing 包中。
-
实例化 StandardScaler:首先,我们创建了 StandardScaler 类的一个实例,命名为 scaler。这个实例将用于后续的标准化过程。
-
拟合并转换数据:通过调用 scaler.fit_transform(X),我们对数据集 X 进行了拟合和转换。在这一步中,fit 方法会计算数据集 X 的均值和标准差,然后 transform 方法会使用这些参数将每个特征转换为标准正态分布。换句话说,对于每个特征,算法都会减去其均值并除以其标准差。
这个过程有助于消除不同特征之间的尺度差异,使得模型对于所有特征的敏感度相同。特别是当特征的尺度相差很大时,标准化是非常重要的步骤。
# 3. 数据预处理 # 特征标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X)
3.4 划分训练集、测试集
在这段代码中,我们使用了 train_test_split 函数,这是 sklearn.model_selection 模块中的一个功能,用于将数据集划分为训练集和测试集。这是机器学习项目中的一个关键步骤,目的是确保模型可以在未见过的数据上进行测试,从而评估其泛化能力。
具体来说,train_test_split 接受几个参数:X_scaled 和 y 分别是经过预处理(如标准化)的特征数据和对应的标签。参数 test_size=0.3 指定了测试集应占总数据集的30%,这意味着剩余的70%将用作训练集。最后,random_state=42 确保了每次代码运行时划分的方式都相同,这有助于实验的可重复性。通过这种方式,我们可以确保模型在训练时有足够的数据,并且在测试时有代表性的数据来验证模型性能。
# 5. 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.3, random_state=42)
3.5 定义Elastic-Net回归模型
这段代码中的 model = ElasticNet() 是在使用Python的scikit-learn库来定义一个Elastic Net回归模型的实例。在这里,ElasticNet() 是scikit-learn中的一个类,它实现了Elastic Net算法,这是一种同时使用L1和L2正则化来优化回归模型的方法。
具体来说,Elastic Net回归是一种线性回归方法,它结合了两种类型的正则化技术:Lasso回归的L1正则化和Ridge回归的L2正则化。通过这种结合,Elastic Net旨在从两者中获得好处:它可以像Lasso那样进行特征选择(即某些系数可以变成完全的零),同时保持像Ridge那样的正则化特性,这对于处理具有多重共线性的数据集特别有用。
在这段代码中,ElasticNet() 被实例化并赋值给变量 model。这意味着 model 现在表示一个Elastic Net回归模型,可以用来对数据进行拟合和预测。此时,model 使用的是Elastic Net的默认参数设置,但这些参数(例如正则化强度和L1与L2正则化的混合比率)可以根据需要进行调整以优化模型性能。
# 6. 定义Elastic Net回归模型和参数网格 model = ElasticNet()
以下是以表格形式展示的 sklearn 中 ElasticNet 类的常用参数,包括参数名称、描述以及可选的值或类型:
参数 描述 可选的值/类型 alpha 控制模型的正则化强度,较大的值表示更强的正则化,有助于减少过拟合风险。 正浮点数 l1_ratio L1和L2正则化之间的平衡,0表示纯L2正则化,1表示纯L1正则化。 0 到 1之间的浮点数 fit_intercept 是否计算该模型的截距。如果设置为False,则不会在计算中使用截距。 布尔值 max_iter 算法求解的最大迭代次数。 正整数 tol 解的精度(求解器停止的标准)。 正浮点数 selection 更新系数时使用的方法。 ‘cyclic’, ‘random’ random_state 当selection使用’random’时,用于随机数生成器的种子。 整数或 None warm_start 设置为True时,重用上一次调用的解作为初始化,否则就擦除之前的解。 布尔值 positive 设置为True时,强制系数为正。 布尔值 Elastic-Net回归结合了Lasso回归的L1正则化和Ridge回归的L2正则化,旨在克服两者各自的局限性。通过调整alpha值和l1_ratio,可以在特征选择(L1正则化)和模型稳定性(L2正则化)之间找到最佳平衡。例如,较大的alpha值和接近1的l1_ratio有利于特征选择,而较小的alpha值和接近0的l1_ratio则增强了模型的稳定性。选择合适的参数对于优化Elastic-Net回归模型在特定数据集上的性能非常关键。
3.6 网格搜索
上述代码段展示了如何使用网格搜索(GridSearchCV)来优化Elastic Net回归模型的参数。首先,定义了一个参数网格 param_grid,其中包括两个关键参数:alpha 和 l1_ratio。alpha 参数控制了正则化的强度,而 l1_ratio 决定了L1和L2正则化之间的比例。为这两个参数提供了多个候选值:alpha 有五个候选值(0.001, 0.01, 0.1, 1, 10),而 l1_ratio 有三个候选值(0.2, 0.5, 0.8)。
接着,使用 GridSearchCV 对象进行网格搜索,该对象采用Elastic Net模型(model),上述定义的参数网格(param_grid),以及5折交叉验证(cv=5)。return_train_score=True 表明在搜索过程中,训练得分也会被计算并返回,这有助于更全面地评估模型性能。
通过执行 grid_search.fit(X_train, y_train),网格搜索在训练数据上运行,试图找到最优化的参数组合。搜索完成后,通过 grid_search.best_params_ 打印出最佳参数组合,并通过 grid_search.best_estimator_ 获取最佳模型实例 best_model。这意味着得到的 best_model 已经根据提供的数据和参数范围调整到最佳状态,可以用于后续的预测或分析工作。
简而言之,这段代码通过网格搜索和交叉验证的方法,为Elastic Net回归模型精细调整了参数,以期获得最佳的模型性能。
param_grid = { 'alpha': [0.001, 0.01, 0.1, 1, 10], # 正则化强度 'l1_ratio': [0.2, 0.5, 0.8] # L1与L2正则化的混合比例,0为L2正则化,1为L1正则化 } # 使用网格搜索,寻找最佳参数(包含训练得分) grid_search = GridSearchCV(model, param_grid, cv=5, return_train_score=True) grid_search.fit(X_train, y_train) # 7. 网格搜索后的最佳参数和模型 print("最佳参数:", grid_search.best_params_) best_model = grid_search.best_estimator_
3.7 评估指标
这段代码的目的是评估Elastic-Net回归模型在训练集和测试集上的性能。具体来说,它执行了以下步骤:
-
预测:首先,使用最佳模型(best_model,即通过网格搜索找到的参数最优化的Elastic-Net回归模型)来预测训练集(X_train)和测试集(X_test)的响应变量。这一步通过调用 predict 方法完成,分别生成 train_predictions 和 test_predictions。
-
计算均方根误差(RMSE):接着,代码使用 mean_squared_error 函数来计算模型预测值和实际值之间的均方误差,再通过取平方根得到均方根误差(RMSE)。RMSE 是回归模型常用的性能指标,它提供了误差的平均大小。对于训练集和测试集分别计算,得到 train_rmse 和 test_rmse。
-
计算决定系数(R² Score):然后,代码计算了决定系数(R² Score),使用 r2_score 函数。决定系数是衡量模型拟合优度的指标,它表示模型对数据变异性的解释程度。值越接近1,表示模型解释的变异性越多,拟合效果越好。同样地,这个指标分别对训练集和测试集计算,得到 train_r2 和 test_r2。
-
打印结果:最后,代码打印了这些评估指标,包括训练集和测试集的 RMSE 和 R² Score。这提供了一个关于模型性能的直观理解,包括模型在训练集上的拟合能力以及在未见数据(测试集)上的泛化能力。
总体而言,这段代码非常重要,因为它帮助我们理解和评估模型的性能,确保模型既没有过拟合(在训练数据上表现过好)也没有欠拟合(在训练数据上表现不足)。
# 8. 单独打印训练集和测试集的模型评估指标 train_predictions = best_model.predict(X_train) test_predictions = best_model.predict(X_test) train_rmse = np.sqrt(mean_squared_error(y_train, train_predictions)) test_rmse = np.sqrt(mean_squared_error(y_test, test_predictions)) train_r2 = r2_score(y_train, train_predictions) test_r2 = r2_score(y_test, test_predictions) print(f"训练集 RMSE: {train_rmse:.4f}, R2: {train_r2:.4f}") print(f"测试集 RMSE: {test_rmse:.4f}, R2: {test_r2:.4f}")
打印结果:
最佳参数: {'alpha': 0.001, 'l1_ratio': 0.8} 训练集 RMSE: 0.7235, R2: 0.6093 测试集 RMSE: 0.7279, R2: 0.5963
通过这些评估指标,我们能够全面了解模型在训练数据和未知数据上的表现,判断模型是否出现了过拟合或欠拟合的现象,并对模型的泛化能力做出判断。这对于理解和改进机器学习模型至关重要。
3.8 结果可视化
之后,我们对结果进行了可视化,例如:训练曲线、真实值与预测值关系图、误差分布图。
3.8.1 训练曲线
这段代码的主要目的是绘制Elastic-Net回归模型在网格搜索过程中的训练曲线。它展示了不同参数组合下模型在训练集和交叉验证测试集上的平均得分。具体步骤如下:
-
获取网格搜索结果:cv_results = grid_search.cv_results_ 这行代码从网格搜索(GridSearchCV)的结果中提取了各项详细信息。cv_results_ 是一个包含了每次训练/验证过程详细结果的字典。
-
提取训练和测试得分:接下来,代码从这个字典中提取了 mean_train_score 和 mean_test_score。这两个值分别表示对于每个参数组合,模型在训练集和交叉验证测试集上的平均得分。这些得分通常用于评估模型的性能。
-
绘制性能曲线:
- 使用 plt.figure 设置图表大小。
- plt.plot 用于绘制曲线,分别为训练得分和测试得分。
- 添加了图表标题(plt.title)、坐标轴标签(plt.xlabel 和 plt.ylabel)以及图例(plt.legend)。
-
展示图表:最后,plt.show() 显示了绘制好的图表。这张图表可以帮助我们直观地理解不同参数组合下模型的表现情况,包括过拟合和欠拟合的趋势。例如,如果训练得分远高于测试得分,可能表明模型过拟合;如果两者都较低,则可能是欠拟合。
总体而言,这段代码非常有用于评估模型在不同参数设置下的性能,以及选择最优的参数组合。通过这种方式,可以更好地理解模型如何在特定的数据集上表现,并据此作出调整。
# 9. 绘制模型的训练曲线 cv_results = grid_search.cv_results_ mean_train_score = cv_results['mean_train_score'] mean_test_score = cv_results['mean_test_score'] plt.figure(figsize=(10, 6)) plt.plot(mean_train_score, label='训练得分') plt.plot(mean_test_score, label='测试得分') plt.title('模型性能曲线') plt.xlabel('参数组合编号') plt.ylabel('得分') plt.legend() plt.show()
3.8.2 真实值与预测值关系图
这段代码用于可视化真实值与预测值之间的关系,它是评估回归模型性能的一个直观方式。具体来说,代码执行了以下几个操作:
-
设置图表大小:plt.figure(figsize=(10, 6)) 设置了绘图的大小,确保图表足够大,以便清晰地展示数据点。
-
绘制散点图:plt.scatter(y_test, test_predictions) 绘制了一个散点图,其中横坐标是测试集的真实值(y_test),纵坐标是模型对测试集的预测值(test_predictions)。这样的散点图有助于直观地观察预测值与真实值的一致性。
-
添加坐标轴标签和标题:
- plt.xlabel('真实值') 和 plt.ylabel('预测值') 分别设置了横轴和纵轴的标签。
- plt.title('真实值 vs 预测值') 添加了图表的标题,表明图表的内容和目的。
-
绘制参考线:plt.plot([y.min(), y.max()], [y.min(), y.max()], 'k--', lw=4) 绘制了一条黑色虚线,这条线表示完美预测的情况,即预测值完全等于真实值。这条线作为参考,可以帮助我们评估预测值偏离真实值的程度。
-
展示图表:最后,plt.show() 显示了绘制好的图表。
通过这个图表,我们可以快速判断模型的预测性能。理想情况下,散点应该紧密地围绕着参考线分布,这表明预测值与真实值非常接近。如果点离线太远,则表明预测误差较大。这种可视化是理解和解释模型预测性能的重要工具。
# 10. 可视化真实值与预测值的关系 plt.figure(figsize=(10, 6)) plt.scatter(y_test, test_predictions) plt.xlabel('真实值') plt.ylabel('预测值') plt.title('真实值 vs 预测值') plt.plot([y.min(), y.max()], [y.min(), y.max()], 'k--', lw=4) plt.show()
3.8.3 误差分布图
这段代码用于绘制模型预测误差的分布图,帮助我们理解模型在预测时的误差特性。具体步骤如下:
-
计算误差:首先,errors = y_test - test_predictions 这行代码计算了测试集的真实值 (y_test) 和模型预测值 (test_predictions) 之间的差异,即预测误差。这个误差反映了模型预测的准确性。
-
设置图表大小:plt.figure(figsize=(10, 6)) 设置了图表的大小,确保图表足够大,以便清晰地展示数据。
-
绘制直方图和核密度估计(KDE):sns.histplot(errors, kde=True) 使用 seaborn 库绘制了误差的直方图,并且加上了核密度估计(KDE)。直方图显示了不同误差值的频率分布,而 KDE 曲线提供了误差分布的平滑估计。
-
添加坐标轴标签和标题:
- plt.xlabel('预测误差') 和 plt.ylabel('频率') 分别设置了横轴和纵轴的标签。
- plt.title('误差分布图') 添加了图表的标题,说明了图表的主要内容。
-
展示图表:plt.show() 显示了绘制好的图表。
通过这个误差分布图,我们可以直观地看到模型预测误差的分布情况。在理想的情况下,误差分布应该接近于正态分布,且集中在零附近。这表示模型的预测通常是准确的,且没有系统性偏差。如果误差分布偏离这种形态,比如长尾或偏斜,那么可能表明模型存在某些系统性问题。这种可视化是评估和改进模型预测性能的重要工具。
# 11. 绘制误差分布图 errors = y_test - test_predictions plt.figure(figsize=(10, 6)) sns.histplot(errors, kde=True) plt.xlabel('预测误差') plt.ylabel('频率') plt.title('误差分布图') plt.show()
完整源码
import warnings import matplotlib.pyplot as plt import numpy as np import seaborn as sns from sklearn.datasets import fetch_california_housing from sklearn.linear_model import ElasticNet from sklearn.metrics import mean_squared_error, r2_score from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.preprocessing import StandardScaler warnings.filterwarnings('ignore') plt.rcParams['font.sans-serif'] = ['KaiTi'] plt.rcParams["axes.unicode_minus"] = False # 1. 导入所需的库 # 已在代码开头导入 # 2. 加载回归数据集 housing = fetch_california_housing() X, y = housing.data, housing.target # 3. 数据预处理 # 特征标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 4. 特征工程 # 在这个例子中,我们直接使用了原始特征,没有进行额外的特征工程 # 5. 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.3, random_state=42) # 6. 定义Elastic Net回归模型和参数网格 model = ElasticNet() param_grid = { 'alpha': [0.001, 0.01, 0.1, 1, 10], # 正则化强度 'l1_ratio': [0.2, 0.5, 0.8] # L1与L2正则化的混合比例,0为L2正则化,1为L1正则化 } # 使用网格搜索,寻找最佳参数(包含训练得分) grid_search = GridSearchCV(model, param_grid, cv=5, return_train_score=True) grid_search.fit(X_train, y_train) # 7. 网格搜索后的最佳参数和模型 print("最佳参数:", grid_search.best_params_) best_model = grid_search.best_estimator_ # 8. 单独打印训练集和测试集的模型评估指标 train_predictions = best_model.predict(X_train) test_predictions = best_model.predict(X_test) train_rmse = np.sqrt(mean_squared_error(y_train, train_predictions)) test_rmse = np.sqrt(mean_squared_error(y_test, test_predictions)) train_r2 = r2_score(y_train, train_predictions) test_r2 = r2_score(y_test, test_predictions) print(f"训练集 RMSE: {train_rmse:.4f}, R2: {train_r2:.4f}") print(f"测试集 RMSE: {test_rmse:.4f}, R2: {test_r2:.4f}") # 9. 绘制模型的训练曲线 cv_results = grid_search.cv_results_ mean_train_score = cv_results['mean_train_score'] mean_test_score = cv_results['mean_test_score'] plt.figure(figsize=(10, 6)) plt.plot(mean_train_score, label='训练得分') plt.plot(mean_test_score, label='测试得分') plt.title('模型性能曲线') plt.xlabel('参数组合编号') plt.ylabel('得分') plt.legend() plt.show() # 10. 可视化真实值与预测值的关系 plt.figure(figsize=(10, 6)) plt.scatter(y_test, test_predictions) plt.xlabel('真实值') plt.ylabel('预测值') plt.title('真实值 vs 预测值') plt.plot([y.min(), y.max()], [y.min(), y.max()], 'k--', lw=4) plt.show() # 11. 绘制误差分布图 errors = y_test - test_predictions plt.figure(figsize=(10, 6)) sns.histplot(errors, kde=True) plt.xlabel('预测误差') plt.ylabel('频率') plt.title('误差分布图') plt.show()
-
-
- 正则化系数:Elastic-Net回归的关键在于平衡L1和L2正则化的比例(通过
λ
1
\lambda_1
λ1 和
λ
2
\lambda_2
λ2控制)。正确的平衡可以在稀疏性和模型稳定性之间找到最佳折中。
-