使用Numpy时多项式系数出错
我正在使用 numpy.polynomial.polynomial.Polynomial
这个类(来自Numpy库),目的是通过 fit()
方法将一些数据拟合成一个多项式函数。得到的多项式是正确的,我可以绘制它,并代入一些点来计算‘y’值,结果也都正确。问题是,Polynomial
类的 .coef
属性返回了一组系数,这些系数似乎经过了某种归一化或变化,我看不出具体是怎么回事。我想说的意思是这样的,接下来是代码:
x_vid = array([0.0, 50.0, 75.0, 100.0])
y_vid = array([0.0, 30.0, 55.0, 100.0])
pol = Polynomial.fit(x_vid, y_vid, 5) # The polynomial is OK!!
print pol.coef
这个 .coef
属性返回了下面这个数组:
30 38.16 17.93 9.98 2.06 1.85
这些系数是按升序排列的,所以这些系数代表了以下的多项式函数:
30 + 38.16x + 17.93x^2 + 9.98x^3 + 2.06x^4 + 1.85x^5
但是,这里就出现了问题,如果我在这个多项式中代入我值的范围 [0-100] 的任何值,它不会返回正确的值。尽管如果我这样做:
pol(0)
→ 我会得到0,这没问题,但很明显在我写的多项式中,当 x=0 时,它不会返回0。
我觉得这个多项式函数可能被归一化或偏移了。我可能在这里遇到的是一个数学问题,而不是编程问题,但任何帮助都非常欢迎,因为我需要写下这个多项式,而我不确定它的正确形式。谢谢。
2 个回答
Ruips。
你的例子有三个问题:
你用四个数据点去拟合一个五次多项式。这种情况叫做“欠定”,可能会产生一些警告信息。不过这不是你问题的主要原因。
你期望
pol(0)
的表现和numpy.polyval
一样,但实际上并不是这样。我也不太确定它的具体功能。这个类提供了一个__call__
方法,这让pol(0)
可以工作,但我查找后发现没有相关的文档(可以参考 Polynomial 文档)。而numpy.polynomial.polynomial
里有自己版本的polyval
。我会把它、np.polyval
和一个自制的版本test_polyval
一起测试。最重要的是,
Polynomial
类的系数顺序和numpy.polyfit
以及numpy.polyval
是不同的。在Polynomial
中,最高次的系数在列表或数组的最后。而在numpy
的函数中,最高次的系数是在最前面(可以参考 polyval 文档)。
下面的代码片段展示了如何在任意的 x 值上评估你 Polynomial
对象表示的多项式,同时也说明了为了让 numpy.polyval
有相同的表现,你需要用 coef[::-1]
来反转系数的顺序。我也可以用 numpy.fliplr
来反转系数的顺序。
import numpy as np
from numpy.polynomial.polynomial import Polynomial,polyval
from numpy import array
import sys
x_vid = array([0.0, 50.0, 75.0, 100.0])
y_vid = array([0.0, 30.0, 55.0, 100.0])
pol = Polynomial.fit(x_vid, y_vid, 5) # The polynomial is OK!!
# I've written this, which should do what numpy.polynomial.polynomial.polyval
# does, as a sanity check:
def test_polyval(polynomialInstance,xArray):
# check that xArray is a numpy.ndarray, using ndarray.shape
try:
y = np.zeros(xArray.shape)
except Exception as e:
sys.exit('polyval error: %s'%e)
# manually sum the polynomial terms on xArray
for exp,c in enumerate(polynomialInstance.coef):
y = y + c*x**exp
return y
# Define some random x values for testing, in the range of points used
# for fitting:
x = np.random.rand(100)*100
# Compute, using our own polyval function, then Polynomial.polyval,
# and finally using numpy.polyval, making sure to reverse the
# coefficient order for the last:
y_test_polyval = test_polyval(pol,x)
y_Polynomial_polyval = polyval(x,pol.coef)
y_numpy_polyval = np.polyval(pol.coef[::-1],x)
# Make sure the two results are within machine epsilon:
if np.allclose(y_test_polyval,y_numpy_polyval) and \
np.allclose(y_test_polyval,y_Polynomial_polyval):
print 'Hurray!'
多项式的系数是为了提高数值稳定性而进行缩放和偏移处理的。你可以选择将它转换成一个“正常”的多项式,或者直接使用这个系列,只需将 off + scl*x
代替 x
,其中 off
和 scl
是通过 pol.mapparms
返回的。如果你想转换成标准形式(不推荐这样做),可以使用 pol.convert(domain=[-1, 1])
。