Alex_McAvoy

想要成为渔夫的猎手

Lasso 回归与 Ridge 回归

Reference

【概述】

对于线性回归来说,其损失函数的解析解为:

当 $XX^T$ 不是满秩矩阵时,没有逆矩阵,此时会出现过拟合现象,其本质就是自变量 $x^{(j)}$ 之间存在多重共线性(Multicollinearity),即自变量 $x^{(j)}$ 间存在相关关系

对于线性回归中的多重共线性问题,其中一个解决方法就是剔除掉共线的自变量,可以通过计算方差膨胀因子(Variance inflation factor,VIF)来量化自变量之间的相关关系,方差扩大因子越大说明自变量的共线性越严重

另一种解决方法是通过对损失函数正则化来解决,使用 L1 范数正则化的回归模型一般称为 Lasso 回归,使用 L2 范数正则化的回归模型一般称为 Ridge 回归

本文仅介绍 Lasso 回归与 Ridge 回归,关于多重共线性与方差膨胀因子,详见:多重共线性与方差膨胀因子

【正则化】

对于给定的容量为 $n$ 的样本集 $D=\{(\mathbf{x_1},y_1),(\mathbf{x_2},y_2),…,(\mathbf{x_n},y_n)\}$,第 $i$ 组样本中的输入 $\mathbf{x_i}$ 具有 $m$ 个特征值,即:$\mathbf{x_i}=(x_i^{(1)},x_i^{(2)},…,x_i^{(m)})^T\in \mathbb{R}^m$,输出为 $y_i$

用假设函数 $f(\mathbf{x_i};\boldsymbol{\theta})$ 来表示对第 $i$ 组数据的预测结果:

其中,特征参数 $\boldsymbol{\theta}$ 为 $(m+1)\times 1$ 的列向量,即:

现在,希望求出相应的 $\{\theta^{(i)}\}^{m+1}_{i=0}$ 来使得 $f(\mathbf{x_i};\boldsymbol{\theta})$ 能够尽量的拟合好样本集 $D$

为了表述方便,对假设函数进行简化,定义一个额外的第 $0$ 个特征量,这个特征量对所有样本的取值全部为 $1$,这使得特征量从过去的 $m$ 个变为 $m+1$ 个,即设:$x_i^{(0)}=1$

那么假设函数就可以写为:

选用残差平方和 RSS 作为损失函数,则有:

对于原始的损失函数 $J_0(\boldsymbol{\theta})$,在加入正则化项 $R(\boldsymbol{\theta})$ 后,新的损失函数为:

其中,$R(\boldsymbol{\theta})$ 是正则化项,$\lambda\geq0$ 为正则化参数,用于控制两者之间的平衡关系

如果 $\lambda$ 设置的过小,那么 $\boldsymbol{\theta}$ 参数的惩罚程度为起到应有的效果,仍会出现过拟合问题

如果 $\lambda$ 设置的过大,那么 $\boldsymbol{\theta}$ 参数的惩罚程度太大,所有的 $\boldsymbol{\theta}$ 参数几乎全部等于 $0$,这就使得把假设函数的除去 $\theta^{(0)}$ 的项全都忽略掉了,相当于直接用 $f(x)=\theta^{(0)}$ 来拟合数据,这就出现了欠拟合问题

因此,为了让正则化起到应用的效果,应当根据实际情况去选择一个合适的正则化参数 $\lambda$

【Lasso 回归】

一种对损失函数正则化的方式是将正则化项 $R(\boldsymbol{\theta})$ 取全部权重向量 $\boldsymbol{\theta}$ 的 L1 范数 $||\boldsymbol{\theta}||_1$,这个过程被称为 L1 正则化,经过这种损失函数正则化后的线性回归,被称为 Lasso 回归,其完整名称是最小绝对值收敛和选择算子(Least Absolute Shrinkage and Selection Operator)回归

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

由于加入了 L1 范数,存在绝对值,因此损失函数 $J(\boldsymbol{\theta})$ 并不是处处可导的,无法通过直接求导的方式来直接得到 $\boldsymbol{\theta}$ 的解析解,通常使用坐标下降法(Coordinate Descent)最小角回归法(Least Angle Regression,LARS),来求 $\boldsymbol{\theta}$ 的最优解

如图所示,展示了采用最小角回归法时惩罚系数 $\lambda$ 对各个自变量的权重系数的影响,图中横轴为惩罚系数 $\lambda$,纵轴为权重系数,每一个颜色表示一个自变量的权重系数

可以看到当 $\lambda$ 逐渐增大时(向左),某些特征的权重系数会快速变成零,通过这个性质说明 Lasso 回归可以用来进行特征选择,即通过控制 $\lambda$ 的大小来选择关键特征

【Ridge 回归】

最优化过程

除上述的 L1 正则化外,另一种对损失函数正则化的方式是将正则化项 $R(\boldsymbol{\theta})$ 取全部权重向量 $\boldsymbol{\theta}$ 的 L2 范数 $||\boldsymbol{\theta}||_2$ 的平方,这种方式被吉洪诺夫正则化(Tikhonov Regularization),又称为 L2 正则化,经过这种损失函数正则化后的线性回归,被称为 Ridge 回归,即岭回归

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

对于损失函数 $J(\boldsymbol{\theta})$ 可以通过求导来直接得到 $\boldsymbol{\theta}$ 的解析解,即:

可以看到岭回归的损失函数的解析解,相较于线性回归来说多了一个可以人为控制的对角矩阵 $I$,这时可以通过调整不同的 $\lambda$ 来使得矩阵 $XX^T+\lambda I$ 整体可逆

如图所示,展示了惩罚系数 $\lambda$ 对各个自变量的权重系数的影响,图中横轴为惩罚系数 $\lambda$,纵轴为权重系数,每一个颜色表示一个自变量的权重系数

可以看到当 $\lambda$ 越大时(向左),惩罚项的影响越来越大,逐渐占据主导地位,会使得每个自变量的权重系数趋近于零;当 $\lambda$ 越小时(向右),惩罚项的影响越来越小,会导致每个自变量的权重系数震荡的幅度变大

推导过程

将数据集 $D$ 写为 $(m+1)\times n$ 的矩阵,即:

同时,将样本中的 $y_i$ 也写为矩阵形式,即输出变量 $Y$ 为 $n\times 1$ 的列向量:

那么损失函数 $J(\boldsymbol{\theta})$ 可写为:

要令目标函数最小,显然要令 $\frac{\partial}{\partial\boldsymbol{\theta}}J(\boldsymbol{\theta})=0$

对于 $\frac{\partial}{\partial\boldsymbol{\theta}}J(\boldsymbol{\theta})$,有:

对于上式的第一部分,由于 $\boldsymbol{\theta}$ 为 $(m+1)\times 1$ 的列向量,$XX^T+\lambda I$ 为 $(m+1)\times (m+1)$ 的矩阵,故 $\theta^T(XX^T+\lambda I)\boldsymbol{\theta}$ 为标量,求导为分母布局下的标量/向量的形式,故有:

对于剩余的三部分(证明详见:最小二乘法),有:

因此,对于 $\frac{\partial}{\partial\boldsymbol{\theta}}J(\boldsymbol{\theta})$,有:

令 $\frac{\partial}{\partial\boldsymbol{\theta}}J(\boldsymbol{\theta})=0$,则有:

【sklearn 实现】

Lasso 回归

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 Lasso
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):
# 建立Lasso回归模型
model = Lasso()

# 训练
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)

Ridge 回归

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

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 Ridge
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):
# 建立Ridge回归模型
model = Ridge()

# 训练
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)
感谢您对我的支持,让我继续努力分享有用的技术与知识点!