python函数拟合

  • 背景

图 1  xyz原数
最近在抖音直播数学答疑的时候,恰好有一位朋友问到了这个问题,已知x,z,y三列数据如上图所示,请问y的最后一位数是多少?

乍一看,还以为很简单,拎(抡)起粉笔就一顿操作(猛如虎)

(1)分别将x,z,y三列数据记作3个数列 { x n } , { z n } \{x_n\}, \{z_n\} { xn},{ zn} { y n } \{y_n\} { yn}, 其中n表示其所在数列的序号或位置。

(2)很容易发现如下规律
z n − x n = 6 (1) z_n-x_n=6 \tag{1} znxn=6(1)

x n + y n = x n + 1 (2) x_n+y_n=x_{n+1} \tag{2} xn+yn=xn+1(2)
以及

z n + y n = z n + 1 (3) z_n+y_n=z_{n+1} \tag{3} zn+yn=zn+1(3)

将(2)和(3)组合一下便得到(1),即

z n − x n = z n + 1 − x n + 1 = 6 (4) z_n-x_n=z_{n+1}-x_{n+1} =6 \tag{4} znxn=zn+1xn+1=6(4)

而问题相当于是要求 { y n } \{y_n\} { yn}的下一个 y n + 1 y_{n+1} yn+1,上面3个关系式中却没有任何项涉及到,故这些关系不能解决根本问题,现在摆在我们面前的有两条路

  • 找出数列 { x n } \{x_n\} { xn} , { z n } \{z_n\} { zn} 的下一项 m 和 m+6,然后利用(1)-(4)的关系进行求解 y n y_{n} yn 下一项 λ \lambda λ
序号 1 2 3 4 5 6 7 8 9
x -5 5 0 2 9 6 4 10 m
z 1 11 6 8 15 12 10 16 m+6
y 10 -5 2 7 -3 -2 6 λ \lambda λ
  • 直接找出 { y n } 和 { x n } , { z n } \{y_n\} 和\{x_n\}, \{z_n\} { yn}{ xn},{ zn} 之间的关系表达式, 即

y n = f ( x n , z n ) (5) y_n = f(x_n, z_n) \tag{5} yn=f(xn,zn)(5)

{ x n } \{x_n\} { xn} { z n } \{z_n\} { zn}的关系,(5)又可以改写成

y n = f ( x n ) (6) y_n = f(x_n) \tag{6} yn=f(xn)(6)

第一条道路相当于绕了一圈,简称间接法,第二条道路更直接,简称直接法,我们先采用直接法来进行解答

  • 先画出 { y n } 和 { x n } \{y_n\} 和\{x_n\} { yn}{ xn}散点图

x, y散点图

为了找出 { y n } 和 { x n } \{y_n\} 和\{x_n\} { yn}{ xn}之间的函数关系,我们可以先建立一个最简单最纯粹的假设

y = a x + b (7) y =ax+b \tag{7} y=ax+b(7)

没错,就是最简单的线性关系,然后拟合出来系数 a 和 b分别是 -0.97580645和5.0702765 (保留8位小数),这样 { y n } 和 { x n } \{y_n\} 和\{x_n\} { yn}{ xn}之间的函数关系便是

y = − 0.9758 x + 5.07 (8) y = -0.9758 x + 5.07\tag{8} y=0.9758x+5.07(8)

然后画出来拟合函数,观察其与原数列之间的差距

一次拟合
我们看到除了第1个点和第5个点靠得近,其余的点差距还是挺大的,既然一次拟合性能太差,那么我来个2次函数呗,即假设

y = a x 2 + b x + c (9) y =ax^2+bx+c \tag{9} y=ax2+bx+c(9)

2次拟合
观察发现2次函数拟合和1次函数拟合没啥大的区别,再继续提高拟合函数次数

4次时候
4次函数拟合

观察发现第1,3,4,5四个点都靠的比较近,差距在缩小,继续提高次数
5次的时候
5次函数拟合

观察发现第2,6,7三个点拟合的还不够完美,继续提高次数

6次的时候

6次函数拟合

此时,拟合曲线恰好经过数列 { y n } \{y_n\} { yn}的7点,可以认为拟合效果比较完美,此时的拟合函数为

y = − 0.01265 x 6 + 0.2035 x 5 − 0.591 x 4 − 4.176 x 3 + 22.7 x 2 − 24.32 x + 2 (10) y = -0.01265 x^6 + 0.2035 x^5 - 0.591 x^4 - 4.176 x^3 + 22.7 x^2 - 24.32 x + 2 \tag{10} y=0.01265x6+0.2035x50.591x44.176x3+22.7x224.32x+2(10)

将x = 10代入上(10)式,求得 y = -351.60606060605966
从y值可以猜出这是一个无限循环小数,循环节为6060,故最后所求的y值为

− 351. 6060 ˙ -351.\dot{6060} 351.6060˙

  • 完整代码
# -*- coding: utf-8 -*-
"""
Project name: 找规律
Description:
Created on Sun Sep 20 17:27:34 2020
@author: 帅帅de三叔    
"""
import numpy as np #导入数值分析模块
import matplotlib.pyplot as plt #导入绘图模块

x0 = [1, 2, 3, 4, 5, 6, 7]
x = [-5, 5, 0, 2, 9, 6, 4]
z = [1, 11, 6, 8, 15, 12, 10]
y = [10, -5, 2, 7, -3, -2, 6]

plt.figure(figsize = (6,4))
plt.scatter(x0, x, color = 'r', label = "x")
plt.scatter(x0, z, color = 'g', label = "z")
plt.scatter(x0, y, color ="brown", label = "y")

coef = np.polyfit(x, y, 6) #求出系数
print('拟合函数的系数 :\n', coef ) #打印出系数
funExpression = np.poly1d(coef) #求出表达式
print('拟合表达式 :\n',funExpression)  #打印出表达式
yFit =np.polyval(funExpression, x) #求出拟合函数的y值
print("拟合出来的y值:\n", yFit)
plt.plot(x0, yFit, color = 'blue', label ="fitting line")

nextY = np.polyval(funExpression, 10) #求出拟合函数的y值
print("所求的y的值为:", nextY )
plt.legend(loc = "upper left")
plt.show()

参考文献
1, https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.polyfit.html

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zengbowengood/article/details/108698905
今日推荐