使用Numpy时多项式系数出错

2 投票
2 回答
3327 浏览
提问于 2025-04-20 01:28

我正在使用 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。

我觉得这个多项式函数可能被归一化或偏移了。我可能在这里遇到的是一个数学问题,而不是编程问题,但任何帮助都非常欢迎,因为我需要写下这个多项式,而我不确定它的正确形式。谢谢。

更多信息: http://docs.scipy.org/doc/numpy/reference/generated/numpy.polynomial.polynomial.Polynomial.html#numpy.polynomial.polynomial.Polynomial

2 个回答

1

Ruips。

你的例子有三个问题:

  1. 你用四个数据点去拟合一个五次多项式。这种情况叫做“欠定”,可能会产生一些警告信息。不过这不是你问题的主要原因。

  2. 你期望 pol(0) 的表现和 numpy.polyval 一样,但实际上并不是这样。我也不太确定它的具体功能。这个类提供了一个 __call__ 方法,这让 pol(0) 可以工作,但我查找后发现没有相关的文档(可以参考 Polynomial 文档)。而 numpy.polynomial.polynomial 里有自己版本的 polyval。我会把它、np.polyval 和一个自制的版本 test_polyval 一起测试。

  3. 最重要的是,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!'
5

多项式的系数是为了提高数值稳定性而进行缩放和偏移处理的。你可以选择将它转换成一个“正常”的多项式,或者直接使用这个系列,只需将 off + scl*x 代替 x,其中 offscl 是通过 pol.mapparms 返回的。如果你想转换成标准形式(不推荐这样做),可以使用 pol.convert(domain=[-1, 1])

撰写回答