首页 > 解决方案 > Scipy Lagrange 除以零

问题描述

我正在尝试使用 Numpy 的拉格朗日插值法插入一组有序对;我以前做过这件事,没有发生任何事故。然而,这一次,我不断得到“除以零误差”,并且插值多项式具有无限系数。我知道由于拉格朗日方法的内部工作原理,数据点不能重复,并且它们不会重复。

这是我的代码和有问题的有序对,采用 numpy 矢量格式。代码:

x = out["x"].round(decimals=3)
x = np.array(x)
y = out["y"].round(decimals=3)
y = np.array(y)
print(x)
print(y)
pol = lagrange(x,y)
print(pol)

有序对:

[273.324 285.579 309.292 279.573 297.427 290.681 276.621 293.586 283.463
 284.674 273.904 288.064 280.125 294.269 288.51  285.898 273.419 273.023
 281.754 281.546 283.21  303.399 297.392 293.359 306.404 356.285 302.487
 280.586 299.487 302.487]
[ 0.     5.414  6.202  0.     9.331 11.52   0.    10.495  5.439  4.709
  0.     4.916  0.    10.508  6.736  5.25   0.     0.     6.53   4.305
  5.124  6.753 10.175 10.545  5.98   9.147 11.137  0.     8.764  9.57 ]

提前非常感谢。

标签: pythonnumpy

解决方案


为什么拉格朗日插值对您不起作用。

302.487您的数组中有两次值x。即你确实重复了它。

为什么拉格朗日插值不是您想要的。

正如蒂姆·罗伯茨(Tim Roberts)指出的那样,拉格朗日插值实际上并不是针对 20 分进行的。问题是高度多项式倾向于过拟合。从过度拟合的维基百科文章中查看以下示例。

在此处输入图像描述

图 2. 将噪声(大致线性)数据拟合到线性函数和多项式函数。尽管多项式函数是完美拟合的,但可以预期线性函数可以更好地泛化:如果使用这两个函数来推断拟合数据之外,线性函数应该可以做出更好的预测。

替代回归

至少有两个有效的替代方案。其中之一是维基百科文章中推荐的内容。如果您知道您的数据来自哪种类型的函数,请使用回归来将该类型的函数拟合到数据中。在上面的例子中,这是一个线性函数。如果你想这样做,请查看scipy 的曲线拟合

替代样条插值

另一种选择是样条插值。再次来自关于样条插值的维基百科文章

样条插值不是一次将单个高次多项式拟合到所有值,而是将低次多项式拟合到值的小子集,例如,在每对十个点之间拟合九个三次多项式,而不是为所有这些拟合一个 10 次多项式。样条插值通常优于多项式插值,因为即使在样条中使用低次多项式时,插值误差也可以很小。样条插值还避免了龙格现象的问题,即在使用高次多项式进行插值时,点之间可能会发生振荡。

我想指出两个小的技术细节。第一点是您需要订购积分,所以我为您做了。并且两个 scipy有一个您需要选择UnivariateSpline的平滑参数。s如果你把它选小,它会像你习惯使用拉格朗日插值一样坚持数据,但如果你把它变大,它会变得更平滑,并希望能更好地概括。下面我选择了 2 个不同的值供您查看,但您可能应该自己尝试一下。我包括了一个非常小的,所以你会看到它可以做你习惯的拉格朗日插值,但不推荐它。此外,您可能应该使用更多数据,对其进行预处理等。但这不是问题所在。

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import UnivariateSpline

idx = np.argsort(x)
x = x[idx]
y = y[idx]

for s in [10,60]:
    t = np.linspace(np.min(x), np.max(x), 10**4)
    f = UnivariateSpline(x,y, s=s)

    plt.scatter(x,y)
    plt.plot(t,f(t))
    plt.title(f'{s=}')
    plt.show()

s=10 s=60


推荐阅读