线性回归算法详解

news2024/9/23 1:27:13

目录

线性回归算法

线性回归方程

误差项分析

似然函数求解

线性回归求解

梯度下降算法

下山方向选择

梯度下降优化

梯度下降策略对比

学习率对结果的影响

代码实现

线性回归算法

线性回归是回归算法中最简单、实用的算法之一,在机器学习中很多知识点都是通用的,掌握一个 算法相当于掌握一种思路,其他算法中会继续沿用的这个思路。

假设某个人去银行准备贷款,银行首先会了解这个人的基本信息,例如年龄、工资等,然后输入银 行的评估系统中,以此决定是否发放贷款以及确定贷款的额度,那么银行是如何进行评估的呢?下面详细介绍银行评估系统的建模过程。假设下表是银行贷款数据,相当于历史数据。

银行评估系统要做的就是基于历史数据建立一个合适的回归模型,只要有新数据传入模型中,就会 返回一个合适的预测结果值。在这里,工资和年龄都是所需的数据特征指标,分别用x1和x2表示,贷款额度就是最终想要得到的预测结果,也可以叫作标签,用y表示。其目的是得到x1、x2与y之间的联系,一旦找到它们之间合适的关系,这个问题就解决了。

线性回归方程

目标明确后,数据特征与输出结果之间的联系能够轻易得到吗?在实际数据中,并不是所有数据点 都整齐地排列成一条线。

圆点代表输入数据,也就是用户实际得到的贷款金额,表示真实值。平面代表模型预测的结果,表 示预测值。可以观察到实际贷款金额是由数据特征x1和x2共同决定的,由于输入的特征数据都会对结果产生影响,因此需要知道x1和x2对y产生多大影响。我们可以用参数θ来表示这个含义,假设θ1表示年龄的参数,θ2表示工资的参数,拟合的平面计算式如下:

既然已经给出回归方程,那么找到最合适的参数θ这个问题也就解决了。

再强调一点,\theta _{0}为偏置项,但是在上式中并没有\theta _{0}x_{0}项,在进行数值计算时,为了使得整体能用矩阵的形式表达,即便没有x_{0}项也可以手动添加, 只需要在数据中加入一列x_{0}并且使其值全部为1即可,结果不变。

误差项分析

看到这里,大家可以发现回归方程的预测值和样本点的真实值并不是一一对应的。说明数据的真实值和预测值之间是有差异的,这个差异项通常称作误差项\varepsilon。它们之间的关系可以这样解释:在样本中,每一个真实值和预测值之间都会存在一个误差。

其中,i为样本编号;\theta ^{T}x^{\left ( i \right )}为预测值;y^{\left ( i \right )}为真实值。

关于这个误差项,接下来所有的分析与推导都是由此产生的。先把下面这句看起来有点复杂的解释搬出来:误差\varepsilon是独立且具有相同的分布,并且服从均值为0方差为\theta ^{2}的高斯分布。

所谓独立,例如,张三和李四一起来贷款,他俩没关系也互不影响,这就是独立关系,银行会平等 对待他们(张三来银行跟银行工作人员说:“后面那是我兄弟,你们得多贷给他点钱。”银行会理他 吗?)。

相同分布是指符合同样的规则,例如张三和李四分别去农业银行和建设银行,这就很难进行对比分 析了,因为不同银行的规则不同,需在相同银行的条件下来建立这个回归模型。

高斯分布用于描述正常情况下误差的状态,银行贷款时可能会多给点,也可能会少给点,但是绝大 多数情况下这个浮动不会太大,比如多或少三五百元。极少情况下浮动比较大,例如突然多给20万,这种可能性就不大。下图是高斯分布曲线,可以发现在均值两侧较近地方的可能性较大,越偏离的情况可能性就越小。

这些知识点不是线性回归特有的,基本所有的机器学习算法的出发点都在此,由此也可以展开分 析,数据尽可能取自相同的源头,当拿到一份数据集时,建模之前肯定要进行洗牌操作,也就是打乱其顺序,让各自样本的相关性最低。

似然函数求解

现在已经对误差项有一定认识了,接下来要用它来实际干点活了,高斯分布的表达式为:

大家应该对这个公式并不陌生,但是回归方程中要求的是参数θ,这里好像并没有它的影子,没关系来转换一下,将y^{\left ( i \right )}=\theta ^{T}x^{i}+\varepsilon ^{i}代入上式,可得:

似然函数就是通过观察样本数据的情况来选择最合适的参数,从而得到与样本数据相似的结果。

上面这个式子基本思路就是找到最合适的参数来拟合数据点,可以把它当作是参数与数据组合后得到的跟标签值一样的可能性大小(如果预测值与标签值一模一样,那就做得很完美了)。对于这个可能性来说,大点好还是小点好呢?当然是大点好了,因为得到的预测值跟真实值越接近,意味着回归方程做得越好。所以就有了极大似然估计,找到最好的参数θ,使其与X组合后能够成为Y的可能性越大越好。

下面给出似然函数的定义:

其中,i为当前样本,m为整个数据集样本的个数。

此外,还要考虑,建立的回归模型应该是尽可能满足数据集 整体,所以需要考虑所有样本。一旦数据量较大,这个公式就会相当复杂, 这就需要对似然函数进行对数变换,让计算简便一些。

如果对上式做变换,得到的结果值可能跟原来的目标值不一样了,但是在求解过程中希望得到极值点,而非极值,也就是能使L(θ)越大的参数θ,所以当进行变换操作时,保证极值点不变即可。

在对数中,可以将乘法转换成加法,即log(A·B)=logA+logB

对上式两边计算其对数结果,可得:

一路走到这里,公式变换了很多,别忘了要求解的目标依旧是使得上式取得极大值时的极值点 (参数和数据组合之后,成为真实值的可能性越大越好)。先来观察一下,在减号两侧可以分成两部分,左边部分可以当作一个常数项,因为它与参数θ没有关系。对于右边部分来说,由于有平方项,其值必然恒为正。整体来看就是要使得一个常数项减去一个恒正的公式的值越大越好,由于常数项不变,那就只能让右边部分越小越好, 可以认为是一个常数,故只需让越小越好,这就是最小二乘法。

虽然最后得到的公式看起来既简单又好理解,就是让预测值和真实值越接近越好,但是其中蕴含的 基本思想还是比较有学习价值的,对于理解其他算法也是有帮助的。

线性回归求解

搞定目标函数后,下面讲解求解方法,列出目标函数列如下:

既然要求极值(使其得到最小值的参数θ),对上式计算其偏导数即可:

经过一系列的矩阵求导计算就得到最终的结果,但是,如果上式中矩阵不可逆会怎么样?显然那就得不到结果了。

其实大家可以把线性回归的结果当作一个数学上的巧合,真的就是恰好能得出这样一个值。但这和 机器学习的思想却有点矛盾,本质上是希望机器不断地进行学习,越来越聪明,才能找到最适合的参数,但是机器学习是一个优化的过程,而不是直接求解的过程。

梯度下降算法

机器学习的核心思想就是不断优化寻找更合适的参数,当给定一个目标函数之后,自然就是想办法 使真实值和预测值之间的差异越小越好,那么该怎么去做这件事呢?可以先来想一想下山问题。

为什么是下山呢?因为在这里把目标函数比作山,到底是上山还是下山问题,取决于你优化的目标 是越大越好(上山)还是越小越好(下山),而基于最小二乘法判断是下山问题。

那该如何下山呢?看起有两个因素可控制——方向与步长,首先需要知道沿着什么方向走,并且按 照该方向前进,在山顶大致一看很多条路可以下山,是不是随便选择一个差不多的方向呢?这好像有点随意,随便散散步就下山了。但是现在情况有点紧急,目标函数不会让你慢慢散步下去,而是希望能够快速准确地到达山坡最低点,这该怎么办呢?别着急——梯度下降算法来了。

下山方向选择

首先需要明确的是什么方向能够使得下山最快,那必然是最陡峭的,也就是当前位置梯度的反方向 (目标函数J(θ)关于参数θ的梯度是函数上升最快的方向,此时是一个下山问题,所以是梯度的反方向)。当沿着梯度方向下山的时候,位置也在不断发生变化,所以每前进一小步之后,都需要停下来再观察一下接下来的梯度变成什么方向,每次前进都沿着下山最快的也就是梯度的反方向进行

到这里相信大家已经对梯度下降有了一个直观的认识了,总结一下,就是当要求一个目标函数极值 的时候,按照机器学习的思想直接求解看起来并不容易,可以逐步求其最优解。首先确定优化的方向 (也就是梯度),再去实际走那么一步(也就是下降),反复执行这样的步骤,就慢慢完成了梯度下降任务,每次优化一点,累计起来就是一个大成绩。

在梯度下降过程中,通常每一步都走得很小心,也就是每一次更新的步长都要尽可能小, 才能保证整体的稳定,因为如果步长过大,可能偏离合适的方向。

梯度下降优化

我们的目标就是找到最合适的参数θ,使得目标函数值最小。这里除以m是尽可能取多的样本进行取平均计算。这里x是数据,y是标签,都是固定的,所以只有参数θ会对最终结果产生影响,此外,还需注意参数θ并不是一个值,可能是很多个参数共同决定了最终的结果。

当进行优化的时候,其中\theta _{0}\theta _{1}分别和不同的数据特征进行组合(例如工资 和年龄),按照之前的想法,既然x1和x2是相互独立的,那么在参数优化的时候自然需要分别考虑\theta _{0}\theta _{1}的情况,在实际计算中,需要分别对\theta _{0}\theta _{1}求偏导,再进行更新。

下面总结一下梯度下降算法。

第①步:找到当前最合适的方向,对于每个参数都有其各自的方向。

第②步:走一小步,走得越快,方向偏离越多,可能就走错路了。

第③步:按照方向与步伐去更新参数。

第④步:重复第1步~第3步。

首先要明确目标函数,可以看出多个参数都会对结果产生影响,那么要做的就是在各个参数上去寻 找其对应的最合适的方向,接下来就是去走那么一小步,为什么是一小步呢?因为当前求得的方向只是瞬时最合适的方向,并不意味着这个方向一直都是正确的,这就要求不断进行尝试,每走一小步都要寻找接下来最合适的方向。

梯度下降策略对比

原理还是比较容易理解的,接下来就要看实际应用了,这里假设目标函数仍然是上式。

在梯度下降算法中有3种常见的策略:批量梯度下降、随机梯度下降和小批量梯度下降,这3种策略 的基本思想都是一致的,只是在计算过程中选择样本的数量有所不同,下面分别进行讨论。

(1)批量梯度下降。此时需要考虑所有样本数据,每一次迭代优化计算在公式中都需要把所有的样本计算一遍,该方法容易得到最优解,因为每一次迭代的时候都会选择整体最优的方向。方法虽好,但也存在问题,如果样本数量非常大,就会导致迭代速度非常慢,下面是批量梯度下降的计算公式:

在更新参数的时候取了一个负号,这是因为现在要求解的是一个下山问题,即沿着梯度的反方向去前进。其中\frac{1}{m}表示对所选择的样本求其平均损失,i表示选择的样本数据,j表示特征。例如表示工资所对应的参数,在更新时数据也需选择工资这一列,这是一一对应的关系。在更新时还涉及系数a,其含义就是更新幅度的大小,也就是之前讨论的步长。

(2)随机梯度下降。考虑批量梯度下降速度的问题,如果每次仅使用一个样本,迭代速度就会大大提升。那么新的问题又来了,速度虽快,却不一定每次都朝着收敛的方向,因为只考虑一个样本有点太绝对了,要是拿到的样本是异常点或者错误点可能还会导致结果更差。下面是随机梯度下降的计算公式,它与批量梯度下降的计算公式的区别仅在于选择样本数量:

 (3)小批量梯度下降。综合考虑批量和随机梯度下降的优缺点,是不是感觉它们都太绝对了,要么全部,要么一个,如果在总体样本数据中选出一批不是更好吗?可以是10个、100个、1000个,但是程序员应该更喜欢16、32、64、128这些数字,所以通常见到的小批量梯度下降都是这类值,其实并没有特殊的含义。下面我们来看一下选择10个样本数据进行更新的情况:

本节对比了不同梯度下降的策略,实际中最常使用的是小批量梯度下降,通常会把选择的样本个数 叫作batch,也就是32、64、128这些数,那么数值的大小对结果有什么影响呢?可以说,在时间和硬件配 置允许的条件下,尽可能选择更大的batch吧,这会使得迭代优化结果更好一些。

学习率对结果的影响

选择合适的更新方向,这只是一方面,下面还需要走走看,可以认为步长就是学习率(更新参数值 的大小),通常都会选择较小的学习率,以及较多的迭代次数,正常的学习曲线走势如下图所示

由上图可见,随着迭代的进行,目标函数会逐渐降低,直到达到饱和收敛状态,这里只需观察迭代 过程中曲线的形状变化,具体数值还是需要结合实际数据。

如果选择较大的学习率,学习过程可能会变得不平稳,因为这一步可能跨越太大了,偏离了正确的方向。在迭代过程中出现不平稳的现象,目标函数始终没能达到收敛状态,甚至学习效果越来越差,这很可能是学习率过大或者选择样本数据过小以及数据预处理问题所导致的。

学习率通常设置得较小,但是学习率太小又会使得迭代速度很慢,那么,如何寻找一个适中的值呢?较大的学习率并不会使得目标函数降低,较小的学习率看起来还不错,可以选择较多的迭代次数来保证达到收敛状态,所以,在实际中宁肯花费更多时间,也不要做无用功。通用的做法就是从较小的学习率开始尝试,如果遇到不平稳现象,那就调小学习率。

代码实现

#线性回归代码
import numpy as np
from utils.features import prepare_for_training

class LinearRegression:

    def __init__(self,data,labels,polynomial_degree = 0,sinusoid_degree = 0,normalize_data=True):
        """
        1.对数据进行预处理操作
        2.先得到所有的特征个数
        3.初始化参数矩阵
        """
        (data_processed,
         features_mean, 
         features_deviation)  = prepare_for_training(data, polynomial_degree, sinusoid_degree,normalize_data=True)
         
        self.data = data_processed
        self.labels = labels
        self.features_mean = features_mean
        self.features_deviation = features_deviation
        self.polynomial_degree = polynomial_degree
        self.sinusoid_degree = sinusoid_degree
        self.normalize_data = normalize_data
        
        num_features = self.data.shape[1]
        self.theta = np.zeros((num_features,1))
        
    def train(self,alpha,num_iterations = 500):
        """
                    训练模块,执行梯度下降
        """
        cost_history = self.gradient_descent(alpha,num_iterations)
        return self.theta,cost_history
        
    def gradient_descent(self,alpha,num_iterations):
        """
                    实际迭代模块,会迭代num_iterations次
        """
        cost_history = []
        for _ in range(num_iterations):
            self.gradient_step(alpha)
            cost_history.append(self.cost_function(self.data,self.labels))
        return cost_history
        
        
    def gradient_step(self,alpha):    
        """
                    梯度下降参数更新计算方法,注意是矩阵运算
        """
        num_examples = self.data.shape[0] # 样本个数
        prediction = LinearRegression.hypothesis(self.data,self.theta)
        delta = prediction - self.labels
        theta = self.theta
        theta = theta - alpha*(1/num_examples)*(np.dot(delta.T,self.data)).T
        self.theta = theta
        
        
    def cost_function(self,data,labels):
        """
                    损失计算方法
        """
        num_examples = data.shape[0]
        delta = LinearRegression.hypothesis(self.data,self.theta) - labels
        cost = (1/2)*np.dot(delta.T,delta)/num_examples
        return cost[0][0]
        
        
        
    @staticmethod
    def hypothesis(data,theta):   
        predictions = np.dot(data,theta)
        return predictions
        
    def get_cost(self,data,labels):  
        data_processed = prepare_for_training(data,
         self.polynomial_degree,
         self.sinusoid_degree,
         self.normalize_data
         )[0]
        
        return self.cost_function(data_processed,labels)
    def predict(self,data):
        """
                    用训练的参数模型,与预测得到回归值结果
        """
        data_processed = prepare_for_training(data,
         self.polynomial_degree,
         self.sinusoid_degree,
         self.normalize_data
         )[0]
         
        predictions = LinearRegression.hypothesis(data_processed,self.theta)
        
        return predictions

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

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

相关文章

深入探讨Java JSON解析与HTML标签清除:详解与实例

“在Java开发中,解析和处理JSON文件是一项常见任务,尤其是当数据中包含大量HTML标签时,去除这些标签又是一项挑战。本文将详细讲解如何在Java中解析JSON文件,创建对应的实体类,并介绍去除HTML标签的方法,最…

RK3588开发板利用udp发送和接收数据

目录 1 send.cpp 2 receive.cpp 3 编译运行 4 测试 1 send.cpp #include <iostream> #include <string> #include <cstring> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> //…

【网络安全】Instagram 和 Meta 2FA 绕过漏洞

未经许可,不得转载。 文章目录 漏洞概述技术细节Meta 2FA 绕过步骤Instagram 2FA 绕过步骤总结漏洞概述 该漏洞允许攻击者在具有受害者Facabook账户权限的情况下,绕过 Meta 的双重身份验证 (2FA) 机制,实现账户接管;并且也能够绕过 Instagram 的双重身份验证 (2FA) 机制,…

堆排序的例题

答案&#xff1a;D C 知识点&#xff1a; 堆排序是把数组排成大顶堆或者小顶堆&#xff0c;选择根结点的最大值或者最小值&#xff0c;因此它是选择排序的方法 堆排序的方法是&#xff1a; 先把数组所有数据组成一个二叉树&#xff0c;然后调整结点与左右孩子树之间的位置&…

【Hot100】LeetCode—35. 搜索插入位置

目录 1- 思路二分 2- 实现⭐35. 搜索插入位置——题解思路 3- ACM 实现 题目连接&#xff1a;35. 搜索插入位置 1- 思路 二分 二分左区间的三种情况。由于目标值不一定在数组中&#xff0c;因此二分的过程中有三种情况判断 2- 实现 ⭐35. 搜索插入位置——题解思路 class So…

大模型参数高效微调技术原理综述(四)-Prompt Tuning

紧接着Stanford的Prefix Tuning论文&#xff0c;Google迅速发表了Prompt Tuning技术论文。Google声称该技术比Prefix Tuning更易上手且成本更低&#xff0c;因此该技术随后也成为了微调技术中的一个重要分支。 本文解读论文**《The Power of Scale for Parameter-Efficient Pr…

Java类加载器双亲委托模型概述

类加载器的双亲委派模型 模型图 加载原理 双亲委派模型的工作过程是&#xff1a;如果一个类加载器收到了类加载的请求&#xff0c;它首先不会自己去尝试加载这个类&#xff0c;而是把这个请求委派给父类加载器去完成&#xff0c;每一个层次的类加载器都是如此&#xff0c;因此所…

C/C++逆向:寻找mian函数(其他编译配置特征)

在上篇文章中写了在逆向中定位main函数几种方法&#xff0c;其中有一种方法是通过编译器特征定位 main 函数&#xff08;使用IDA分析简单demo程序获取特征&#xff0c;根据得到的特征可以定位相同编译器编译程序的main函数&#xff09;。在上一篇文章中我们提取了VS环境(VS2017…

【软件测试专栏】软件测试 — 概念篇

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;软件测试专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 软件测试 — 概念篇 关键词&#xff1a;软件需求、用户需求、开发…

从混乱到秩序:产品经理在需求变更中的关键角色

在软件开发过程中&#xff0c;需求是驱动整个项目的核心。需求的来源多种多样&#xff0c;包括客户、市场、领导等&#xff0c;产品经理的职责是将这些需求收集、整理并转化为可行的开发计划。本文将探讨需求的来源、产品经理的角色、软件开发中的挑战以及应对变化的策略。 需求…

Java小白一文讲清Java中集合相关的知识点(一)

集合 诞生缘由 数组 长度开始时必须指定&#xff0c;而且一旦指定&#xff0c;不能更改保存的必须为同一类型元素使用数组进行增/删元素所需要编写的代码–比较麻烦 Person[] pers new Person[1]; pers[0] new Person(); //此时增加新的Person对象呢&#xff1f; Person[…

【学习笔记】卫星通信NTN 3GPP标准化进展分析(一)-基本信息

一、引言&#xff1a; 本文来自3GPP Joern Krause, 3GPP MCC (May 14,2024) Non-Terrestrial Networks (NTN) (3gpp.org) 本文总结了NTN标准化进程以及后续的研究计划&#xff0c;是学习NTN协议的入门。 【学习笔记】卫星通信NTN 3GPP标准化进展分析&#xff08;一&#xf…

前端开发第二节课

HTML常用的标签 文本格式化标签 在网页中&#xff0c;有时需要为文字设置粗体、斜体或下划线等效果&#xff0c;这时就需要用到HTML中的文本格式化标签使文字以特殊的方式显示。 标签语义&#xff1a;突出重要性&#xff0c;比普通文字更重要。 加粗 <strong></st…

Spring框架;Spring中IOC简介及搭建;Spring中AOP简介;

一&#xff0c;Spring介绍 Spring 的全称&#xff1a; Spring Framework Spring是一个优秀的开源的轻量级的企业应用开发框架&#xff0c;是为了解决企业应用程序开发复杂性而创建的。它大大简化了java企业级开发的复杂性&#xff0c;提供了强大&#xff0c;稳定的功能&#xf…

XR-Frame 实现 始终朝向屏幕(相机)的面片与模型

wxml&#xff0c;xr-frame中plane平面默认是趴在场景中的&#xff0c;需要先绕x轴渲染90度&#xff0c; // 面片 <xr-node id"l" position"-3.0 0 0.0"><xr-mesh rotation"90 0 0" geometry"plane" uniforms"u_base…

浅析synchronized锁升级的原理与实现 2

本文内容是继我的上篇博客 浅析synchronized锁升级的原理与实现 1-CSDN博客 目录 各状态锁的升级场景 无锁 --> 轻量级锁 偏向锁 --> 轻量级锁 偏向锁 --> 重量级锁 轻量级锁 --> 重量级锁 总结 各状态锁的升级场景 下面我们结合代码看下各状态锁的升级场景。…

VL53L1CB TOF开发(2)----多区域扫描模式

VL53L1CB TOF开发.2--多区域扫描模式 概述视频教学样品申请源码下载硬件准备主要特点生成STM32CUBEMX串口配置IIC配置XSHUTGPIO1X-CUBE-TOF1堆栈设置函数说明初始化设置预设模式 (Preset mode)VL53L1_SetPresetModeVL53L1_SetDistanceMode时间预算单个ROI&#xff08;Single R…

从 Oracle 到 TiDB 丨数据库资源评估指南

原文来源&#xff1a; https://tidb.net/blog/5058e24f 本文作者&#xff1a;柳冬冬 导读 在当今技术飞速发展的时代&#xff0c;传统单机数据库正面临着前所未有的挑战。随着人工智能、云计算和大数据的崛起&#xff0c;企业对数据库的性能、可靠性和扩展性的需求日益增…

wordcloud兼figma的词云图片python生成

文章目录 一.Figma1.简介2.特点 二.代码构成1.详细代码2.word.py代码详解3.成果图 一.Figma 1.简介 Figma是一款全平台可使用的使用软件&#xff0c;和Sketch功能差不多&#xff1b;但是他可以在Mac&#xff0c;Windows PC&#xff0c;Linux计算机甚至Chromebook&#xff0c;…

中国各地级市-产业增加值、产业升级、产业结构高级化(2000-2021年)

产业增加值、产业升级和产业结构高级化是衡量地区经济发展水平的重要指标&#xff1a; 产业增加值&#xff1a;指在一定时期内&#xff0c;单位产值的增长部分&#xff0c;体现了产值、产量和增加值的综合增长能力。 产业升级&#xff1a;指通过技术进步和效率提升&#xff0c…