使用polyfit通过30个点找到多项式函数

时间:2017-07-20 14:16:10

标签: python numpy

我需要找到完全适合30个数据点的29阶多项式函数。我们可以肯定,这样的功能存在。但是,numpy.polyfit的错误只在三点之后急剧增加。

import numpy as np

y = [126,  34,  78, 120,  83,  62, 104,   6,  70, 142, 147,  63,  35, 126,   9,  84,   7, 122,  93,  29,  95, 141,  42, 102,  38,  96, 130,  83, 138, 148]

print(len(y))

x = np.arange(len(y))
f = np.polyfit(x,y,30)

def eval_polynom(f, x):
    res = 0
    for i in range(len(f)):
        res += f[i] * x**(len(f)-i-1)

    return res  

for i in range(len(y)):
    print(y[i], " -- ", eval_polynom(f, x[i]))  

我的数据点是(x,y),x = [0,1,2,3,4,...,29]

输出

126  --  125.941598976
34  --  34.7366402172
78  --  73.703669116
120  --  134.514176467
83  --  51.6471546864
62  --  105.143046704
104  --  70.1470309453
6  --  13.808372367
70  --  347.425617622
142  --  -1281.11122538
...

有没有办法获得精确的多项式函数,使误差为0?

3 个答案:

答案 0 :(得分:1)

y - 绿色,多项式 - 红色,错误 - 蓝色,它的140度多项式

y - green, polynome - red, error - blue

  

我需要找到完全适合30个数据点的29阶多项式函数。我们可以肯定,这样的功能存在

为什么你确定这个?我尝试了一些曲折和可视化,并认为你的数据点不适合这样的polinome。

我尝试过切比雪夫的多项式,它做得更好,但即使用140度多项式也无法拟合这些值。

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from numpy.polynomial.chebyshev import chebfit,chebval
%matplotlib inline

y = [126,  34,  78, 120,  83,  62, 104,   6,  70, 142, 147,  63,  35, 126,   9,  84,   7, 122,  93,  29,  95, 141,  42, 102,  38,  96, 130,  83, 138, 148]

print(len(y))

x = np.arange(len(y))
c = chebfit(x, y, 30)

p = []
for i in np.arange(len(y)):
    p.append(chebval(i, c))

df = pd.DataFrame(data={'x': x, 'y': y, 'p': p})
df['diff'] = df['y'] - df['p']
sns.pointplot(x = 'x', y = 'y', data=df, color='green')
sns.pointplot(x = 'x', y = 'p', data=df, color='red')
sns.pointplot(x = 'x', y = 'diff', data=df, color='blue')

答案 1 :(得分:1)

eval_polynom函数中几乎肯定会出现整数溢出问题(由于指数较大),因为x中的值都是整数。尝试替换

res += f[i] * x**(len(f)-i-1)

res += f[i] * float(x)**(len(f)-i-1)

您可能最终会得到仍然不完全匹配的值,但请记住,浮点运算本质上是不准确的。如果数字变大则更是如此,就像这里的情况一样。

答案 2 :(得分:1)

虽然不准确,但如果使用NumPys polyval

,效果会更好
import numpy as np

y = [126,  34,  78, 120,  83,  62, 104,   6,  70, 142, 147,  63,  35, 126,   9,  84,   7, 122,  93,  29,  95, 141,  42, 102,  38,  96, 130,  83, 138, 148]

x = np.arange(len(y))
f = np.polyfit(x ,y, 30)

for i in range(len(y)):
    print(y[i], " -- ", np.polyval(f, x[i])) 

给出了

(126, ' -- ', 125.94427340268774)
(34, ' -- ', 34.674505165214924)
(78, ' -- ', 73.961360153890183)
(120, ' -- ', 133.96863767482208)
(83, ' -- ', 52.113307162099574)
(62, ' -- ', 105.65069882437891)
(104, ' -- ', 68.588480573695762)
(6, ' -- ', 14.814788499822299)
(70, ' -- ', 76.373263353880958)
(142, ' -- ', 149.39793233756134)
...

请注意,您应该使用29度多项式来拟合30个点。

enter image description here