python 怎么算l2范数_数学推导+纯Python实现机器学习算法13:Lasso回归

版权说明:本公号转载文章旨在学习交流,不用于任何商业用途,版权归原作者所有,如有异议,敬请后台联络我们,议定合作或删除,我们将第一时间按版权法规定妥善处理,非常感谢!


Python机器学习算法实现

Author:louwill

本节我们要介绍的是基于L1正则化的Lasso模型,下一节介绍基于L2正则化的Ridge模型。在正式介绍这两种模型之前,笔者还是想带大家复习一下过拟合和正则化等机器学习关键问题。

正则化与L1范数

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

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

9b1da2fe6494998a5fe96b6822951871.png

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

      继续回到公式。第一项经验误差函数在机器学习中无疑地位重要,但它不是笔者今天要讲的,今天要讲的是公式的第二项:正则化项。第二项中 λ 为正则化系数,通常是大于 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正则化约束。其形式如下所示:

a9658806df97775c2725fc19b69c7307.png

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

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

import numpy as npimport pandas as pddata = 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)

b1d182a5ce6c334580f604ca6679d339.png

定义参数初始化函数:

# 定义参数初始化函数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 = np.vectorize(sign)vec_sign(np.zeros((3,1))) 

3ae9f933713d2d018cf0b58f51ad6dba.png

在MSE损失函数的基础上定义Lasso损失:

# 定义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    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_train    return y_hat, loss, dw, db

定义Lasso训练过程函数:

# 定义训练过程def lasso_train(X, y, learning_rate=0.01, epochs=300):    loss_list = []    w, b = initialize(X.shape[1])    for i in range(1, epochs):        y_hat, loss, dw, db = l1_loss(X, y, w, b, 0.1)        w += -learning_rate * dw        b += -learning_rate * db        loss_list.append(loss)                if i % 50 == 0:            print('epoch %d loss %f' % (i, loss))        params = {            'w': w,            'b': b        }        grads = {            'dw': dw,            'db': db        }    return loss, loss_list, params, grads

执行训练:

# 执行训练示例loss, loss_list, params, grads = lasso_train(X_train, y_train, 0.01, 500)

04cc26737a6d3d62b7b085d44b7aa772.png

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

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

import numpy as npfrom sklearn.metrics import r2_scoreclass Lasso():    def __init__(self):        pass        def prepare_data(self):        data = np.genfromtxt('./example.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:]        return X_train, y_train, X_test, y_test        def initialize_params(self, dims):        w = np.zeros((dims, 1))        b = 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 = X.shape[0]        num_feature = X.shape[1]                y_hat = np.dot(X, w) + b        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*np.vectorize(self.sign)(w)        db = np.sum((y_hat - y)) / num_train        return y_hat, loss, dw, db        def lasso_train(self, X, y, learning_rate, epochs):        loss_list = []        w, b = self.initialize_params(X.shape[1])        for i in range(1, epochs):            y_hat, loss, dw, db = self.l1_loss(X, y, w, b, 0.1)            w += -learning_rate * dw            b += -learning_rate * db            loss_list.append(loss)                        if i % 300 == 0:                print('epoch %d loss %f' % (i, loss))                        params = {                'w': w,                'b': b            }            grads = {                'dw': dw,                'db': db            }        return loss, loss_list, params, grads            def predict(self, X, params):        w = params['w']        b = params['b']        y_pred = np.dot(X, w) + b        return y_pred    if __name__ == '__main__':    lasso = Lasso()    X_train, y_train, X_test, y_test = lasso.prepare_data()    loss, loss_list, params, grads = lasso.lasso_train(X_train, y_train, 0.01, 3000)    print(params)    y_pred = lasso.predict(X_test, params)    print(r2_score(y_test, y_pred))

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

# 导入线性模型模块from sklearn import linear_model# 创建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_)

d81aa0a5b64683bab604308b2986ff5d.png

以上就是本节内容,下一节我们继续来看基于L2正则化的Ridge回归。

更多内容可参考笔者GitHub地址:

https://github.com/luwill/machine-learning-code-writing

参考资料:

https://www.analyticsvidhya.com/blog/2017/06/a-comprehensive-guide-for-linear-ridge-and-lasso-regression/

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

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

相关文章

山东理工大学计算机学院学号,计算机组成原理课程设计--山东理工大学计算机学院...

《计算机组成原理课程设计--山东理工大学计算机学院》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《计算机组成原理课程设计--山东理工大学计算机学院(14页珍藏版)》请在人人文库网上搜索。1、山东理工大学计算机学院课 程 设 计计算机组成原理班 级 姓 名 学 号 指…

Java 8快多少?

Java SE 8已于昨天发布 。 传统上&#xff0c;每个新的主要JRE版本都提供免费的性能提升。 我们还能再得到免费的午餐吗&#xff1f; 这次收益有多大&#xff1f; 让我们对其进行基准测试。 基准方法 使用3个不同的JRE版本&#xff08;SunJDK 1.6.0_26 &#xff0c;OpenJDK 1…

Win10 OpenCV3.3.0+VS2013配置大坑,OpenCV解决方案编译报错“找不到python36_d.lib”错误...

今天因为想要用OpenCV做图像识别&#xff0c;小白一个&#xff0c;在网上找到一个教程&#xff0c;但是需要配置OpenCV3.3.0的环境&#xff0c;于是又在网上找OpenCV3.3.0VS2013&#xff08;因为我之前已经安过了VS2013&#xff09;&#xff0c;前面的都顺利执行&#xff0c;但…

正在编写推箱子游戏的自动求解程序

网上搜索了一下&#xff0c;有好多人现成的产品&#xff0c;不少国产的。编写这个程序只是为了回忆一下算法。不能丢了。 自动求解有俩种方案&#xff1a;一个是求最小行走步骤&#xff0c;一个是求最小推箱子数目。 第一种算法简单些&#xff0c;只要将小人推动的四个方向进行…

JS面向对象编程

什么是面向对象编程&#xff08;OOP&#xff09;&#xff1f;用对象的思想去写代码&#xff0c;就是面向对象编程。 面向对象编程的特点 抽象&#xff1a;抓住核心问题封装&#xff1a;只能通过对象来访问方法继承&#xff1a;从已有对象上继承出新的对象多态&#xff1a;多对…

mvp的全称_是让人提神醒脑的 MVP、MVVM 关系精讲!

前言很高兴见到你&#xff01;我是《Jetpack MVVM 精讲》的独立原创作者 KunMinX&#xff0c;GitHub star 8.7k&#xff0c;专注于深度思考和 Jetpack MVVM 的分享。关于 MVP 和 MVVM 本质和区别的文章&#xff0c;本来我是不想写的&#xff0c;因为经过长达一年的耳濡目染 和对…

启航考研计算机课程,计算机考研专业课如何备考

计算机考研科目多&#xff0c;任务重&#xff0c;我们应该如何在有限的时间里更高效的复习&#xff0c;看一下天任启航考研为大家总结的复习计划吧!1、有计划&#xff0c;重基础计算机学科专业基础综合考试涵盖数据结构、计算机组成原理、操作系统和计算机网络基础等学科专业基…

IntelliJ中的实时模板

如上所述这里 &#xff0c;的IntelliJ的现场模板可以让你轻松地插入预定义的代码片段到你的源代码。 我在下面发布了一些我最常用的模板&#xff0c;到GitHub上模板文件完整列表的链接&#xff08;作为我设置新IntelliJ环境时的参考&#xff09;以及将IntelliJ设置文件添加到G…

链家广州二手房的数据与分析——爬取数据

之前在博客分享了利用 R 和 rvest 包爬虫的基础方法。现在就来实战一下&#xff1a;爬取链家网广州 40,000 套二手房的数据。 之前在 Web Scraping with R 说过的爬虫方法在这篇中就不在赘述了。这里就分享怎么样爬取网站中翻页的数据。 >> Web Scraping across Multiple…

Vue脚手架搭建项目

全局安装vue脚手架 $ npm install -g vue-cli 卸载方法 $ npm uninstall -g vue-cli 查看vue版本&#xff08;注意&#xff1a;大写的V&#xff09; $ vue -V 创建项目 $ vue init webpack vue-app ? Project name vue-app ? Project description Vue Project ? Author Pr…

es安全组端口_从零开始在远程服务器(Linux)上搭建es,eshead和ik分词器

一、资源准备远程服务器一个&#xff08;本教程为CentOS 64位&#xff09;注&#xff1a;ik分词器版本需与es版本统一jdk1.8.0elasticsearch-head-master.zip二、开放端口注&#xff1a;本例采用的是阿里云服务器1.登录阿里云&#xff0c;选择控制台2.找到左上角的三条白线--》…

sipp模拟freeswitch分机测试(SIP协议调试)

1、freeswitch安装 1) 网上很多安装方法都不靠谱&#xff0c;系统版本&#xff0c;各种依赖库一堆问题&#xff0c;下面是验证的可行的。 yum install -y http://files.freeswitch.org/freeswitch-release-1-6.noarch.rpm epel-releaseyum install -y freeswitch-config-vanill…

hd计算机技术,BD和HD的区别是什么?

BD和HD的区别是什么?我们在网上下载电影的时候&#xff0c;往往发帖子的童鞋会提示我们影片的规格&#xff0c;如所谓BD1280或者HD1024等等&#xff0c;一些朋友搞不清楚这是什么意思&#xff0c;实际上我们只能说BD和HD的区别是什么&#xff0c;关于1280和1024那完全是分辨率…

Java比以往任何时候都摇滚

在TIOBE索引上 &#xff0c;Java和C长期以来一直排名第一和第二&#xff0c;并且随着最近发布的JDK 8 GA的发布&#xff0c;对于我们的社区来说&#xff0c;情况不会变得更糟。 Java简直就是岩石&#xff01; 它是构建几乎所有应用程序的最佳平台。 但是&#xff0c;为什么Ja…

滚动条判断是否滑动到顶部底部

/*** [滚动条]*/$(window).scroll(function() {var scrollTop $(this).scrollTop(); // 滚动条距离顶部的高度console.log("滚动条距离顶部的高度-->" scrollTop);var scrollHeight $(document).height(); // 当前页面的总高度console.log("当前页面的总…

DotNet软件开发框架

这是我4月份发在donews博客上的文章,现在都转到博客园来&#xff0c;风满袖希望进一步阐述你的架构&#xff0c;我就将这篇文章转移到博客园。原文&#xff1a;http://blog.donews.com/shanyou/archive/2005/04/23/347792.aspx 以我个人的能力&#xff0c;没有足够的时间和…

vue 拷贝 数组_vue 使用lodash实现对象数组深拷贝操作

我就废话不多说了&#xff0c;大家还是直接看代码吧~export default {mounted() {this.init();},methods: {init() {let lodash require(lodash);let obj1 {a: 1,b: { f: { g: 1 } },c: [1, 2, 3],h: () > {return 123;},k: undefined};let obj2 lodash.cloneDeep(obj1);…

VBA代码分行

VBA代码分行如果是语句可以直接在要换行的位加一个空格一个下划&#xff1a; Dim MyPath As String, MyName As String, _ tmpPath As String如果是字符串可以加以加一个空格一个&和一个空格加一个下划线&#xff1a;x "ABCDEFG" & _"HIJKLMNO" 转…

[Swift通天遁地]五、高级扩展-(6)对基本类型:Int、String、Array、Dictionary、Date的扩展...

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号&#xff1a;山青咏芝&#xff08;shanqingyongzhi&#xff09;➤博客园地址&#xff1a;山青咏芝&#xff08;https://www.cnblogs.com/strengthen/&#xff09;➤GitHub地址&a…

JavaFX中的塔防(5)

这是本使用FXGameEngine在JavaFX中创建塔防游戏的正在进行的教程的第5部分。 敌人现在飞向目标的攻击路径&#xff0c;炮塔瞄准并射击。 因此&#xff0c;最重要的部分在那里&#xff0c;但是仍然缺少许多细节。 游戏只是开始而没有给我们机会为下一个浪潮做准备。 它不显示分数…