监督学习单模型—线性模型—LASSO回归、Ridge回归

目标变量通常有很多影响因素,通过各类影响因素构建对目标变量的回归模型,能够实现对目标的预测。但根据稀疏性的假设,即使影响一个变量的因素有很多,其关键因素永远只会是少数。在这种情况下,还用传统的线性回归方法来处理的话,效果可能并不理想。针对这种情况,下面介绍两种线性回归模型的拓展模型—— LASSO 回归和 Ridge 回归。

一、LASSO回归

1. 原理推导

LASSO(the least absolute shrinkage and election operator)回归模型,可译为最小绝对收缩和选择算子,已知线性回归模型的最优参数估计表达式为:

ω∧✶ = (XTX)-1XTy【式 1】

具体解析见:【监督学习单模型—线性模型—线性回归】

假设训练样本量为 m ,样本特征数为 n ,按照惯例,有 m > n ,即样本量大于特征数。当 m > n 时,若 rank(X) = n ,即 X 为满秩矩阵,则 XTX 是可逆矩阵,式 1 是可以直接求解的,但如果 m < n ,即特征数大于样本量时,rank(X) < n ,矩阵 X 不满秩,XTX 不可逆,这时候式 1 中的参数 ω∧✶ 是不可估计的。

对于这个问题,LASSO 回归给出的做法是在线性回归的损失函数后面加一个 1-范数项,也叫正则化项,即:L(ω) = (y-ωX)2 + λ||ω||1【式 2】 ,其中 |ω||1 即为矩阵的 1-范数,λ 为 1-范数项的系数。

范数(norm)的概念:在数学分析中,范数可视为一种长度或者距离概念的函数。针对向量或者矩阵而言,常用的范数包括 0-范数、1-范数、2-范数和 p-范数等。矩阵的 0-范数为矩阵中非零元素的个数,矩阵的 1-范数可定义为矩阵中所有元素的绝对值之和,而矩阵的 2-范数是指矩阵中各元素的平方和再求均方根的结果。

从机器学习的角度来看,式 2 相当于给最初的线性回归损失函数添加了一个 L1 正则化项,λ 也叫正则化系数。从防止模型过拟合的角度而言,正则化项相当于对目标参数施加了一个惩罚项,使得模型不能过于复杂。在优化过程中,正则化项的存在能够使那些不重要的特征系数逐渐为零,从而保留关键特征,使得模型简化。所以,式 2 等价于:arg min (y-ωX)2【式 3】s.t. Σ|ωij| < s【式 4】,其中式 3 即为线性回归目标函数,式 4 为其约束条件,即权重系数矩阵所有元素绝对值之和小于一个指定常数 s ,s 取值越小,特征参数中被压缩到零的特征就会越多。

下图是 LASSO 回归的参数估计图:

如上图所示,横纵坐标分别为两个回归参数 ω1 和 ω2 ,菱形线框表示 LASSO 回归的 L1 正则化约束:|ω1| + |ω2| ≤ s ,椭圆形区域为回归参数的求解空间。可以看到,LASSO 回归的参数解空间与纵坐标轴相交,此时意味着参数 ω1 被压缩为 0 。

如何针对式 2 :L(ω) = (y-ωX)2 + λ||ω||1 的 LASSO 回归目标函数进行参数优化?即如何求 LASSO 回归的最优解问题。L1 正则化项的存在使得式 2 是连续不可导的函数,直接使用梯度下降法无法进行寻优,一种替代的 LASSO 回归寻优方法称为坐标下降法(coordinate descent method)。坐标下降法是一种迭代算法,相较于梯度下降法通过损失函数的负梯度来确定下降方向,坐标下降法是在当前坐标轴上搜索损失函数的最小值,无需计算函数梯度。

以二维空间为例,假设 LASSO 回归损失函数为凸函数 L(x,y) ,给定初始点 x0 ,可以找到使得 L(y) 达到最小的 y1 ,然后固定 y1 ,再找到使得 L(x) 达到最小的 x2 。这样反复迭代之后,根据凸函数的性质,一定能够找到使得 L(x,y) 最小的点 (xk,yk) 。坐标下降法的寻优过程如下图所示:

2. 代码实现

数据集:葡萄酒质量(类型:txt 文件)

  • 输入变量:物理化学性质(例如,pH 值、酒精含量、酸度)。

  • 输出变量:感官评分(质量),这是有序的类别。

“fixed acidity”;“volatile acidity”;“citric acid”;“residual sugar”;“chlorides”;“free sulfur dioxide”;“total sulfur dioxide”;“density”;“pH”;“sulphates”;“alcohol”;“quality”
7.4;0.7;0;1.9;0.076;11;34;0.9978;3.51;0.56;9.4;5
7.8;0.88;0;2.6;0.098;25;67;0.9968;3.2;0.68;9.8;5
7.8;0.76;0.04;2.3;0.092;15;54;0.997;3.26;0.65;9.8;5
11.2;0.28;0.56;1.9;0.075;17;60;0.998;3.16;0.58;9.8;6
7.4;0.7;0;1.9;0.076;11;34;0.9978;3.51;0.56;9.4;5
7.4;0.66;0;1.8;0.075;13;40;0.9978;3.51;0.56;9.4;5
7.9;0.6;0.06;1.6;0.069;15;59;0.9964;3.3;0.46;9.4;5
7.3;0.65;0;1.2;0.065;15;21;0.9946;3.39;0.47;10;7
7.8;0.58;0.02;2;0.073;9;18;0.9968;3.36;0.57;9.5;7
7.5;0.5;0.36;6.1;0.071;17;102;0.9978;3.35;0.8;10.5;5
6.7;0.58;0.08;1.8;0.097;15;65;0.9959;3.28;0.54;9.2;5
7.5;0.5;0.36;6.1;0.071;17;102;0.9978;3.35;0.8;10.5;5

1)基于 Numpy 的代码实现

【代码实现】:

import numpy as np# 定义符号函数
def sign(x):if x > 0:return 1elif x < 0:return -1else:return 0
# 利用Numpy对符号函数进行向量化
vec_sign = np.vectorize(sign)# 定义LASSO回归损失函数
def l1_loss(X, y, w, b, alpha):# 训练样本数num_train = X.shape[0]# 训练特征数# num_feature = X.shape[1]# 回归模型预测输出y_hat = np.dot(X, w) + b# L1损失函数loss = np.sum((y_hat - y) ** 2) / num_train + np.sum(alpha * abs(w))# 基于向量化符号函数的参数梯度计算dw = np.dot(X.T, (y_hat - y)) / num_train + alpha * vec_sign(w)db = np.sum((y_hat - y)) / num_trainreturn y_hat, loss, dw, db# 初始化模型参数
def initialize_params(dims):# 将权重向量初始化为零向量w = np.zeros((dims, 1))# 将偏置参数初始化为0b = 0return w, b# 定义LASSO回归模型的训练过程
def lasso_train(X, y, learning_rate=0.01, epochs=1000):# 记录训练损失的空列表loss_his = []# 初始化模型参数w, b = initialize_params(X.shape[1])# 迭代训练for i in range(1, epochs):# 计算当前迭代的预测值、损失和梯度alpha = 0.1y_hat, loss, dw, db = l1_loss(X, y, w, b, alpha)# 基于梯度下降法的参数更新w += -learning_rate * dwb += -learning_rate * db# 记录当前迭代的损失loss_his.append(loss)# 每50次迭代打印当前损失信息# if i % 50 == 0:# print('epoch %d loss %f' % (i, loss))# 将迭代优化后的参数保存到字典中params = {'w':w, 'b':b}return loss_his, params# 导入数据集 (12,12)
data = np.genfromtxt('D:\PycharmProjects\wine_lasso_quality.txt', delimiter=';')
# 选择特征与标签
num_row = data.shape[0]
num_column = data.shape[1]
x = data[1:, 0:num_column-1]
y = data[1:, num_column-1].reshape(-1, 1)
# 加一列
X = np.column_stack((np.ones((num_row-1, 1)), x))
# 划分数据集,使用30%的数据作为测试集
offset = int(X.shape[0] * 0.7)
# 训练集 (8,12) & (8,1)
X_train, y_train = X[:offset], y[:offset]
# 测试集 (4,12) & (4,1)
X_test, y_test = X[offset:], y[offset:]
# 执行训练示例
learning_rate = 0.01
epochs = 100
loss_list, params = lasso_train(X_train, y_train, learning_rate, epochs)
# 获取训练参数
print('训练参数:\n', params)
# 将测试集应用在模型上
y_predict = np.dot(X_test, params['w']) + params['b']
print('测试集训练标签:\n', y_predict)

【结果展示】:

2)基于 Sklearn 的模型实现

【代码实现】:

import numpy as np
from sklearn import linear_model# 导入数据集 (12,12)
data = np.genfromtxt('D:\PycharmProjects\wine_lasso_quality.txt', delimiter=';')
# 选择特征与标签
num_row = data.shape[0]
num_column = data.shape[1]
x = data[1:, 0:num_column-1]
y = data[1:, num_column-1].reshape(-1, 1)
# 加一列
X = np.column_stack((np.ones((num_row-1, 1)), x))
# 划分数据集,使用30%的数据作为测试集
offset = int(X.shape[0] * 0.7)
# 训练集 (8,12) & (8,1)
X_train, y_train = X[:offset], y[:offset]
# 测试集 (4,12) & (4,1)
X_test, y_test = X[offset:], y[offset:]# 创建LASSO回归模型实例
sk_LASSO = linear_model.Lasso(alpha=0.1)
# 对训练集进行拟合
sk_LASSO.fit(X_train, y_train)
# 打印模型相关系数
print('sklearn LASSO intercept:(截距)', sk_LASSO.intercept_)
print('\nsklearn LASSO coefficients:(系数)\n', sk_LASSO.coef_)
print('\nsklearn LASSO number of iterations(迭代次数):', sk_LASSO.n_iter_)

【结果展示】:

从上述结果可以看出,LASSO 回归模型使得大量特征的参数被压缩为 0 。

二、Ridge回归

1. 原理推导

类似于 LASSO 回归模型,Ridge 回归(岭回归)是一种使用 2-范数作为惩罚项改造线性回归损失函数的模型。此时损失函数如式 5 所示:

L(ω) = (y-ωX)2 + λ||ω||2【式 5】

其中 ||ω||2 = λ · Σi=1n ωi2 ,也叫 L2 正则化项,采用 2-范数进行正则化的原理是最小化参数矩阵的每个元素,使其无限接近 0 但又不像 L1 那样等于 0 。

为什么参数矩阵中的每个元素变得很小,就能防止过拟合?下面以深度神经网络为例来说明。在 L2 正则化中,如果正则化系数 λ 取值较大,参数矩阵 ω 中的每个元素都会变小,线性计算,激活函数在此时相对呈线性状态,这样就会降低深度神经网络的复杂性,因而可以防止过拟合,所以式 5 等价于:arg min (y-ωX)2(s.t. Σωij2 < s)【式 6】

式 6 的第一个公式即为线性回归目标函数,括号里的公式为其约束条件,即权重系数矩阵所有元素平方之和小于指定常数 s 。相应地,式 1 可改写为:ω∧✶ = (XTX + λI)-1XTy【式 7】

从式 7 可以看到,通过给 XTX 加上一个单位矩阵使其变成非奇异矩阵并可以进行求逆运算,从而求解 Ridge 回归。下图是 Ridge 回归的参数估计图:

如上图所示,横纵坐标分别为两个回归参数 ω1 和 ω2 ,圆形区域表示 Ridge 回归的 L2 正则化约束:ω12 + ω22 ≤ s ,椭圆形区域为回归参数的求解空间。由此可见,LASSO 回归的参数解空间与纵坐标轴相交,而 Ridge 回归参数只是接近 0 但不等于 0 。

Ridge 回归参数求解要比 LASSO 回归相对容易一些,一方面,我们可以直接基于式 7 的矩阵运算进行求解,另一方面,也可以按照线性回归的梯度下降优化方式进行迭代计算。

2. 代码实现

1)基于 Numpy 的代码实现

【代码实现】:

import numpy as np# 定义Ridge回归损失函数
def l2_loss(X, y, w, b, alpha):# 训练样本数num_train = X.shape[0]# 训练特征数# num_feature = X.shape[1]# 回归模型预测输出y_hat = np.dot(X, w) + b# L2损失函数loss = np.sum((y_hat - y) ** 2) / num_train + alpha * (np.sum(np.square(w)))# 参数梯度计算dw = np.dot(X.T, (y_hat - y)) / num_train + 2 * alpha * wdb = np.sum((y_hat - y)) / num_trainreturn y_hat, loss, dw, db# 初始化模型参数
def initialize_params(dims):# 将权重向量初始化为零向量w = np.zeros((dims, 1))# 将偏置参数初始化为0b = 0return w, b# 定义Ridge回归模型的训练过程
def ridge_train(X, y, learning_rate=0.01, epochs=1000):# 记录训练损失的空列表loss_his = []# 初始化模型参数w, b = initialize_params(X.shape[1])# 迭代训练for i in range(1, epochs):# 计算当前迭代的预测值、损失和梯度alpha = 0.1y_hat, loss, dw, db = l2_loss(X, y, w, b, alpha)# 基于梯度下降法的参数更新w += -learning_rate * dwb += -learning_rate * db# 记录当前迭代的损失loss_his.append(loss)# 每50次迭代打印当前损失信息# if i % 50 == 0:# print('epoch %d loss %f' % (i, loss))# 将迭代优化后的参数保存到字典中params = {'w':w, 'b':b}return loss_his, params# 导入数据集 (12,12)
data = np.genfromtxt('D:\PycharmProjects\wine_lasso_quality.txt', delimiter=';')
# 选择特征与标签
num_row = data.shape[0]
num_column = data.shape[1]
x = data[1:, 0:num_column-1]
y = data[1:, num_column-1].reshape(-1, 1)
# 加一列
X = np.column_stack((np.ones((num_row-1, 1)), x))
# 划分数据集,使用30%的数据作为测试集
offset = int(X.shape[0] * 0.7)
# 训练集 (8,12) & (8,1)
X_train, y_train = X[:offset], y[:offset]
# 测试集 (4,12) & (4,1)
X_test, y_test = X[offset:], y[offset:]
# 执行训练示例
learning_rate = 0.01
epochs = 100
loss_list, params = ridge_train(X_train, y_train, learning_rate, epochs)
# 获取训练参数
print('训练参数:\n', params)
# 将测试集应用在模型上
y_predict = np.dot(X_test, params['w']) + params['b']
print('测试集训练标签:\n', y_predict)

【结果展示】:

2)基于 Sklearn 的模型实现

【代码实现】:

import numpy as np
from sklearn.linear_model import Ridge# 导入数据集 (12,12)
data = np.genfromtxt('D:\PycharmProjects\wine_lasso_quality.txt', delimiter=';')
# 选择特征与标签
num_row = data.shape[0]
num_column = data.shape[1]
x = data[1:, 0:num_column-1]
y = data[1:, num_column-1].reshape(-1, 1)
# 加一列
X = np.column_stack((np.ones((num_row-1, 1)), x))
# 划分数据集,使用30%的数据作为测试集
offset = int(X.shape[0] * 0.7)
# 训练集 (8,12) & (8,1)
X_train, y_train = X[:offset], y[:offset]
# 测试集 (4,12) & (4,1)
X_test, y_test = X[offset:], y[offset:]# 创建Ridge回归模型实例
clf = Ridge(alpha=0.1)
# 对训练集进行拟合
clf.fit(X_train, y_train)
# 打印模型相关系数
print('sklearn LASSO intercept:(截距)', clf.intercept_)
print('\nsklearn LASSO coefficients:(系数)\n', clf.coef_)

【结果展示】:

可以看到,Ridge 回归参数大多比较接近 0 ,但都不等于 0 ,这也正是 Ridge 回归的一个特征。

从数学角度来看,LASSO 回归和 Ridge 回归都是在 XTX 为不可逆矩阵的情况下,求解回归参数的一种 “妥协” 性的方法。通过给常规的平方损失函数添加 L1 正则化项和 L2 正则化项,使得回归问题有可行解,虽然这种解是一种有偏估计。
但从业务可解释性的角度来看,影响一个变量的因素有很多,但关键因素永远只会是少数。当影响一个变量的因素有很多时(特征数可能会大于样本量),用传统的线性回归方法来处理可能效果会不太理想。LASSO 回归和 Ridge 回归通过对损失函数施加正则化项的方式,使得回归建模过程中大量不重要的特征系数被压缩为 0 或者接近 0 ,从而找出对目标变量有较强影响的关键特征。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/26848.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【QT】QLinearGradient 线性渐变类简单使用教程

目录 0.简介 1&#xff09;qtDesigner中 2&#xff09;实际执行 1.功能详述 3.举一反三的样式 0.简介 QLinearGradient 是 Qt 框架中的一个类&#xff0c;用于定义线性渐变效果&#xff08;通过样式表设置&#xff09;。它可以用来填充形状、背景或其他图形元素&#xff0…

攻防世界GFSJ1184_welcome_CAT_CTF

题目 附件&#xff1a; 两个文件client和server Get Flag Exeinfo File分析 file client client: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]6045aa1ba5…

EL表达式和JSTL标签

目录 1. EL表达式 1.1. EL表达式概述 1.2. EL表达式运算 1.3. EL表达式操作对象 1.4. EL表达式内置对象 jsp 9个 11个 1.4.1. 参数隐藏对象 1.4.2. 域隐藏对象 1.4.3. PageContext对象 2. JSTL标签 2.1. JSTL概述 2.1.1. 什么是JSTL 2.1.2. 导入标签库 2.2. JSTL核…

PhotoShop学习01

了解Photoshop 这里省略了Photoshop的软件安装&#xff0c;请自行查找资源下载。 1.打开图片 下图为启动photoshop后出现的界面&#xff0c;我们可以通过创建新文件或打开已有文件来启用photoshop的工作界面。 可以通过左边的按钮进行新文件的创建或打开已有文件。 也可以点…

LabVIEW虚拟弗兰克赫兹实验仪

随着信息技术的飞速发展&#xff0c;虚拟仿真技术已经成为教学和研究中不可或缺的工具。开发了一种基于LabVIEW平台开发的虚拟弗兰克赫兹实验仪&#xff0c;该系统不仅能模拟实验操作&#xff0c;还能实时绘制数据图形&#xff0c;极大地丰富了物理实验的教学内容和方式。 ​ …

【TI毫米波雷达】DCA1000的ADC原始数据C语言解析及FMCW的Python解析2D-FFT图像

【TI毫米波雷达】DCA1000的ADC原始数据C语言解析及FMCW的Python解析2D-FFT图像 文章目录 ADC原始数据C语言解析Python的2D-FFT图像附录&#xff1a;结构框架雷达基本原理叙述雷达天线排列位置芯片框架Demo工程功能CCS工程导入工程叙述Software TasksData PathOutput informati…

【数据结构】堆与二叉树

一、树的概念 1.1 什么是树&#xff1f; 树是一种非线性的数据结构&#xff0c;其由 n 个 ( n > 0 ) 有限节点所组成的一个有层次关系的集合。之所以称其为树&#xff0c;是因为其逻辑结构看起来像是一颗倒挂的树。 在树中&#xff0c;有一个特殊的节点称为根节点&#xf…

从零开始开发纯血鸿蒙应用之语音朗读

从零开始开发纯血鸿蒙应用 〇、前言一、API 选型1、基本情况2、认识TextToSpeechEngine 二、功能集成实践1、改造右上角菜单2、实现语音播报功能2.1、语音引擎的获取和关闭2.2、设置待播报文本2.3、speak 目标文本2.4、设置语音回调 三、总结 〇、前言 中华汉字洋洋洒洒何其多…

8 SpringBoot进阶(上):AOP(面向切面编程技术)、AOP案例之统一操作日志

文章目录 前言1. AOP基础1.1 AOP概述: 什么是AOP?1.2 AOP快速入门1.3 Spring AOP核心中的相关术语(面试)2. AOP进阶2.1 通知类型2.1.1 @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行(通知的代码在业务方法之前和之后都有)2.1.2 @Before:前置通知,此…

人大金仓国产数据库与PostgreSQL

一、简介 在前面项目中&#xff0c;我们使用若依前后端分离整合人大金仓&#xff0c;在后续开发过程中&#xff0c;我们经常因为各种”不适配“问题&#xff0c;但可以感觉得到大部分问题&#xff0c;将人大金仓视为postgreSQL就能去解决大部分问题。据了解&#xff0c;Kingba…

Deepseek 模型蒸馏

赋范课堂&#xff1a; https://www.bilibili.com/video/BV1qUN8enE4c/

经验分享:用一张表解决并发冲突!数据库事务锁的核心实现逻辑

背景 对于一些内部使用的管理系统来说&#xff0c;可能没有引入Redis&#xff0c;又想基于现有的基础设施处理并发问题&#xff0c;而数据库是每个应用都避不开的基础设施之一&#xff0c;因此分享个我曾经维护过的一个系统中&#xff0c;使用数据库表来实现事务锁的方式。 之…

【前端基础】1、HTML概述(HTML基本结构)

一、网页组成 HTML&#xff1a;网页的内容CSS&#xff1a;网页的样式JavaScript&#xff1a;网页的功能 二、HTML概述 HTML&#xff1a;全称为超文本标记语言&#xff0c;是一种标记语言。 超文本&#xff1a;文本、声音、图片、视频、表格、链接标记&#xff1a;由许许多多…

MongoDB—(一主、一从、一仲裁)副本集搭建

MongoDB集群介绍&#xff1a; MongoDB 副本集是由多个MongoDB实例组成的集群&#xff0c;其中包含一个主节点&#xff08;Primary&#xff09;和多个从节点&#xff08;Secondary&#xff09;&#xff0c;用于提供数据冗余和高可用性。以下是搭建 MongoDB 副本集的详细步骤&am…

Hive-06之函数 聚合Cube、Rollup、窗口函数

1、Hive函数介绍以及内置函数查看 内容较多&#xff0c;见《Hive官方文档》 https://cwiki.apache.org/confluence/display/Hive/LanguageManualUDF 1&#xff09;查看系统自带的函数 hive> show functions; 2&#xff09;显示自带的函数的用法 hive> desc function…

CSS定位详解

1. 相对定位 1.1 如何设置相对定位&#xff1f; 给元素设置 position:relative 即可实现相对定位。 可以使用 left 、 right 、 top 、 bottom 四个属性调整位置。 1.2 相对定位的参考点在哪里&#xff1f; 相对自己原来的位置 1.3 相对定位的特点&#xff1…

[Lc滑动窗口_1] 长度最小的数组 | 无重复字符的最长子串 | 最大连续1的个数 III | 将 x 减到 0 的最小操作数

目录 1. 长度最小的字数组 题解 代码 ⭕2.无重复字符的最长子串 题解 代码 3.最大连续1的个数 III 题解 代码 4.将 x 减到 0 的最小操作数 题解 代码 1. 长度最小的字数组 题目链接&#xff1a;209.长度最小的字数组 题目分析: 给定一个含有 n 个 正整数 的数组…

MySQL 事务笔记

MySQL 事务笔记 目录 事务简介事务操作事务四大特性并发事务问题事务隔离级别总结 事务简介 事务&#xff08;Transaction&#xff09;是数据库操作的逻辑单元&#xff0c;由一组不可分割的SQL操作组成。主要用于保证&#xff1a; 多个操作的原子性&#xff08;要么全部成功…

数据结构秘籍(四) 堆 (详细包含用途、分类、存储、操作等)

1 引言 什么是堆&#xff1f; 堆是一种满足以下条件的树&#xff1a;&#xff08;树这一篇可以参考我的文章数据结构秘籍&#xff08;三&#xff09;树 &#xff08;含二叉树的分类、存储和定义&#xff09;-CSDN博客&#xff09; 堆中的每一个结点值都大于等于&#xff08…

【网络安全 | 渗透测试】GraphQL精讲一:基础知识

未经许可,不得转载, 文章目录 GraphQL 定义GraphQL 工作原理GraphQL 模式GraphQL 查询GraphQL 变更(Mutations)查询(Queries)和变更(Mutations)的组成部分字段(Fields)参数(Arguments)变量别名(Aliases)片段(Fragments)订阅(Subscriptions)自省(Introspecti…