热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

grads相关系数_Lasso回归

正则化与L1范数正则化是防止模型过拟合的核心技术之一,关于欠拟合和过拟合的问题,这里笔者就不再展开来说,不了解的朋友可以看看笔者很早之前写

正则化与L1范数

正则化是防止模型过拟合的核心技术之一,关于欠拟合和过拟合的问题,这里笔者就不再展开来说,不了解的朋友可以看看笔者很早之前写的一篇文章:谈谈过拟合。

总的来说,监督机器学习的核心原理莫过于如下公式:

该公式可谓是机器学习中最核心最关键最能概述监督学习的核心思想的公式了:所有的有监督机器学习,无非就是正则化参数的同时最小化经验误差函数。最小化经验误差是为了极大程度的拟合训练数据,正则化参数是为了防止过分的拟合训练数据。你看,多么简约数学哲学。正如之前所说,监督机器学习是为了让我们建立的模型能够发现数据中普遍的一般的规律,这个普遍的一般的规律无论对于训练集还是未知的测试集,都具有较好的拟合性能。

继续回到公式。第一项经验误差函数在机器学习中无疑地位重要,但它不是笔者今天要讲的,今天要讲的是公式的第二项:正则化项。第二项中 λ 为正则化系数,通常是大于 0 的,是一种调整经验误差项和正则化项之间关系的系数。λ = 0 时相当于该公式没有正则化项,模型全力讨好第一项,将经验误差进行最小化,往往这也是最容易发生过拟合的时候。随着 λ 逐渐增大,正则化项在模型选择中的话语权越来越高,对模型的复杂性的惩罚也越来越厉害。所以,在实际的训练过程中,λ 作为一种超参数很大程度上决定了模型生死。

系数 λ 说完了,然后就是正则化项,正则化项形式有很多,但常见的也就是 L1 和 L2 正则化。本节我们先来看L1。

在说常见的 L1 和 L2 之前,先来看一下 L0 正则化。L0 正则化也就是 L0 范数,即矩阵中所有非 0 元素的个数。如何我们在正则化过程中选择了 L0 范数,那该如何理解这个 L0 呢?其实非常简单,L0 范数就是希望要正则化的参数矩阵 W 大多数元素都为 0。如此简单粗暴,让参数矩阵 W 大多数元素为 0 就是实现稀疏而已。说到这里,权且打住,想必同样在机器学习领域摸爬滚打的你一定想问,据我所知稀疏性不通常都是用 L1 来实现的吗?这里个中缘由笔者不去细讲了,简单说结论:在机器学习领域,L0 和 L1 都可以实现矩阵的稀疏性,但在实践中,L1 要比 L0 具备更好的泛化求解特性而广受青睐。先说了 L1,但还没解释 L1 范数是什么,L1 范数就是矩阵中各元素绝对值之和,正如前述所言,L1 范数通常用于实现参数矩阵的稀疏性。至于为啥要稀疏,稀疏有什么用,通常是为了特征选择和易于解释方面的考虑。

Lasso

Lasso的全称叫做Least absolute shrinkage and selection operator,直译过来为最小收缩与选择算子。其本质就是在常规的线性回归的基础上对参数加了一个L1正则化约束。其形式如下所示:

规约到线性回归模型上,上式的第一项就是MSE损失,第二项则是L1正则化项。我们同样按照之前线性回归的打法来对其进行实现,只是需要注意一下L1正则化项的求导处理。我们来看具体的实现代码。

导入相关package并读入示例数据:

import numpy as np

import pandas as pd

data = np.genfromtxt('mystery.dat', delimiter = ',')

# 选择特征与标签

x = data[:,0:100]

y = data[:,100].reshape(-1,1)

# 加一列

X = np.column_stack((np.ones((x.shape[0],1)),x))

# 划分训练集与测试集

X_train, y_train = X[:70], y[:70]

X_test, y_test = X[70:], y[70:]

print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)

定义参数初始化函数:

# 定义参数初始化函数

def initialize(dims):

w = np.zeros((dims, 1))

b = 0

return w, b

定义符号函数并进行向量化,用于对L1正则化项的梯度计算:

# 定义符号函数

def sign(x):

if x > 0:

return 1

elif x <0:

return -1

else:

return 0

# 利用numpy对符号函数进行向量化

vec_sign &#61; np.vectorize(sign)

vec_sign(np.zeros((3,1)))

在MSE损失函数的基础上定义Lasso损失&#xff1a;

# 定义lasso损失函数

def l1_loss(X, y, w, b, alpha):

num_train &#61; X.shape[0]

num_feature &#61; X.shape[1]

y_hat &#61; np.dot(X, w) &#43; b

loss &#61; np.sum((y_hat-y)**2)/num_train &#43; np.sum(alpha*abs(w))

dw &#61; np.dot(X.T, (y_hat-y)) /num_train &#43; alpha * vec_sign(w)

db &#61; np.sum((y_hat-y)) /num_train

return y_hat, loss, dw, db

定义Lasso训练过程函数&#xff1a;

# 定义训练过程

def lasso_train(X, y, learning_rate&#61;0.01, epochs&#61;300):

loss_list &#61; []

w, b &#61; initialize(X.shape[1])

for i in range(1, epochs):

y_hat, loss, dw, db &#61; l1_loss(X, y, w, b, 0.1)

w &#43;&#61; -learning_rate * dw

b &#43;&#61; -learning_rate * db

loss_list.append(loss)

if i % 50 &#61;&#61; 0:

print(&#39;epoch %d loss %f&#39; % (i, loss))

params &#61; {

&#39;w&#39;: w,

&#39;b&#39;: b

}

grads &#61; {

&#39;dw&#39;: dw,

&#39;db&#39;: db

}

return loss, loss_list, params, grads

执行训练&#xff1a;

# 执行训练示例

loss, loss_list, params, grads &#61; lasso_train(X_train, y_train, 0.01, 500)

可以看到&#xff0c;在L1的约束下&#xff0c;在训练过程中有不少对标签贡献率低的特征的系数都变成了0。这就是L1的作用&#xff0c;一定程度上可以进行特征选择和实现稀疏化。

最后可以简单写一个Lasso回归的class来对上述过程进行封装&#xff1a;

import numpy as np

from sklearn.metrics import r2_score

class Lasso():

def __init__(self):

pass

def prepare_data(self):

data &#61; np.genfromtxt(&#39;./example.dat&#39;, delimiter &#61; &#39;,&#39;)

x &#61; data[:, 0:100]

y &#61; data[:, 100].reshape(-1, 1)

X &#61; np.column_stack((np.ones((x.shape[0], 1)), x))

X_train, y_train &#61; X[:70], y[:70]

X_test, y_test &#61; X[70:], y[70:]

return X_train, y_train, X_test, y_test

def initialize_params(self, dims):

w &#61; np.zeros((dims, 1))

b &#61; 0

return w, b

def sign(self, x):

if x > 0:

return 1

elif x <0:

return -1

else:

return 0

def l1_loss(self, X, y, w, b, alpha):

num_train &#61; X.shape[0]

num_feature &#61; X.shape[1]

y_hat &#61; np.dot(X, w) &#43; b

loss &#61; np.sum((y_hat - y) ** 2) / num_train &#43; np.sum(alpha*abs(w))

dw &#61; np.dot(X.T, (y_hat - y)) / num_train &#43; alpha*np.vectorize(self.sign)(w)

db &#61; np.sum((y_hat - y)) / num_train

return y_hat, loss, dw, db

def lasso_train(self, X, y, learning_rate, epochs):

loss_list &#61; []

w, b &#61; self.initialize_params(X.shape[1])

for i in range(1, epochs):

y_hat, loss, dw, db &#61; self.l1_loss(X, y, w, b, 0.1)

w &#43;&#61; -learning_rate * dw

b &#43;&#61; -learning_rate * db

loss_list.append(loss)

if i % 300 &#61;&#61; 0:

print(&#39;epoch %d loss %f&#39; % (i, loss))

params &#61; {

&#39;w&#39;: w,

&#39;b&#39;: b

}

grads &#61; {

&#39;dw&#39;: dw,

&#39;db&#39;: db

}

return loss, loss_list, params, grads

def predict(self, X, params):

w &#61; params[&#39;w&#39;]

b &#61; params[&#39;b&#39;]

y_pred &#61; np.dot(X, w) &#43; b

return y_pred

if __name__ &#61;&#61; &#39;__main__&#39;:

lasso &#61; Lasso()

X_train, y_train, X_test, y_test &#61; lasso.prepare_data()

loss, loss_list, params, grads &#61; lasso.lasso_train(X_train, y_train, 0.01, 3000)

print(params)

y_pred &#61; lasso.predict(X_test, params)

print(r2_score(y_test, y_pred))

以上是基于numpy的手动实现Lasso的过程&#xff0c;下面再来看Lasso在sklearn中的实现。

# 导入线性模型模块

from sklearn import linear_model

# 创建lasso模型实例

sk_lasso &#61; linear_model.Lasso(alpha&#61;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 nu



推荐阅读
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文为Codeforces 1294A题目的解析,主要讨论了Collecting Coins整除+不整除问题。文章详细介绍了题目的背景和要求,并给出了解题思路和代码实现。同时提供了在线测评地址和相关参考链接。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
author-avatar
X你好先生
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有