【问题标题】:Why do numpy's polyfit and polyval expect polynomial coefficients in opposite order?为什么 numpy 的 polyfit 和 polyval 期望多项式系数的顺序相反?
【发布时间】:2020-08-31 11:29:36
【问题描述】:

我使用 numpy 的 polyfit 来拟合一些嘈杂的数据,然后想使用 polyval 来评估一些新点的拟合。出于某种原因,拟合效果很好,但polyval 只有在我反转多项式系数的顺序时才会给出正确的结果:

import numpy as np
import numpy.polynomial.polynomial as poly
import matplotlib.pyplot as plt

# a noisy line
x = np.linspace(0, 10, 100)
y = x + np.random.normal(0, 1, x.shape)

# calculate fit polynomial
fit_coeffs_poly = poly.polyfit(x, y, deg=1)
fit_polynomial_poly = poly.Polynomial(fit_coeffs_poly)(x)

# plot to check fit 
plt.plot(x, y, label='noisy')
plt.plot(x, fit_polynomial_poly, '-r', label='polyfit')
plt.legend(loc='lower right')
plt.show()

合身看起来不错:

polyval 仅在系数反转时有效:

>>> for i in range(0, 10):
>>>    print(np.polyval(fit_coeffs_poly, i))

0.9792056688016727
1.139755470535941
1.3003052722702093
1.4608550740044774
1.6214048757387456
1.781954677473014
1.9425044792072823
2.1030542809415502
2.2636040826758186
2.424153884410087

>>> for i in range(0, 10):
>>>    print(np.polyval(fit_coeffs_poly[::-1], i))

0.16054980173426825
1.139755470535941
2.1189611393376135
3.0981668081392866
4.077372476940959
5.056578145742631
6.035783814544304
7.0149894833459765
7.9941951521476495
8.973400820949323

我不禁觉得这在某种程度上是错误的,他们倒退是没有意义的。

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    我挖掘了很多并发现了发生了什么。事实证明 numpy 有两组多项式工具,一组在基本 numpy 库中,另一组在 numpy.polynomial 中,他们期望事情的顺序相反。 polyfitpolyval 在这两个库中都可以找到,并且在这个简单的情况下似乎操作相同,但它们的参数不同:

    来自numpy

    def polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False)
    def polyval(p, x)
    

    polyfitpolyval 都期望并返回从高到低度排序的多项式系数。

    来自numpy.polynomial

    def polyfit(x, y, deg, rcond=None, full=False, w=None)
    def polyval(x, c, tensor=True) 
    

    polyfitpolyval 都期望并返回从低到高度排序的多项式系数。另请注意,polyval 期望参数的顺序不同。

    这是一个快速演示:

    import numpy as np
    import numpy.polynomial.polynomial as poly
    import matplotlib.pyplot as plt
    
    # a noisy line
    x = np.linspace(0, 10, 100)
    y = x + np.random.normal(0, 1, x.shape)
    
    # calculate fit polynomial with base numpy
    fit_coeffs_np = np.polyfit(x, y, deg=1)
    fit_polynomial_np = poly.Polynomial(fit_coeffs_np[::-1])(x)
    print("numpy", fit_coeffs_np)
    
    # calculate fit polynomial with numpy.polynomial.polynomial
    fit_coeffs_poly = poly.polyfit(x, y, deg=1)
    fit_polynomial_poly = poly.Polynomial(fit_coeffs_poly)(x)
    print("poly", fit_coeffs_poly)
    
    # test some values
    for i in range(0, 10):
        print(np.polyval(fit_coeffs_np, i), poly.polyval(i, fit_coeffs_poly))
    
    # make a nice plot
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.plot(x, y, label='noisy')
    plt.plot(x, fit_polynomial_poly, '-g', label='np.poly')
    plt.plot(x, fit_polynomial_np, '-r', label='np')
    plt.legend(loc='lower right')
    plt.text(0, 10, 'np: {}'.format(fit_coeffs_np))
    plt.text(0, 9, 'np.poly: {}'.format(fit_coeffs_poly))
    plt.savefig('good.png')
    plt.show() 
    

    -0.009244843991578149 -0.009244843991576678
    1.0080792020754397 1.0080792020754408
    2.0254032481424575 2.025403248142458
    3.042727294209475 3.0427272942094756
    4.060051340276494 4.060051340276493
    5.077375386343512 5.07737538634351
    6.094699432410529 6.094699432410528
    7.112023478477547 7.112023478477545
    8.129347524544565 8.129347524544563
    9.146671570611582 9.14667157061158
    

    两者在名义上看起来是等价的,但你不能在不注意细微差别的情况下混搭。

    如果有人知道为什么有两种不同的实现,我很想知道。

    【讨论】:

      猜你喜欢
      • 2013-12-10
      • 1970-01-01
      • 2021-07-24
      • 1970-01-01
      • 2020-05-23
      • 1970-01-01
      • 2011-10-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多