多特征线性回归模型

news2024/11/16 18:00:50

一、预测目标和原始数据展示

(一)预测目标:

通过Economy..GDP.per.Capita.(GDP)和Freedom预测Happiness.Score

(二)部分数据展示:

特征有很多,本文研究Economy..GDP.per.Capita.(GDP)和Freedom,也就是用Economy..GDP.per.Capita.(GDP)和Freedom预测Happiness.Score。

原始数据链接: 

链接:https://pan.baidu.com/s/1yUsHkwGyZafYCvdZu0YHNg?pwd=z6bp 
提取码:z6bp

二、数学原理及其应用

(一)所用参数介绍:

Y:我们需要预测的真实值,也就是Happiness.Score(自由指数)

X1:Economy..GDP.per.Capita.(GDP)

X2:Freedom(我理解为一个国家的自由度,调查得到)

θ1:X1的系数

θ2:X2的系数

ε:误差 

α:学习率

θ0:偏置项

(二)θ代表什么?

  若Y=X1+X2,那么代表着X1、X2对结果Y的影响是相同的,X1取一个数,X2取一个数,那么加起来就是Y。显而易见,GDP+Freedom != Happiness.Score,那么就需要两个数作为X1、X2的系数,来找到θ1和θ2,使得GDP和Freedom对Happiness.Score的影响达到一个最合适的比重,我们的核心目标,就是求得θ1和θ2。

(三)预测公式:

 注意这里θX是代表θ1X1+θ2X2,称为预测值。ε是误差。上述公式分开写应该如下:

 我们希望的是误差越小越好,因为误差越小,我们的预测值就越接近于真实值。

(四)偏置项

在线性回归中,偏置项也被称为截距(intercept),是指模型中的一个常数项,用于调整模型的拟合程度。偏置项通常表示自变量为0时的响应变量值,即直线在y轴上的截距。

偏置项的存在可以使得模型更加灵活,能够更好地拟合数据。如果模型中不包含偏置项,则拟合的直线必须经过原点。

简单理解,就是截距。

(五)前提引入:

1.误差独立并且具有相同的分布,服从均值为0,方差为σ^2的高斯分布。

这个问题我也理解不彻底,只是先作为一个前提条件提出。

2.我们这里所说的X、Y、θ都不单单指一个数,而是一个矩阵,由于运算需要,以上公式需要改动一下,对θ矩阵求转置。

 

(六)使误差最小:

高斯分布公式:

应用到本文中: 

 

我们的目标是希望的是误差越小越好,因为误差越小,我们的预测值就越接近于真实值。

要使误差越小,就要使似然函数越大,在似然函数之前,需先了解最大似然估计:

  假如一个箱子里有很多很多红球和黑球,数量足够庞大,就假设有70亿个,我任意抽五个球,设抽到黑球的概率为θ,那么抽到红球的概率为1-θ

可以得到似然函数:

 现在抽到的这三黑两红,就是一组观测数据,我要用这组数据,去估计箱子里红球和黑球各有多少,那么我就要使这组数据出现的概率最大,简单来说,如果某个参数值能够使得观测数据出现的概率更大,那么这个参数更有可能是其实际的参数。因为我就抽了这五个,那我应该希望这组观测数据出现的概率更大,才能估计箱子里红球和黑球各有多少。

  而似然函数就可以衡量参数与观测数据的匹配程度,所以说要使似然函数越大越好。

  这里就是数学问题了,我现在想要在似然函数最大的情况下求得θ,那就对θ求导并使其函数只等于0,因为导数反应的是函数的变化率,或者说是切线斜率,当函数到达最高点时,函数的变化率或者说是切线斜率就等于0,想想一个开口向下的抛物线函数。在独立同分布的条件下,联合概率密度等于边缘概率密度的乘积。 

回到线性回归中。

 现在,得到了一个常数和一个函数,我们称他为损失函数,要使似然函数最大,那么问题进一步转化为了让损失函数最小。我们把损失函数定义出来,如下:

 

 想要解决时损失函数最小的问题,需要用到梯度下降算法,但在这之前,其原理需要用到高数中的方向导数与梯度。

(七)方向导数与梯度

  高数书中这么引入方向导数:偏导数反映的是函数沿坐标轴方向的变化率,但许多物理现象告诉我们,只考虑沿坐标轴方向的变化率是不够的,例如:热空气要向冷的地方流动,气象学中就要确定大气温度,气压沿着某些方向的变化率,因此,我们有必要来讨论函数沿任一指定方向的变化率问题。

  梯度下降算法得到loss函数的最小值,而下降不能胡乱下降,需要找到一个方向,也就是函数沿任一指定方向的变化率,以下来证明沿哪个方向下降:

   这是一个常见的高数题,请先记住题中的梯度向量:

  梯度量永远指向方向导数变化最大的向,换句话说,梯度向量的方向是函数上升最快的方向。

那么现在,进入梯度下降算法。

(八)梯度下降 

  梯度下降算法的基本思路是通过不断迭代来更新模型参数,直到达到最小化目标函数的效果。具体地,给定一个初始点,我们计算当前点的负梯度(即梯度的相反数),并沿着负梯度的方向更新参数。重复这个过程,直到收敛到一个局部极小值或全局极小值。 在梯度下降算法中,学习率是一个非常关键的参数。它决定了每一次迭代中,更新参数的幅度大小。这个学习率,可以理解为步长。

  本文研究两个特征值,Economy..GDP.per.Capita.(GDP)和Freedom,对应的损失函数定义和更新参数θ如下:

 梯度量永远指向方向导数变化最大的向,换句话说,梯度向量的方向是函数上升最快的方向。所以说虽然求导后得负,但要取反。上述更新参数的算法为批量梯度下降。

以上就为我理解的原理,下面进入代码模块

三、代码模块

(一)数据预处理

#Preprocess_data.py
import numpy as np
import pandas as pd

def Preprocess_data(train_X1):
    Mean_value = np.mean(train_X1,0) #求得均值
    Standard_deviation = np.std(train_X1,0) #求得标准差

    train_X1 = (train_X1 - Mean_value)/Standard_deviation

    sample_number = train_X1.shape[0]
    train_X1 = np.hstack((np.ones((sample_number, 1)), train_X1))
    
    return train_X1

为什么要对数据进行预处理?

  如果两种数据相差太大,那么会对预测结果造成非常大的误差,假如说要用年龄和身高作为预测数据的话,例如:年龄:[20,21,10,18,27,33,60......],身高:[180,170,175,169,166,185,187......],两位数和三位数的相差太大了,那么求得的他们的系数θ也会相差很大,造成的是身高对预测结果的影响远远大于年龄对预测结果的影响,这样的误差对模型十分致命,所以,我们要对数据进行预处理。

归一化预处理:

  通过将每个特征的值减去均值,并除以标准差,实现了对特征值的归一化。这样做可以使得各个特征的取值范围相对统一,避免某些特征因为数值范围过大而在优化过程中权重变化较小或者被主导的问题。参考概率论中的随机变量标准化正态分布。

train_X1 = np.hstack((np.ones((sample_number, 1)), train_X1))

  在二(四)中我们提到偏置项,为数据添加一列1,就是为了得到偏置项,也就是截距。

(二)梯度下降算法实现

#Linear_Regression.py
import numpy as np
from Preprocess_data import Preprocess_data

class LinearRegression:
    def __init__(self,train_X1,train_Y):
        train_X1 = Preprocess_data(train_X1)
        self.train_X1 = train_X1
        self.train_Y = train_Y

        self.theta = np.zeros(((self.train_X1.shape[1]),1))
        
    def train(self,alpha,train_times):
        record_loss = self.gradient_descent(alpha,train_times)
        return self.theta,record_loss
    
    def gradient_descent(self,alpha,train_times):
        record_loss = []
        for _ in range(train_times):
            self.gradient_step(alpha)
            record_loss.append(self.compute_loss(self.train_X1,self.train_Y))
        return record_loss
        
    def gradient_step(self,alpha):
        prediction = LinearRegression.hypothesis(self.train_X1,self.theta)
        delta = prediction - self.train_Y
        theta = self.theta
        Sample_number = self.train_X1.shape[0]
        theta = theta - alpha*(1/Sample_number)*(np.dot(delta.T,self.train_X1)).T
        self.theta = theta

    @staticmethod
    def hypothesis(train_X1,theta):
        prediction = np.dot(train_X1,theta)
        return prediction
    
    def compute_loss(self,train_X1,train_Y):
        sample_number = train_X1.shape[0]
        delta = LinearRegression.hypothesis(self.train_X1,self.theta)- train_Y
        loss = (1/2)*np.dot(delta.T,delta)/sample_number #使用均方误差来衡量线性回归模型的拟合程度
        return loss[0][0]
    
    def predict(self,X1_predictions):
        X1_predictions = Preprocess_data(X1_predictions)
        final_prediction = LinearRegression.hypothesis(X1_predictions,self.theta)
        return final_prediction

self.theta = np.zeros(((self.train_X1.shape[1]),1))

  数据预处理中我们为了得到偏置项为数据添加了一列1,由于矩阵相乘的特点同时也是为了得到偏置项,我们按照数据的列数,创建theta的行数。

theta = theta - alpha*(1/Sample_number)*(np.dot(delta.T,self.train_X1)).T
  这一步就是二(八)中批量梯度下降数学表达式的实现。

@staticmethod

  通过将方法定义为静态方法,可以直接通过类名调用该方法,而不需要先创建类的实例。这在某些情况下可以简化代码的编写和调用方式。 

(三)数据传入和模型

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
from Linear_Regression import LinearRegression

data = pd.read_csv('D:\\Programming\\MicrosoftVSCodeData\\MachineLearning\\data\\world-happiness-report-2017.csv')

train_data = data.sample(frac=0.8)
test_data = data.drop(train_data.index)

X1_title = "Economy..GDP.per.Capita."
X2_title = "Freedom"
Y_title = "Happiness.Score"

X_train = train_data[[X1_title, X2_title]].values
Y_train  = train_data[[Y_title]].values

test_X = test_data[[X1_title, X2_title]].values
test_Y = test_data[[Y_title]].values

X = data[[X1_title, X2_title]]
y = data[Y_title]

train_times = 500  
alpha = 0.01  

mesh_size = .02
margin = 0

# Condition the model on sepal width and length, predict the petal width
model = LinearRegression(X_train,Y_train)
(theta, loss_history) = model.train(alpha,train_times)

print('开始损失',loss_history[0])
print('结束损失',loss_history[-1])
plt.plot(range(train_times), loss_history)
plt.title('loss_function')
plt.show()

# Create a mesh grid on which we will run our model
x_min, x_max = X[X1_title].min() - margin, X[X1_title].max() + margin
y_min, y_max = X[X2_title].min() - margin, X[X2_title].max() + margin
xrange = np.arange(x_min, x_max, mesh_size)
yrange = np.arange(y_min, y_max, mesh_size)
xx, yy = np.meshgrid(xrange, yrange)

# Condition the model on sepal width and length, predict the petal width
pred = model.predict(np.c_[xx.ravel(), yy.ravel()])
pred = pred.reshape(xx.shape)

# Generate the plot
fig = px.scatter_3d(train_data, x=X1_title, y=X2_title, z=Y_title)
fig.update_traces(marker=dict(size=10))
fig.add_trace(go.Surface(x=xrange, y=yrange, z=pred, name='Predict_Happiness'))

fig.add_trace(go.Scatter3d(
    x=test_data[X1_title],
    y=test_data[X2_title],
    z=test_data[Y_title],
    mode='markers',
    marker=dict(
        size=10,
        color='red'
    ),
    name='test_data'
))

fig.show()

真没找到合适的多特征线性回归模型,不得已出此下策用非线性的模型改成线性,原模型如下: 

 模型来源:Ml regression in Python (plotly.com)

将模型代码copy,数据改成自己的数据即可。如果网站加载缓慢的,用UU加速器,搜索学术资源进行加速(没有打广告)。

模型改动:添加了以下代码把测试数据加入图中进行对比和画出损失函数图像。

fig.add_trace(go.Scatter3d(
    x=test_data[X1_title],
    y=test_data[X2_title],
    z=test_data[Y_title],
    mode='markers',
    marker=dict(
        size=10,
        color='red'
    ),
    name='test_data'
))

print('——————————————————————————')

print('开始损失',loss_history[0])
print('结束损失',loss_history[-1])
plt.plot(range(train_times), loss_history)
plt.title('loss_function')
plt.show()

四、程序调试和模型展示

经数据代入方程计算得出误差大约在0.4左右,如果把剩余的6个特征也加入方程,误差可更小。

 

五、参考课程和鸣谢

【多元微分专题】第六期:方向导数和梯度的直观理解_哔哩哔哩_bilibili

9-多特征回归模型_哔哩哔哩_bilibili

 高斯分布 - 知乎 (zhihu.com)

【梯度下降】3D可视化讲解通俗易懂_哔哩哔哩_bilibili

每天一个数学小知识——导数的定义_哔哩哔哩_bilibili

有些参考文章可能未列出,感谢各位老师的教导!

本人学术不精,如有错误望指正,感谢! 

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

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

相关文章

B端企业形象设计的正确姿势,你学会了吗?

如今,企业形象设计在B端市场中变得越来越重要。它是企业与客户之间建立联系的桥梁,也是吸引目标客户的重要方式。为了帮助您打造一个独特而专业的企业形象设计,我将为您提供十个步骤。 步骤1:了解企业定位和目标 在设计B端企业形…

Angular模板语法

1 Angular数据文本绑定 Angular 中使用{{}}绑定业务逻辑里面定义的数据 <div class"title"> {{title}}</div>2 Angular模板里面绑定属性 [title]"student"绑定动态属性 ts: public title: string zhaoshuai-lc html: <div [title]"…

自制目录扫描工具并由py文件转为exe可执行程序

心血来潮让ChatGPT写了一个目录扫描工具&#xff0c;然后进行了一定的修改和完善&#xff0c;可以实现对网站目录的一个简单扫描并输出扫描结果&#xff0c;主要包括存在页面、重定向页面和禁止访问页面。 虽然代码很简单&#xff0c;但是做这个东西的过程还是挺有意思的&…

Jmeter只能做性能测试吗?

Jmeter除了可以性能测试&#xff0c;还能做接口测试 1、Jmeter和Fiddler&#xff0c;Postman有什么区别? Fiddler&#xff1a;虽然有接口测试功能&#xff0c;很少用来做接口测试。 一般用Fiddle来做抓包和异常测试&#xff0c;辅助接口测试。Postman&#xff1a; 是接口调试…

求任意连续子段的最小值之和

一道超级经典的单调栈问题&#xff0c;本题的关键在于你不要同时两边取等号&#xff0c;不然相等的区间会重复计算 还有记得开long long #include<bits/stdc.h> using namespace std; using lllong long; const int N 2e510; int n; ll a[N]; ll l[N]; ll r[N]; int m…

cudnn too short

原因是libcudnn.so为软链接&#xff0c;相当于快捷键&#xff0c;但是没有映射到真正的libcudnn.so.8.9.5上 cd /usr/local/cuda-11.6/lib64 ln -s libcudnn.so.8.9.5 libcudnn.so.8 ln -s libcudnn.so.8.9.5 libcudnn.so

VMware安装RedHat8.3虚拟机

red hat enterprise linux 8.3 ios镜像 链接&#xff1a;https://pan.baidu.com/s/1HbgXTh8q_YWlVVs8VAa14g?pwdot10 提取码&#xff1a;ot10 Red Hat Enterprise Linux&#xff08;RHEL&#xff09; 是一款由红帽公司开发和支持的商业操作系统。RHEL 8.3是RHEL 8系列的一个…

数据库事务提交后才发送MQ消息解决方案

项目场景&#xff1a; 在项目开发中常常会遇到在一个有数据库操作的方法中&#xff0c;发送MQ消息&#xff0c;如果这种情况消息队列效率比较快&#xff0c;就会出现数据库事务还没提交&#xff0c;消息队列已经执行业务&#xff0c;导致不一致问题。举个应用场景&#xff0c;…

stm32 ADC

目录 简介 stm32的adc 框图 ①电压输入范围 ②输入通道 ​编辑③ADC通道 ④ADC触发 ⑤ADC中断 ⑥ADC数据 ⑦ADC时钟 ADC的四种转换模式 hal库代码 标准库代码 简介 自然界的信号几乎都是模拟信号&#xff0c;比如光亮、温度、压力、声音&#xff0c;而为了方便存储、…

容器:软件性能测试的最佳环境

容器总体上提供了一种经济的和可扩展的方法来测试产品在实际情况下的性能&#xff0c;同时还能保持较低的资源成本和开销成本。 软件性能和可伸缩性是我们谈论应用程序开发时经常遇到的话题。一个很大的原因是应用程序的性能和可伸缩性直接影响其在市场上的成功。一个应用程序…

搭建Qt5.7.1+kylinV10开发环境、运行环境

1.下载Qt源码 Index of / 2.编译Qt 解压缩qt-everywhere-opensource-src-5.7.1.tar.gz 进入到qt-everywhere-opensource-src-5.7.1/qtbase/mkspecs这个目录下&#xff0c; 2.1找到以下目录 复制他&#xff0c;然后改名linux-x86-arrch64&#xff0c;博主这里名字取的有些问…

历年网规上午真题(2017年)

解析:D/C 计算机主要性能指标:时钟频率(主频)、运算速度、运算精度、内存大小、数据处理速率(PDR)等 数据库主要指标:最大并发、负载均衡能力、最大连接数等 解析:A 敏捷开发是一种应对快速变化的需求的一种软件开发方法,是一种以人为核心、迭代、循序渐进的开发方…

深度学习之基于Yolov5闯红灯及红绿灯检测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、闯红灯及红绿灯检测系统![请添加图片描述](https://img-blog.csdnimg.cn/8f260c2ed5ed4d8596e27d38abe42745.jpeg)四. 总结 一项目简介 基于Y…

生成独立运行的QT程序

前言 使用windeployqt程序生成独立运行的QT程序。 方法 1.在QT Creator使用release构建运行一下代码&#xff0c;不使用debug模式&#xff0c;将release文件夹中生成的***.exe文件复制到一个新的文件夹下。 2.打开 Qt 5.14.2(MinGW 7.3.0 64-bit) 进入exe文件所在的目录执…

Java精品项目62基于Springboot+Vue实现的大学生在线答疑平台(编号V62)

Java精品项目62基于SpringbootVue实现的大学生在线答疑平台(编号V62) 大家好&#xff0c;小辰今天给大家介绍一个基于SpringbootVue实现的大学生在线答疑平台(编号V62)&#xff0c;演示视频公众号&#xff08;小辰哥的Java&#xff09;对号查询观看即可 文章目录 Java精品项目…

Temu新规,12岁以下儿童产品必需提供CPC认证

近日Temu发布儿童用品合规通知&#xff1a;为保障Temu平台消费者的合法权益&#xff0c;保障儿童类商品在目的国的正常销售及合规要求&#xff0c;针对以12岁及以下儿童为主要使用对象的产品&#xff0c; 卖家需提供CPC认证&#xff0c;要求说明&#xff1a; 1、所有产品均需…

linux 下 物理迁移 mysql 数据库 不能启动问题

1、授权问题 # chown -R 777 /app/db/mysql 2、/etc/my.cnf配置问题 [mysqld] basedir/app/db/mysql datadir/app/db/mysql/data socket/app/db/mysql/mysql.sock.lock innodb_buffer_pool_size128M innodb_force_recovery 1 symbolic-links0 [mysqld_safe] log-error/app/…

半方差函数详解

1 引言 托布勒的地理第一定律指出&#xff0c;“一切都与其他事物有关&#xff0c;但近处的事物比远处的事物更相关。 在半变异函数的情况下&#xff0c;更接近的事物更可预测&#xff0c;变异性更小&#xff0c;而遥远的事物则难以预测&#xff0c;相关性也较低。 例如&…

做CSGO游戏搬砖前,这五个问题必须了解

相信经常看我文章的人或多或少都已经了解steam搬砖项目&#xff0c;也叫CSGO游戏搬砖项目&#xff0c;还有人叫它&#xff1a;国外steam游戏汇率差项目&#xff0c;无论怎么称呼&#xff0c;都是同一个项目。虽然我已经实操Steam搬砖项目超过三年&#xff0c;带领了数百名学员踏…