Python scipy曲线拟合返回初始估计值

Python scipy曲线拟合返回初始估计值,python,scipy,curve-fitting,Python,Scipy,Curve Fitting,为了拟合双曲函数,我尝试使用以下代码: 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 asy

为了拟合双曲函数,我尝试使用以下代码:

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_阶跃和n_均值是先前生成的测量值。代码运行良好,没有给出错误消息,但只返回初始猜测,只做了很小的更改。此外,协方差矩阵仅包含零。我试图用一个更好的初始猜测做同样的拟合,但这没有任何影响。
此外,我以初始猜测作为输入绘制了完全相同的函数,这确实给了我一个接近实际值的函数。有人知道我在哪里犯错吗?或者我是否使用了错误的函数来进行拟合?

问题必须出在
n\u步骤
n\u意思
(如当前所述,问题中未给出);当试图用一些任意选择的输入参数来重现问题时,优化工作正如预期的那样。让我们试试看

首先,让我们在给定的参数空间中定义一些任意选择的输入参数

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.  ]
也就是说,即使我们的
参数
与我们的
猜测
大不相同,但拟合还是完美的。换句话说,如果我们可以自由选择
n_步骤
n_平均值
,那么该方法将按预期工作

为了尝试稍微挑战优化,我们还可以尝试添加一些噪声:

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))


这里我们注意到,最佳结果与我们提供的
参数和
猜测值不同,仍然在
最小拟合
最大拟合
提供的范围内,并且仍然提供了良好的拟合。

与此处发生的任何情况无关,请注意,
vars
是Python内置程序的名称,因此您可能希望避免将其用作变量名称,因为它最终会隐藏内置程序。但实际上,如果给定的
guess
恰好提供了(接近)最优的结果,无论
n\u step
n\u mean
是什么,那么问题到底是什么?谢谢!这确实与输入值有关。只是尝试再次运行相同的代码,但将输入数据从float32转换为float64,从而解决了问题。仍然奇怪的是,该函数没有给出警告或转换数据本身…捕捉得好,而且非常好奇!由于SciPy使用MINPACK实现LM(这实际上不是这里使用的算法),因此数据类型可能最终会影响到LM,但这种行为肯定是意外的;问题是初始步长是
np.float64
ε的平方根,这导致在
np.float32
情况下dfs消失。