多项式#

NumPy 中的多项式可以通过 便捷类 来“创建”、“操作”甚至“拟合”,这些类属于 NumPy 1.4 中引入的 numpy.polynomial 包。

在 NumPy 1.4 之前,numpy.poly1d 是首选类,为了保持向后兼容性,它仍然可用。然而,新的 polynomial 更完善,其 便捷类 为处理多项式表达式提供了更一致、更优的接口。因此,建议在新代码中使用 numpy.polynomial

注意

术语

“多项式模块”一词指的是在 numpy.lib.polynomial 中定义的旧 API,它包括 numpy.poly1d 类以及在 numpy 命名空间中可访问的以 poly 为前缀的多项式函数(例如 numpy.polyaddnumpy.polyvalnumpy.polyfit 等)。

“多项式包”一词指的是在 numpy.polynomial 中定义的新 API,它包括用于不同类型多项式的便捷类(PolynomialChebyshev 等)。

numpy.poly1d 迁移到 numpy.polynomial#

如上所述,定义在 numpy.lib.polynomial 中的 poly1d 和相关函数(如 numpy.polyfitnumpy.poly)被认为是遗留的,**不应**在新代码中使用。自 NumPy 1.4 版本以来,numpy.polynomial 包已成为处理多项式的首选。

快速参考#

下表重点介绍了用于常见任务的遗留多项式模块和多项式包之间的一些主要区别。为简便起见,导入了 Polynomial 类。

from numpy.polynomial import Polynomial

如何…

遗留 (numpy.poly1d)

numpy.polynomial

从系数创建多项式对象 [1]

p = np.poly1d([1, 2, 3])

p = Polynomial([3, 2, 1])

从根创建多项式对象

r = np.poly([-1, 1]) p = np.poly1d(r)

p = Polynomial.fromroots([-1, 1])

deg 次的多项式拟合到数据

np.polyfit(x, y, deg)

Polynomial.fit(x, y, deg)

在某点上求多项式的值 [2]

p(2.0)np.polyval([1, 2, 3], 2.0)

p(2.0)polyval(2.0, p.coef) (拟合后使用 p.convert().coef

迁移指南#

遗留的多项式模块 numpy.lib.polynomialnumpy.polynomial 之间存在显著差异。最显著的差异是多项式表达式系数的顺序。 numpy.polynomial 中的各种例程都处理从零次幂向上递增的系数级数,这与 poly1d 的约定顺序相反。记忆此规则的简单方法是:索引对应于次数,即 coef[i]i 次项的系数。

尽管约定上的差异可能会令人困惑,但从遗留多项式 API 迁移到新 API 非常直接。例如,以下演示了如何将代表表达式 \(x^{2} + 2x + 3\)numpy.poly1d 实例转换为代表相同表达式的 Polynomial 实例。

>>> import numpy as np
>>> p1d = np.poly1d([1, 2, 3])
>>> p = np.polynomial.Polynomial(p1d.coef[::-1])

除了 coef 属性外,多项式包中的多项式还具有 domainwindow 属性。这些属性在将多项式拟合到数据时最为相关,但应注意,具有不同 domainwindow 属性的多项式不被视为相等,也不能在算术运算中混合使用。

>>> p1 = np.polynomial.Polynomial([1, 2, 3])
>>> p1
Polynomial([1., 2., 3.], domain=[-1.,  1.], window=[-1.,  1.], symbol='x')
>>> p2 = np.polynomial.Polynomial([1, 2, 3], domain=[-2, 2])
>>> p1 == p2
False
>>> p1 + p2
Traceback (most recent call last):
    ...
TypeError: Domains differ

有关 domainwindow 属性的更多详细信息,请参阅 便捷类 的文档。

遗留多项式模块与多项式包之间的另一个主要区别是多项式拟合。在旧模块中,拟合是通过 polyfit 函数完成的。在多项式包中,首选 fit 类方法。例如,考虑对以下数据的简单线性拟合。

In [1]: rng = np.random.default_rng()

In [2]: x = np.arange(10)

In [3]: y = np.arange(10) + rng.standard_normal(10)

使用遗留的多项式模块,可以使用 polyfit 将线性拟合(即 1 次多项式)应用于这些数据。

In [4]: np.polyfit(x, y, deg=1)
Out[4]: array([0.87055444, 0.22350597])

使用新的多项式 API,首选 fit 类方法。

In [5]: p_fitted = np.polynomial.Polynomial.fit(x, y, deg=1)

In [6]: p_fitted
Out[6]: Polynomial([4.14100093, 3.91749496], domain=[0., 9.], window=[-1.,  1.], symbol='x')

请注意,系数是在由 windowdomain 之间的线性映射定义的缩放域中给出的。convert 可用于获取未缩放数据域中的系数。

In [7]: p_fitted.convert()
Out[7]: Polynomial([0.22350597, 0.87055444], domain=[-1.,  1.], window=[-1.,  1.], symbol='x')

polynomial 包的文档#

除了标准的幂级数多项式外,多项式包还提供了其他几种多项式,包括切比雪夫、埃尔米特(两种子类型)、拉盖尔多项式和勒让德多项式。这些每种都具有来自 numpy.polynomial 命名空间的可用的相关 便捷类,它提供了处理不同类型多项式的统一接口。

有关每种多项式单独定义的特定函数的文档,请参见相应的模块文档。

遗留多项式的文档#