Alex_McAvoy

想要成为渔夫的猎手

弹性网络回归

Reference

【概述】

Lasso 回归与 Ridge 回归 中,介绍了 Lasso 回归与岭回归两种正则化的方法

当多个特征存在相关时,Lasso 回归可能只会随机选择其中一个,岭回归则会选择所有的特征

如果将这两种正则化的方法结合起来,就能够集合两种方法的优势,这种正则化后的算法就被称为弹性网络回归(Elastic Net Regression)

【假设形式】

弹性网络回归算法的损失函数结合了 Lasso 回归和岭回归的正则化方法,通过两个参数 $\lambda$ 和 $\rho$ 来控制惩罚项的大小

其最优化目标同样是求损失函数 $J(\boldsymbol{\theta})$ 最小时 $\boldsymbol{\theta}$ 的大小,即:

可以看到,当 $\rho=0$ 时,其损失函数就等同于岭回归的代价函数,当 $\rho=1$ 时,其代价函数就等同于 Lasso 回归的损失函数

如下图所示,展示了 Lasso 回归与弹性网络回归对比,虚线表示 Lasso 回归的十个特征,实线表示弹性网络回归的十个特征,每一个颜色表示一个自变量的权重系数,可以看到,相对 Lasso 回归来说,弹性网络回归保留了 Lasso 回归的特征选择的性质,又兼顾了岭回归的稳定性

与 Lasso 回归相似,弹性网络回归中,损失函数中有绝对值存在,不是处处可导的,无法通过直接求导的方式来直接得到 $\boldsymbol{\theta}$ 的解析解,通常使用坐标下降法(Coordinate Descent)来求解 $\boldsymbol{\theta}$ 的最优解

关于坐标下降法的详细介绍,见:坐标下降法

【skleran 实现】

sklearn 中的波士顿房价数据集为例,实现 Lasso 回归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.linear_model import ElasticNet
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import r2_score

# 特征提取
def deal_data():
boston = load_boston() # sklearn的波士顿房价数据集
df = pd.DataFrame(boston.data, columns=boston.feature_names)
df['result'] = boston.target
data = np.array(df)
return data[:, :-1], data[:, -1]

# 模型训练
def train_model(features, labels):
# 建立弹性网络回归模型,l1_ratio即损失函数中的ρ,l1_ratio=1时,为Lasso回归
model = ElasticNet(l1_ratio=0.7)

# 训练
model.fit(features, labels)
return model

# 模型评估
def estimate_model(y_true, y_pred):
MSE = mean_squared_error(y_true, y_pred)
RMSE = np.sqrt(MSE)
MAE = mean_absolute_error(y_true, y_pred)
R2 = r2_score(y_true, y_pred)
indicators = {"MSE": MSE, "RMSE":RMSE, "MAE":MAE, "R2":R2}
return indicators

# 可视化
def visualization(y_true, y_pred, model):
# 绘图
plt.plot(range(y_true.shape[0]), y_true, "b-")
plt.plot(range(y_true.shape[0]), y_pred, "r-.")
plt.legend(["original value", "predicted value"])
plt.xlabel("samples", fontsize="15")
plt.ylabel("y", fontsize="15")

plt.show()

if __name__ == "__main__":
# 特征提取
x, y = deal_data()

# 简单交叉验证
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3,random_state=0)

# 模型训练
model = train_model(x_train, y_train)

# 预测结果
y_pred = model.predict(x_test) # predict()输入输出均为二维
print("y test:", y_test[:10]) # 测试集y值
print("y pred:", y_pred[:10]) # 预测y值

# 模型评估
indicators = estimate_model(y_test, y_pred)
print("MSE:", indicators["MSE"])
print("RMSE:", indicators["RMSE"])
print("MAE:", indicators["MAE"])
print("R2:", indicators["R2"])

# 可视化
visualization(y_test, y_pred, model)
感谢您对我的支持,让我继续努力分享有用的技术与知识点!