很抱歉重新回答
但我觉得这个答案还有遗漏。
为了拟合多项式,我们需要解决以下方程组:
a0*x0^n + a1*x0^(n-1) .. + an*x0^0 = y0
a0*x1^n + a1*x1^(n-1) .. + an*x1^0 = y1
...
a0*xm^n + a1*xm^(n-1) .. + an*xm^0 = ym
这是一个形式为V @ a = y
的问题。
其中,"V"是一个范德蒙矩阵:
[[x0^n x0^(n-1) 1],
[x1^n x1^(n-1) 1],
...
[xm^n xm^(n-1) 1]]
"y"是一个列向量,保存着y值:
[[y0],
[y1],
...
[ym]]
而 "a" 是我们要解决的系数列向量:
[[a0],
[a1],
...
[an]]
可以使用线性最小二乘法解决这个问题,具体步骤如下:
import numpy as np
x = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0])
y = np.array([0.0, 0.8, 0.9, 0.1, -0.8, -1.0])
deg = 3
V = np.vander(x, deg + 1)
z, *_ = np.linalg.lstsq(V, y, rcond=None)
print(z)
...产生与polyfit方法相同的解决方案:
z = np.polyfit(x, y, deg)
print(z)
我们希望找到一个解决方案,其中a2 = 1
将a2 = 1
代入答案开头的方程组中,然后将相应项从左侧移到右侧,我们得到:
a0*x0^n + a1*x0^(n-1) + 1*x0^(n-2) .. + an*x0^0 = y0
a0*x1^n + a1*x1^(n-1) + 1*x0^(n-2) .. + an*x1^0 = y1
...
a0*xm^n + a1*xm^(n-1) + 1*x0^(n-2) .. + an*xm^0 = ym
=>
a0*x0^n + a1*x0^(n-1) .. + an*x0^0 = y0 - 1*x0^(n-2)
a0*x1^n + a1*x1^(n-1) .. + an*x1^0 = y1 - 1*x0^(n-2)
...
a0*xm^n + a1*xm^(n-1) .. + an*xm^0 = ym - 1*x0^(n-2)
这相当于从范德蒙矩阵中删除第二列,然后将其从y向量中减去,如下所示:
y_ = y - V[:, 2]
V_ = np.delete(V, 2, axis=1)
z_, *_ = np.linalg.lstsq(V_, y_, rcond=None)
z_ = np.insert(z_, 2, 1)
print(z_)
请注意,在解决线性最小二乘问题后,我在系数向量中插入了1,因为我们不再解决a2
,因为我们将其设置为1并从问题中删除了它。
为了完整起见,这是绘制出来的解决方案:
![三种不同方法的图表](https://istack.dev59.com/qTTVk.webp)
以及我使用的完整代码:
import numpy as np
x = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0])
y = np.array([0.0, 0.8, 0.9, 0.1, -0.8, -1.0])
deg = 3
V = np.vander(x, deg + 1)
z, *_ = np.linalg.lstsq(V, y, rcond=None)
print(z)
z = np.polyfit(x, y, deg)
print(z)
y_ = y - V[:, 2]
V_ = np.delete(V, 2, axis=1)
z_, *_ = np.linalg.lstsq(V_, y_, rcond=None)
z_ = np.insert(z_, 2, 1)
print(z_)
from matplotlib import pyplot as plt
plt.plot(x, y, 'o', label='data')
plt.plot(x, V @ z, label='polyfit')
plt.plot(x, V @ z_, label='constrained (a2 = 0)')
plt.legend()
plt.show()
curve_fit
函数或lmfit
。 - Clebscipy.optimize.curve_fit()
函数,并使用bounds
参数来设置自变量的下限和上限。 - pault