通俗易懂之最小二乘法(附matlab和python例子实现)
共 3909字,需浏览 8分钟
·
2021-04-02 23:52
前言
最小二乘法也称最小平方法,是一种数学优化技术,通过最小化误差的平方和来寻找数据的最佳函数匹配。
感谢各友的鼓励与支持🌹🌹🌹,往期文章都在最后梳理出来了(●'◡'●)
👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇
线性函数模型
典型的一类函数模型是线性函数模型。最简单的线性式是y=b0x+b1写成矩阵形式为:
直接给出该式的参数解:
其中:
为x的算术平均值,也可解得如下形式:
最小二乘法原理
假设结果y
与m
个因素x[i]
有关,且为线性关系,即:
y = k[0] + k[1] * x[1] + k[2] * x[2] + ... + k[m] * x[m]
经过测量,现有n
组数据(n >= m)
,求合适的k[i]
,使得上述表达式与测量结果尽可能的相符。
最小二乘法的做法很简单,让所有残差的平方和最小即可
,设p[i]
表示第i组测试数据,把k[i]
看成未知数,最小化f
:
f = (p[1] - y[1]) ^ 2 + (p[2] - y[2]) ^ 2 + ... + (p[n] - y[n]) ^ 2
实例分析
这里举个简单例子说明最小二乘法的过程。现要用钱去买游戏币,售币处贴出公示如下:
10元 —— 11个游戏币
20元 —— 23个游戏币
50元 —— 58个游戏币
100元 —— 123个游戏币
显然,付的钱数与得到的游戏币存在某种线性关系,设有:y = ax + b
,代入以上数据得:
10a + b = 11
20a + b = 23
50a + b = 58
100a + b = 123
构造残差函数
f = (10a + b - 11) ^ 2 + (20a + b - 23) ^ 2 + (50a + b - 58) ^ 2 + (100a + b - 123) ^ 2
分别对a, b
求偏导,并令其等于0
,才能使f
取得最值。
20(10a + b - 11) + 40(20a + b - 23) + 100(50a + b - 58) + 200(100a + b - 123) = 0
2(10a + b - 11) + 2(20a + b - 23) + 2(50a + b - 58) + 2(100a + b - 123) = 0
解出结果:a = 1.2439, b = -2.2245
,从而关系式为:y = 1.2439x - 2.2245
。
有了该表达式,现在可以对未知点进行预测了,例如80块钱,大约可以买97个游戏币,而125元钱大约可以买153个。
python实现
import numpy as np
from scipy.optimize import leastsq
def func(p, x):
k, b = p
return k * x + b
def error(p, x, y):
return func(p, x) - y
X = np.array([10, 20, 50, 100])
Y = np.array([11, 23, 58, 123])
P = (0, 0)
ret = leastsq(error, P, args=(X, Y))
k, b = ret[0]
print(k, b)
运行结果:
解出k=1.24388, b=-2.2245
,与上面手算的一致。可以通过pyplot将数据以图的形式直观的展现出来。
import numpy as np
from scipy.optimize import leastsq
import matplotlib.pyplot as plt
def func(p, x):
k, b = p
return k * x + b
def error(p, x, y):
return func(p, x) - y
X = np.array([10, 20, 50, 100])
Y = np.array([11, 23, 58, 123])
P = (0, 0)
ret = leastsq(error, P, args=(X, Y))
k, b = ret[0]
print(k, b)
plt.figure()
plt.scatter(X, Y, color='red')
x = np.linspace(0, 200, 200)
y = k * x + b
plt.plot(x, y)
plt.show()
运行结果:
matlab实现例子
在matlab中,有现成的曲线拟合函数polyfit
,其也是基于最小二乘原理实现的,具体用法为:
ans=polyfit(x,y,n). 其中x,y为待拟合点的坐标向量,n为多项式的阶数。
下面代码是用polyfit函数来做曲线拟合:
clear
clc
x=[2,4,5,6,6.8,7.5,9,12,13.3,15];
[~,k]=size(x);
y=[-10,-6.9,-4.2,-2,0,2.1,3,5.2,6.4,4.5];
for n=1:9
ANSS=polyfit(x,y,n); %用polyfit拟合曲线
for i=1:n+1 %answer矩阵存储每次求得的方程系数,按列存储
answer(i,n)=ANSS(i);
end
x0=0:0.01:17;
y0=ANSS(1)*x0.^n ; %根据求得的系数初始化并构造多项式方程
for num=2:1:n+1
y0=y0+ANSS(num)*x0.^(n+1-num);
end
subplot(3,3,n)
plot(x,y,'*')
hold on
plot(x0,y0)
end
suptitle('不同次数方程曲线拟合结果,从1到9阶')
在分析时间与温度关系时,也会用到最小二乘法对其进行拟合。具体事例如下:
例如:对某日隔两小时测一次气温。设时间为ti,气温为Ci,i = 0,2 ,4,…,24。数据如下:
表2 温度(Ci)随时间(ti)变化关系
-----------------------------------------------------------
ti 0 2 4 6 8 10 12 14 16 18 20 22 24
-----------------------------------------------------------
ci 15 14 14 16 20 23 28 27 26 25 22 18 16
-----------------------------------------------------------
x = [0 2 4 6 8 10 12 14 16 18 20 22 24]
y = [15 14 14 16 20 23 26 27 26 25 22 18 16]
plot(x,y,'o')
grid on
hold on
% 三阶拟合 得到的 p = -0.0061 0.1474 -0.0246 13.7390是个多项式的系数
% 即拟合的曲线y = -0.0061*x3 + 0.1474*x2 - 0.0246*x + 13.7390 (其中x3表示x的3次方,x2同理)
p = polyfit(x,y,3)
x1 = 0:0.01:24
y1 = polyval(p,x1)
plot(x1,y1,'r')
axis([0 24 12 28]) % axis坐标轴范围设置
xlabel('温度(度)');
ylabel('时间(点)');
title('温度变化图','position', [18,10])
运行结果:
「❤️ 感谢大家」
如果你觉得这篇内容对你挺有有帮助的话:
- 点赞支持下吧,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)
- 欢迎在留言区与我分享你的想法,也欢迎你在留言区记录你的思考过程。
- 觉得不错的话,也可以阅读近期梳理的文章(感谢鼓励与支持🌹🌹🌹):
- 编程中的惰性思想、
- PyMySQL数据库搭建
- 看到这些代码,我自叹不如!!!
- GitHub 太慢?9 种方案可提速!
- 图像技术-人像动漫化
- 提高你的Python编码效率
- 0.052秒打开100GB数据,这个Python开源库火爆了!
- 小程序云开发资源的管理
- 教你用python进行数字化妆,可爱至极
- 加速Python列表和字典,让你代码更加高效
- 汇总超全的Matplotlib可视化最有价值的 50 个图表(附完整 Python 源代码)(三)
- 汇总超全的Matplotlib可视化最有价值的 50 个图表(附完整 Python 源代码)(二)
- 汇总超全的Matplotlib可视化最有价值的 50 个图表(附完整 Python 源代码)(一)
- 教你用Python制作实现自定义字符大小的简易小说阅读器
- 「查缺补漏」巩固你对算法复杂度的理解
- 汇总了32个为开发者提供的免费工具
- 教你通过python利用近邻法实现图片缩小后变成另一张图(类似幻影坦克)
- 30 行代码实现蚂蚁森林自动收能量
老铁,三连支持一下,好吗?↓↓↓
欢迎大家加入到知识星球这个大家庭,这里一定有与你志同道合的小伙伴,在这里大家可以一起交流,一起学习,一同吹逼,一同玩耍。。。
长按按钮 “识别二维码” 关注我更多精彩内容等着你哦
点分享
点点赞
点在