数据分析 | 岭回归与LASSO回归

根据线性回归模型的参数估计公式 β = ( X ′ X ) − 1 X ′ y \beta=(X'X)^{-1}X'y β=(XX)1Xy 可知,得到 β \beta β 的前提是 ( X ′ X ) − 1 (X'X)^{-1} (XX)1 必须不为零,即可逆。但在实际应用中,可能会出现自变量个数多于样本量,或者自变量间存在多重共线性的情况,此时 X ′ X = 0 X'X=0 XX=0 ,将无法再根据公式计算出回归系数的估计值 β \beta β.

岭回归与LASSO回归

  • 一、岭回归模型
    • 01 模型概述
    • 02 代码实现
  • 二、LASSO回归模型
    • 01 模型概述
  • 三、代码

一、岭回归模型

01 模型概述

为解决多元线性回归模型中可能存在的不可逆问题,提出了岭回归模型。该模型解决思路就是,在线性回归模型的目标函数上添加 l 2 l2 l2正则项(惩罚项)
J ( β ) = ∑ ( y − X β ) 2 + λ ∣ ∣ β ∣ ∣ 2 2 = ∑ ( y − X β ) 2 + ∑ λ β 2 J(\beta)=\sum(y-X\beta)^2+\lambda||\beta||_2^2=\sum(y-X\beta)^2+\sum\lambda\beta^2 J(β)=(yXβ)2+λβ22=(yXβ)2+λβ2
在线性回归模型的目标函数中添加l2正则项,其中 λ \lambda λ为非负数。当 λ = 0 \lambda=0 λ=0 时目标函数退化为线性回归模型的目标函数,当 λ → + ∞ \lambda\rightarrow+\infin λ+ 时,通过缩减回归系数使 β \beta β 趋向于0

另外, λ \lambda λ l 2 l2 l2正则项的平方数,用于平衡模型方差(回归系数的方差)和偏差。

系数求解如下:

展开岭回归模型中的平方项
J ( β ) = ( y − X β ) ′ ( y − X β ) + λ β ′ β = y ′ y − y ′ X β − β ′ X ′ y + β ′ X ′ X β + λ β ′ β J(\beta)=(y-X\beta)'(y-X\beta)+\lambda\beta'\beta=y'y-y'X\beta-\beta'X'y+\beta'X'X\beta+\lambda\beta'\beta J(β)=(yXβ)(yXβ)+λββ=yyyXββXy+βXXβ+λββ
计算导函数
∂ J ( β ) ∂ β = 2 ( X ′ X + λ I ) β − 2 X ′ y \frac{\partial J(\beta)}{\partial \beta}=2(X'X+\lambda I)\beta-2X'y βJ(β)=2(XX+λI)β2Xy
参数求解
2 ( X ′ X + λ I ) β − 2 X ′ y = 0 ∴ β = ( X ′ X + λ I ) − 1 X ′ y 2(X'X+\lambda I)\beta-2X'y=0\\\therefore\beta=(X'X+\lambda I)^{-1}X'y 2(XX+λI)β2Xy=0β=(XX+λI)1Xy
其中需要注意的是 λ \lambda λ 值的确定,这里采用交叉验证法:

首先将数据集拆分为k个样本量大体相等的数据组,并且每个数据组与其他组都没有重叠的观测。

然后从k组数据中挑选k-1组数据用于模型的训练,剩下的一组数据用于模型的测试。

以此类推,将会得到k中训练集和测试集。在每一种训练集和测试集下,都会对应一个模型及模型得分(如均方误差)。

python提供 RidgeCV(alphas = (0.1,1.0,10), fit_intercept=True, normalize=False, scoring=None, cv=None) 函数提供交叉验证法来确定 λ \lambda λ的值

  • alphas:指定多个lambda值的元组或数组对象,默认该参数包含0.1、1、10三种值
  • fit_intercept:是否需要拟合截距项,默认为True
  • normalize:建模时是否需要对数据集做标准化处理,默认为False
  • scoring:指定用于评估模型的度量方法
  • cv:指定交叉验证的重数。

02 代码实现

import pandas as pd
import numpy as np
from sklearn.linear_model import Ridge,RidgeCV   # Ridge岭回归,RidgeCV带有广义交叉验证的岭回归

# 导入数据
data = pd.read_excel(r'diabetes.xlsx')
X_train = data[['AGE','SEX','BMI','BP','S1','S2','S3']]
y_train = data['Y']
# 运用等比数列构造200个不同的Lambda值
Lambdas = np.logspace(-5,2,200)
# 设置交叉验证的参数,对于每一个Lambda值,都执行10重交叉验证
ridge_cv = RidgeCV(alphas = Lambdas, normalize=True, scoring='neg_mean_squared_error',
                   cv = 10)
# 模型拟合
ridge_cv.fit(X_train, y_train)
# 返回最佳的lambda值
ridge_best_Lambda = ridge_cv.alpha_
ridge_best_Lambda

得到最佳的 λ \lambda λ值为0.0090110182516650178

# 基于最佳的Lambda值建模
ridge = Ridge(alpha = ridge_best_Lambda, normalize=True)
ridge.fit(X_train, y_train)
# 返回岭回归系数
pd.Series(index = ['Intercept'] + X_train.columns.tolist(),
 data = [ridge.intercept_] + ridge.coef_.tolist())

结果如下:

Intercept   -61.021183
AGE           0.078594
SEX         -21.941443
BMI           6.240046
BP            1.234446
S1            1.143375
S2           -1.207391
S3           -2.344764
dtype: float64

即:y = -61.021183 + 0.078594AGE - 21.941443SEX + 6.240046BMI + 1.234446BP + 1.143375S1 - 1.207391S2 - 2.344764S3

二、LASSO回归模型

01 模型概述

​ 岭回归模型解决线性回归模型中矩阵X’X不可逆的办法是添加I2正则的惩罚项,但缺陷在于始终保留建模时的所有变量,无法降低模型的复杂度。对于此,Lasso回归采用了l1正则的惩罚项。
J ( β ) = ∑ ( y − X β ) 2 + λ ∣ ∣ β ∣ ∣ 1 = ∑ ( y − X β ) 2 + ∑ λ ∣ β ∣ J(\beta)=\sum(y-X\beta)^2+\lambda||\beta||_1=\sum(y-X\beta)^2+\sum\lambda|\beta| J(β)=(yXβ)2+λβ1=(yXβ)2+λβ
对于Lasso回归模型中 λ \lambda λ值的确定,提供函数 LassoCV(alphas=None, fit_intercept=True, normalize=False, max_iter=1000, tol=0.0001)

  • max_iter:指定模型最大的迭代次数,默认为1000次
  • tol:指定误差收敛范围

三、代码

# 导入第三方模块
import pandas as pd
import numpy as np
from sklearn import model_selection
from sklearn.linear_model import Ridge,RidgeCV
import matplotlib.pyplot as plt

# 读取数据集
diabetes = pd.read_excel(r'diabetes.xlsx', sep = '')
# 构造自变量(剔除性别、年龄和因变量)
predictors = diabetes.columns[2:-1]
# 将数据集拆分为训练集和测试集
X_train, X_test, y_train, y_test = model_selection.train_test_split(diabetes[predictors], diabetes['Y'], 
                                                                    test_size = 0.2, random_state = 1234
                                                                 	)

岭回归:

# 构造不同的Lambda值
Lambdas = np.logspace(-5, 2, 200)
# 岭回归模型的交叉验证
# 设置交叉验证的参数,对于每一个Lambda值,都执行10重交叉验证
ridge_cv = RidgeCV(alphas = Lambdas, normalize=True, scoring='neg_mean_squared_error', cv = 10)
# 模型拟合
ridge_cv.fit(X_train, y_train)
# 返回最佳的lambda值
ridge_best_Lambda = ridge_cv.alpha_
ridge_best_Lambda

λ \lambda λ= 0.013509935211980266

# 导入第三方包中的函数
from sklearn.metrics import mean_squared_error
# 基于最佳的Lambda值建模
ridge = Ridge(alpha = ridge_best_Lambda, normalize=True)
ridge.fit(X_train, y_train)
# 返回岭回归系数
pd.Series(index = ['Intercept'] + X_train.columns.tolist(),data = [ridge.intercept_] + ridge.coef_.tolist())
# 预测
ridge_predict = ridge.predict(X_test)
# 预测效果验证
RMSE = np.sqrt(mean_squared_error(y_test,ridge_predict))
RMSE

RSM= 53.12361694661972

Lasso回归:

# 导入第三方模块中的函数
from sklearn.linear_model import Lasso,LassoCV
# LASSO回归模型的交叉验证
lasso_cv = LassoCV(alphas = Lambdas, normalize=True, cv = 10, max_iter=10000)
lasso_cv.fit(X_train, y_train)
# 输出最佳的lambda值
lasso_best_alpha = lasso_cv.alpha_
lasso_best_alpha

λ \lambda λ = 0.062949889902218878

# 基于最佳的lambda值建模
lasso = Lasso(alpha = lasso_best_alpha, normalize=True, max_iter=10000)
lasso.fit(X_train, y_train)
# 返回LASSO回归的系数
pd.Series(index = ['Intercept'] + X_train.columns.tolist(),data = [lasso.intercept_] + lasso.coef_.tolist())

# 预测
lasso_predict = lasso.predict(X_test)
# 预测效果验证
RMSE = np.sqrt(mean_squared_error(y_test,lasso_predict))
RMSE

RMSE = 53.06143725822573

线性回归:

# 导入第三方模块
from statsmodels import api as sms
# 为自变量X添加常数列1,用于拟合截距项
X_train2 = sms.add_constant(X_train)
X_test2 = sms.add_constant(X_test)

# 构建多元线性回归模型
linear = sms.OLS(y_train, X_train2).fit()
# 返回线性回归模型的系数
linear.params

# 模型的预测
linear_predict = linear.predict(X_test2)
# 预测效果验证
RMSE = np.sqrt(mean_squared_error(y_test,linear_predict))
RMSE

RMSE = 53.426239397229892

故此数据集应采用Lasso回归拟合最好。

你可能感兴趣的:(python,讲解,回归,数据分析,机器学习)