为了适应双曲线函数,我尝试使用以下代码:
import numpy as np
from scipy.optimize import curve_fit
def hyperbola(x, s_1, s_2, o_x, o_y, c):
# x > Input x values
# s_1 > slope of line 1
# s_2 > slope of line 2
# o_x > x offset of crossing of asymptotes
# o_y > y offset of crossing of asymptotes
# c > curvature of hyperbola
b_2 = (s_1 + s_2) / 2
b_1 = (s_2 - s_1) / 2
return o_y + b_1 * (x - o_x) + b_2 * np.sqrt((x - o_x) ** 2 + c ** 2 / 4)
min_fit = np.array([-3.0, 0.0, -2.0, -10.0, 0.0])
max_fit = np.array([0.0, 3.0, 3.0, 0.0, 10.0])
guess = np.array([-2.5/3.0, 4/3.0, 1.0, -4.0, 0.5])
vars, covariance = curve_fit(f=hyperbola, xdata=n_step, ydata=n_mean, p0=guess, bounds=(min_fit, max_fit))
其中n_step和n_mean是先前生成的测量值。代码运行正常并且没有给出错误消息,但它只返回初始猜测,只有很小的变化。此外,协方差矩阵仅包含零。我尝试用更好的初始猜测做同样的拟合,但这没有任何影响。 此外,我用初始猜测作为输入绘制了完全相同的函数,这给了我一个接近实际值的函数。有谁知道我在哪里弄错了?或者我使用错误的功能来使我健康?
答案 0 :(得分:2)
问题必须在于n_step
和n_mean
(目前未在问题中提供);当尝试使用一些任意选择的输入参数集重现问题时,优化按预期工作。我们来试试吧。
首先,让我们通过
在给定的参数空间中定义一些任意选择的输入参数params = [-0.1, 2.95, -1, -5, 5]
让我们看看它的样子:
import matplotlib.pyplot as plt
xs = np.linspace(-30, 30, 100)
plt.plot(xs, hyperbola(xs, *params))
基于此,让我们通过
为xdata
和ydata
定义一些相当粗略的输入
xdata = np.linspace(-30, 30, 10)
ydata = hyperbola(xs, *params)
有了这些,让我们运行优化,看看我们是否匹配给定的参数:
vars, covariance = curve_fit(f=hyperbola, xdata=xdata, ydata=ydata, p0=guess, bounds=(min_fit, max_fit))
print(vars) # [-0.1 2.95 -1. -5. 5. ]
即使我们的params
与我们的guess
有很大的不同,但这种拟合也很完美。换句话说,如果我们可以自由选择n_step
和n_mean
,那么该方法可以按预期工作。
为了尝试稍微挑战优化,我们还可以尝试添加一些噪音:
np.random.seed(42)
xdata = np.linspace(-30, 30, 10)
ydata = hyperbola(xdata, *params) + np.random.normal(0, 10, size=len(xdata))
vars, covariance = curve_fit(f=hyperbola, xdata=xdata, ydata=ydata, p0=guess, bounds=(min_fit, max_fit))
print(vars) # [ -1.18173287e-01 2.84522636e+00 -1.57023215e+00 -6.90851334e-12 6.14480856e-08]
plt.plot(xdata, ydata, '.')
plt.plot(xs, hyperbola(xs, *vars))
在这里,我们注意到最佳结果与我们提供的params
和guess
不同,仍然在min_fit
和max_fit
提供的范围内,提供了一个很好的契合。