多项式回归初探及实践

多项式回归初探及实践

起因
学弟这学期在上数模课,这次的作业是 根据 2000~2021年的人口数量,估计22年的人口数。换言之,就是给你一部分的训练数据,需要拟合出一个曲线,以此来测试另外的数据。
这不是机器学习入门的回归嘛,就来了劲了 玩一玩~

准备工作
emm,因为某些原因,学弟选择了六次多项式,那我也就训练一只六次多项式;

首先,数据如下,其中红色框框为测试数据,其余部分为训练数据:
在这里插入图片描述

首先,训练一元多项式,如下: y = f ( x ) = θ 0 + θ 1 x + θ 2 x 2 + . . . + θ n x n y=f(x)=\theta_0+\theta_1x+\theta_2x^2+...+\theta_nx^n y=f(x)=θ0+θ1x+θ2x2+...+θnxn

采用的损失函数是均方误差MSE: J ( θ ) = 1 m ∑ i = 1 m ( f ( x ( i ) ) − y ( i ) ) 2 J(\theta)=\frac{1}{m}\sum_{i=1}^{m}{(f(x^{(i)})-y^{(i)})^2} J(θ)=m1i=1m(f(x(i))y(i))2

并使用梯度下降的方法,对于参数 θ \theta θ 的梯度为:
∂ J ∂ θ j = 1 m ∑ i = 1 m ( f ( x ( i ) ) − y ( i ) ) x j ( i ) \frac{\partial J}{\partial \theta_j}=\frac{1}{m}\sum_{i=1}^{m}{(f(x^{(i)})-y^{(i)})x_j^{(i)}} θjJ=m1i=1m(f(x(i))y(i))xj(i)

所以,参数更新方程为:
θ j = θ j − η ∂ J ∂ θ j = θ j − η m ∑ i = 1 m ( f ( x ( i ) ) − y ( i ) ) x j ( i ) \theta_j=\theta_j-\eta\frac{\partial J}{\partial \theta_j}=\theta_j-\frac{\eta}{m}\sum_{i=1}^{m}{(f(x^{(i)})-y^{(i)})x_j^{(i)}} θj=θjηθjJ=θjmηi=1m(f(x(i))y(i))xj(i)

我使用了随机梯度下降法,参数更新如下:
θ j = θ j − η ∂ J ∂ θ j = θ j − η ( f ( x ( k ) ) − y ( k ) ) x j ( k ) \theta_j=\theta_j-\eta\frac{\partial J}{\partial \theta_j}=\theta_j-\eta(f(x^{(k)})-y^{(k)})x_j^{(k)} θj=θjηθjJ=θjη(f(x(k))y(k))xj(k)

同时,还把数据进行了标准化,加速参数的迭代: z ( i ) = x ( i ) − μ σ z^{(i)}=\frac{x^{(i)}-\mu}{\sigma} z(i)=σx(i)μ,其中 μ \mu μ为训练样本的均值, σ \sigma σ为训练样本的标准差;

训练!
因为是六次函数,学习率太高会导致很容易跳出去,这里我采用的是 1 e − 5 1e^{-5} 1e5,误差较小的同时,训练速度也不是很慢;

import numpy as np
import matplotlib.pyplot as plt


train=np.loadtxt('1.csv', delimiter=',', skiprows=1)
train_x=train[:,0]
train_y=train[:,1]

theta=np.random.rand(7)

def to_matrix(x):
    return np.vstack([np.ones(x.shape[0]),x,x**2,x**3,x**4,x**5,x**6]).T

def f(x):
    return np.dot(x,theta)

mu=train_x.mean()    #获取平均值
sigma=train_x.std()    #获取标准差

def standardize(x):
    return (x-mu)/sigma

def MSE(x,y):   #均方误差
    return (1/x.shape[0])*np.sum((y-f(x))**2)

train_x=standardize(train_x)

X=to_matrix(train_x)    #矩阵化


plt.plot(train_x,train_y,'o')
plt.show()

ETA=1e-5    #学习率
diff=1    #误差的差值
count=0    #更新次数

errors=[]    #均方误差的历史记录
errors.append(MSE(X,train_y))


while diff>1e-5:
    p=np.random.permutation(X.shape[0])
    for x,y in zip(X[p,:],train_y[p]):
        theta=theta-ETA*(f(x)-y)*x

    errors.append(MSE(X,train_y))
    diff=errors[-2]-errors[-1]
    count+=1
    log='第{}次: theta={}, 差值={:.4f}'
    print(log.format(count, theta, diff))

x=np.linspace(-2,2,100)
plt.plot(train_x,train_y,'o')
plt.plot(x,f(to_matrix(x)))
plt.show()
print(MSE(X, train_y))
p=[22]
print(f(to_matrix(standardize(p))))

最后拟合出来的图形,如下:
在这里插入图片描述
最后的 θ \theta θ参数,以及MSE和2022年的预测人口如下:

1337659: theta=[ 1.33911935e+03  4.85124258e+01  2.69310404e+01  8.74366182e-01
 -2.21498077e+01 -7.65711382e-01  4.50309967e+00], 差值=0.0000
MSE=3.8565485574153895
2022=[1426.37429178]

2022年的人口预测误差为:0.01033751135446032667979430222839

正则化
考虑到误差还是在1%左右,并且图形只在训练数据邻域内拟合的不错,猜测大概率出现了过拟合的情况;
所以采用正则化的方式,降低过拟合度:
向上面所使用的目标函数加入下面的正则化项: R ( θ ) = λ 2 ∑ j = 1 m θ j 2 R(\theta)=\frac{\lambda}{2}\sum_{j=1}^{m}\theta_j^2 R(θ)=2λj=1mθj2
即:
J ( θ ) = 1 m ∑ i = 1 m ( f ( x ( i ) ) − y ( i ) ) 2 + λ 2 ∑ j = 1 m θ j 2 J(\theta)=\frac{1}{m}\sum_{i=1}^{m}{(f(x^{(i)})-y^{(i)})^2}+\frac{\lambda}{2}\sum_{j=1}^{m}\theta_j^2 J(θ)=m1i=1m(f(x(i))y(i))2+2λj=1mθj2

因为 θ 0 \theta_0 θ0只有参数,被称为偏置项,故不对他进行正则化, λ \lambda λ是决定正则化影响程度的正的常数,这个值需要自己定。

正则化项的微分如下:
∂ R ( θ ) ∂ θ j = λ θ j \frac{\partial R(\theta)}{\partial \theta_j}=\lambda\theta_j θjR(θ)=λθj

因此,当前的参数更新方程为:
θ j = θ j − η ( ∂ J ∂ θ j + λ θ j ) = θ j − η ( 1 m ∑ i = 1 m ( f ( x ( i ) ) − y ( i ) ) x j ( i ) + λ θ j ) \theta_j=\theta_j-\eta(\frac{\partial J}{\partial \theta_j}+\lambda\theta_j)=\theta_j-\eta(\frac{1}{m}\sum_{i=1}^{m}{(f(x^{(i)})-y^{(i)})x_j^{(i)}}+\lambda\theta_j) θj=θjη(θjJ+λθj)=θjη(m1i=1m(f(x(i))y(i))xj(i)+λθj)

import numpy as np
import matplotlib.pyplot as plt


train=np.loadtxt('1.csv', delimiter=',', skiprows=1)
train_x=train[:,0]
train_y=train[:,1]

theta=np.random.rand(7)

def to_matrix(x):
    return np.vstack([np.ones(x.shape[0]),x,x**2,x**3,x**4,x**5,x**6]).T

def f(x):
    return np.dot(x,theta)

mu=train_x.mean()    #获取平均值
sigma=train_x.std()    #获取标准差

def standardize(x):
    return (x-mu)/sigma

def MSE(x,y):   #均方误差
    return (1/x.shape[0])*np.sum((y-f(x))**2)

train_x=standardize(train_x)

X=to_matrix(train_x)    #矩阵化


plt.plot(train_x,train_y,'o')
plt.show()

# ETA=0.00011    #学习率
ETA=0.00004    #学习率
diff=1    #误差的差值
count=0    #更新次数
LAMBDA=0.00661    #正则化常量

errors=[]    #均方误差的历史记录
errors.append(MSE(X,train_y))


while diff>1e-5:
    #正则化项,偏置项不用正则化,所以用常量
    reg_term=LAMBDA*np.hstack([0,theta[1:]])
    p=np.random.permutation(X.shape[0])
    for x,y in zip(X[p,:],train_y[p]):
        theta=theta-ETA*((f(x)-y)*x+reg_term)

    errors.append(MSE(X,train_y))
    diff=errors[-2]-errors[-1]
    count+=1
    log='第{}次: theta={}, 差值={:.4f}'
    print(log.format(count, theta, diff))

x=np.linspace(-2,2,100)
plt.plot(train_x,train_y,'o')
plt.plot(x,f(to_matrix(x)))
plt.show()
print(MSE(X, train_y))
p=[22]
print(f(to_matrix(standardize(p))))

通过调整 λ \lambda λ和学习率 η \eta η,当前得到的结果如下:

232154: theta=[1341.30275915   43.84239659   13.91964783    6.33130563  -10.04948196
   -2.18130811    1.65564268], 差值=0.0000
MSE=1.5442272555955348
2022=[1411.76770428]

拟合出的图像如下:
在这里插入图片描述

2022年的人口预测误差为:-0.00087093739817818640298063437646092%

我采用了L2正则化法,通过抑制参数的影响,从而减少过拟合;也可以通过L1正则化法,把多次函数,去掉没用的高次项,变为更简单的函数来减少过拟合。

完结撒花~
也算是顺利完成了叭 真棒


学弟用的最小二乘法,通过解方程来获得参数,精度比我的好,他的MSE很小(没办法,迭代只能近似,毕竟后面的梯度太小了,再多次的迭代作用也不大)
这里附上他的推导过程吧,有兴趣可以学习一下:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大学生考研的意义?

当我拿起笔头,准备写这个话题时,心里是非常难受的,因为看到太多的学生在最好的年华,在自由的大学本应该开拓知识,提升认知,动手实践,不断尝试和试错,不断历练自己跳出学生思维圈&…

web实现太极八卦图、旋转动画、定位、角度、坐标、html、css、JavaScript、animation

文章目录前言1、html部分2、css部分3、JavaScript部分4、微信小程序演示前言 哈哈 1、html部分 <div class"great_ultimate_eight_diagrams_box"><div class"eight_diagrams_box"><div class"eight_diagrams"><div class&…

学会这12个Python装饰器,让你的代码更上一层楼

学会这12个Python装饰器&#xff0c;让你的代码更上一层楼 Python 装饰器是个强大的工具&#xff0c;可帮你生成整洁、可重用和可维护的代码。某种意义上说&#xff0c;会不会用装饰器是区分新手和老鸟的重要标志。如果你不熟悉装饰器&#xff0c;你可以将它们视为将函数作为输…

Android 9.0 Launcher3双层(抽屉)高斯模糊(毛玻璃)背景功能的实现

1.前言 在9.0的系统rom定制化开发中,在定制Launcher3的功能需求开发中,对于抽屉式即双层桌面的workspace的app列表排序的功能,也是常有的需求, 把常用的app图标放在前面,其他的可以放在列表后面做个整体的排序,这就需要了解app列表排序的流程,然后根据需求来实现app排序…

Springboot——自定义Filter使用测试总结

文章目录前言自定义过滤器并验证关于排除某些请求的方式创建测试接口请求测试验证异常过滤器的执行流程注意事项资料参考前言 在Java-web的开发领域&#xff0c;对于过滤器和拦截器用处还是很多&#xff0c;但两者的概念却极易混淆。 过滤器和拦截器都是采用AOP的核心思想&am…

【python绘图】matplotlib+seaborn+pyecharts学习过程中遇到的好看的绘图技巧(超实用!)(持续更新中!)

目录一些必要的库一些写的还不错的博客按照图像类型扇形图——可视化样本占比散点图——绘制双/多变量分布1. 二维散点图2. seaborn的jointplot绘制3. seaborn的jointplot绘制&#xff08;等高线牛逼版&#xff09;组合点阵图sns.pairplot叠加图Area Plot按照功能绘制混淆矩阵绘…

图像修复与去噪

博主简介 博主是一名大二学生&#xff0c;主攻人工智能研究。感谢让我们在CSDN相遇&#xff0c;博主致力于在这里分享关于人工智能&#xff0c;c&#xff0c;Python&#xff0c;爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主&#xff0c;博主会继续更新的&#xff0c…

Python 基础教程【2】:条件语句和循环语句

本文已收录于专栏&#x1f33b;《Python 基础》文章目录1、流程控制语句1.1 顺序语句1.2 条件语句1.2.1 if语句注意事项1.2.2 三元运算符1.2.3 自动类型转换1.3 循环语句1.3.1 while 循环1.3.2 for-in 循环1.3.3 for...else 循环1.3.4 break 和 continue 的区别2、实践——猜数…

蓝桥杯刷题冲刺 | 倒计时24天

作者&#xff1a;指针不指南吗 专栏&#xff1a;蓝桥杯倒计时冲刺 &#x1f43e;马上就要蓝桥杯了&#xff0c;最后的这几天尤为重要&#xff0c;不可懈怠哦&#x1f43e; 文章目录1.修剪灌木2.统计子矩阵1.修剪灌木 题目 链接&#xff1a; 修剪灌木 - 蓝桥云课 (lanqiao.cn) 找…

【pygame游戏】Python实现蔡徐坤大战篮球游戏【附源码】

前言 话说在前面&#xff0c;我不是小黑子~&#x1f60f; 本文章纯属技术交流~娱乐 前几天我获得了一个坤坤打篮球的游戏&#xff0c;也给大家分享一下吧~ 好吧&#xff0c;其实并不是这样的游戏&#xff0c;往下慢慢看吧。 准备工作 开发环境 Python版本&#xff1a;3.7.8 …

17.电话号码的字母组合(深度递归遍历解决经典老题)

前文C深度递归遍历解决"电话号码的字母组合问题"&#xff0c;本题考察的比较全面&#xff0c;考察到vector的使用&#xff0c;深度遍历以及递归的熟练度&#xff0c;希望能对铁子们有所帮助一&#xff0c;题目链接&#xff1a;https://leetcode.cn/problems/letter-c…

Python的30个编程技巧

1. 原地交换两个数字 Python 提供了一个直观的在一行代码中赋值与交换&#xff08;变量值&#xff09;的方法&#xff0c;请参见下面的示例&#xff1a; x,y 10,20 print(x,y) x,y y,x print(x,y) #1 (10, 20) #2 (20, 10) 赋值的右侧形成了一个新的元组&#xff0c;左侧立即解…

软测面试了一个00后,绝对能称为是内卷届的天花板

前言 公司前段缺人&#xff0c;也面了不少测试&#xff0c;结果竟然没有一个合适的。一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资也不低&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。令我印象最深的是一个00后测试员&#xf…

数据结构One——绪论

本喵是FW视频封面最终版宝子&#xff0c;你不点个赞吗&#xff1f;不评个论吗&#xff1f;不收个藏吗&#xff1f; 最后的最后&#xff0c;关注我&#xff0c;关注我&#xff0c;关注我&#xff0c;你会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#…

ChatGPT是如何训练得到的?通俗讲解

首先声明喔&#xff0c;我是没有任何人工智能基础的小白&#xff0c;不会涉及算法和底层原理。 我依照我自己的简易理解&#xff0c;总结出了ChatGPT是怎么训练得到的&#xff0c;非计算机专业的同学也应该能看懂。看完后训练自己的min-ChatGPT应该没问题 希望大牛如果看到这…

程序员必会技能—— 使用日志

目录 1、为什么要使用日志 2、自定义日志打印 2.1、在程序中得到日志对象 2.2、使用日志对象打印日志 2.3、日志格式 3、日志的级别 3.1、日志级别的分类 3.2、日志级别的设置 4、持久化日志 5、更简单的日志输出——lombok 5.1、如何在已经创建好的SpringBoot项目中添加…

【IoT】嵌入式驱动开发:IIC子系统

IIC有三种接口实现方式 三种时序对比: 图1 IIC子系统组成 图2 图3 IIC操作流程 设备端 1.i2c_get_adapter 2.i2c_new_device(相当于register设备) 3.I2c_put_adapter 驱动端 1.填充i2c_driver 2.i2c_add_driver(相当于register驱动) 3.在probe中建立访问方式 client相…

Qt浏览器开发:关于QCef以及qcefview开发原理

CEFCEF全称是Chromium Embedded Framework&#xff0c;它是Chromium的Content API的封装库&#xff0c;基于Google Chromium 的开源项目&#xff0c;而Google Chromium项目主要是为Google Chrome应用开发的&#xff0c;而CEF的目标则是为第三方应用提供可嵌入浏览器支持.目前CE…

做技术,最忌讳东张西望

又好长时间没更新&#xff0c;研二了&#xff0c;忙着做实验、写论文、发论文&#xff0c;再加上给我导做一些事情&#xff08;都习惯了&#xff0c;以前很不爽的事情&#xff0c;现在居然能这么平静的说出来&#xff09;。 但这不是我今天说的重点&#xff0c;而是另外一件事…

ChatGPT解答:python大批量读写ini文件时,性能很低,有什么解决方法吗,给出具体的思路和实例

ChatGPT解答&#xff1a; python大批量读写ini文件时&#xff0c;性能很低&#xff0c;有什么解决方法吗&#xff0c;给出具体的思路和实例 ChatGPTDemo Based on OpenAI API (gpt-3.5-turbo). python大批量读写ini文件时&#xff0c;性能很低&#xff0c;有什么解决方法吗&…
最新文章