寻找曲线最大值 scipy

7

我已经对一组数据点进行了拟合曲线。 我想知道如何找到我的曲线的最高点,然后我想注释该点(我不想使用我的数据中的最大y值来实现此目的)。 我无法准确地编写我的代码,但这是我的代码的基本布局。

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

x = [1,2,3,4,5]
y = [1,4,16,4,1]

def f(x, p1, p2, p3):
    return p3*(p1/((x-p2)**2 + (p1/2)**2))   

p0 = (8, 16, 0.1) # guess perameters 
plt.plot(x,y,"ro")
popt, pcov = curve_fit(f, x, y, p0)
plt.plot(x, f(x, *popt)) 

还有没有一种方法可以找到峰宽?

我是否错过了一个可以做到这一点的简单内置函数?我能够对该函数进行微分并找到其为零的点吗?如果可以,如何操作?


这与编程无关,纯粹是数学。要找到函数的最大值,需要计算它的导数。 - Julien Spronck
是的,为了获得最大值,我将函数的导数设为零。我在问题中已经提到:“我能够对函数进行微分并找到它为零的点吗?如果可以,怎么做?” - skitt1z1
2
拟合函数后,您将得到一组参数p1、p2、p3,这些参数定义了您的拟合。您的拟合最大值在(p2, 4*p3/p1)处。您可以使用任何方法来近似答案,但这将给您精确的答案。 - Julien Spronck
1
我想我刚刚回答了那个问题:p1,p2,p3 = popt - Julien Spronck
我看到popt是一个数组,所以我可以将p1、p2和p3视为该数组的元素,并进行计算? - skitt1z1
显示剩余8条评论
2个回答

7
在找到最佳参数以最大化您的函数后,您可以使用 minimize_scalar(或来自 scipy.optimize 中的其他方法之一)来找到峰值。

请注意,在下面的示例中,我将x [2] = 3.2 移位,以便曲线的峰值不会落在数据点上,并确保我们找到曲线的峰值而不是数据的峰值。

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

x = [1,2,3.2,4,5]
y = [1,4,16,4,1]

def f(x, p1, p2, p3):
    return p3*(p1/((x-p2)**2 + (p1/2)**2))   

p0 = (8, 16, 0.1) # guess perameters 
plt.plot(x,y,"ro")
popt, pcov = curve_fit(f, x, y, p0)

# find the peak
fm = lambda x: -f(x, *popt)
r = minimize_scalar(fm, bounds=(1, 5))
print "maximum:", r["x"], f(r["x"], *popt)  #maximum: 2.99846874275 18.3928199902

x_curve = np.linspace(1, 5, 100)
plt.plot(x_curve, f(x_curve, *popt))
plt.plot(r['x'], f(r['x'], *popt), 'ko')
plt.show()

当然,与其对函数进行优化,我们可以只计算一堆x值并且接近目标:
x = np.linspace(1, 5, 10000)
y = f(x, *popt)
imax = np.argmax(y)
print imax, x[imax]     # 4996 2.99859985999

4
如果您不介意使用sympy,这将非常容易。假设您已经运行了您发布的代码:
import sympy

sym_x = sympy.symbols('x', real=True)
sym_f = f(sym_x, *popt)
sym_df = sym_f.diff()
solns = sympy.solve(sym_df)  # returns [3.0]

啊...那个方法确实有效,谢谢!您是否知道使用scipy有类似的方法? - skitt1z1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接