python抛物线拟合与固定峰值

gz5pxeao  于 2021-08-25  发布在  Java
关注(0)|答案(3)|浏览(537)

我有一组数据,想用抛物线拟合。这已经适用于numpy的polyfit函数,如下所示:

fit = np.polyfit(X, y, 2)
formula = np.poly1d(fit)

现在我想让抛物线的峰值在一个固定的x值上,并且拟合仍然尽可能地以这个固定的峰值进行。有没有办法做到这一点?
根据我的数据,我知道抛物线总是向下开的。

z5btuh9x

z5btuh9x1#

我认为这是一个相当困难的问题,因为二阶多项式(ax^2+bx+c)峰值的x坐标总是在x=-b/2a。
您可以做的一件事是删除b项,并在拟合多项式时将其偏移所需的峰值x,如下面的代码所示。注意,我使用了 scipy.optimize.curve_fit 以适合自定义函数 func .

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

# generating a parabola with noise

np.random.seed(42)
x = np.linspace(-10, 10, 100)
y = 10 -(x-2)**2 + np.random.normal(0, 5, x.shape)

# function to fit

def func(x, a, c):
    return a*x**2 + c

# desired x peak value

x_peak = 2

popt, pcov = curve_fit(func, x - x_peak, y)

y_fit = func(x - x_peak, *popt)

# plotting

plt.plot(x, y, 'k.')
plt.plot(x, y_fit)
plt.axvline(x_peak)
plt.show()

输出图像:

wmtdaxz3

wmtdaxz32#

在抛物线上固定一个点可以简化问题,因为现在可以用常数稍微重写方程:

y = A(x - B)**2 + C

给定系数 a , b , c 在您最初的无约束贴合中,您拥有

a = A
b = -2AB
c = AB**2 + C

唯一的区别是因为 B 是一个常数,你没有 x - B 在方程中,你需要自己设置最小二乘问题。给定数组 x , y 不变的 B ,问题如下所示:

m = np.stack((x - B, np.ones_like(x)), axis=-1)
(A, C), *_ = np.linalg.lstsq(m, y, rcond=None)

然后,可以从以下公式中提取法向系数: a , b , c 在上面
这是一个完整的示例,就像另一个答案中的示例一样:

B = 2

np.random.seed(42)
x = np.linspace(-10, 10, 100)
y = 10 -(x - B)**2 + np.random.normal(0, 5, x.shape)

m = np.stack(((x - B)**2, np.ones_like(x)), axis=-1)
(A, C), *_ = np.linalg.lstsq(m, y, rcond=None)

a = A
b = -2 * A * B
c = A * B**2 + C

y_fit = a * x**2 + b * x + c

你可以放弃 a , b , c 全力以赴

y_fit = A * (x - B)**2 + C

结果将是相同的。

plt.plot(x, y, 'k.')
plt.plot(x, y_fit)

qpgpyjmq

qpgpyjmq3#

在没有峰值位置的情况下,拟安装的功能应为:
y=a x^2+b x+c
当峰值位置为x=p时,给定p:
-b/(2a)=p
b=-2 a p
y=ax^2-2x+c
y=a(x^2-2px)+c
知道p,变量的一个变化:
x=x^2-2px
因此,首先从数据(x,y)计算新的数据(x,y)
然后通过线性回归计算a和c
y=a x+c

相关问题