scipy curve_fit返回初始估算值

时间:2018-06-05 13:08:36

标签: 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 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是先前生成的测量值。代码运行正常并且没有给出错误消息,但它只返回初始猜测,只有很小的变化。此外,协方差矩阵仅包含零。我尝试用更好的初始猜测做同样的拟合,但这没有任何影响。 此外,我用初始猜测作为输入绘制了完全相同的函数,这给了我一个接近实际值的函数。有谁知道我在哪里弄错了?或者我使用错误的功能来使我健康?

1 个答案:

答案 0 :(得分:2)

问题必须在于n_stepn_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))

enter image description here

基于此,让我们通过

xdataydata定义一些相当粗略的输入
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_stepn_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))

enter image description here

在这里,我们注意到最佳结果与我们提供的paramsguess不同,仍然在min_fitmax_fit提供的范围内,提供了一个很好的契合。