【问题标题】:Is it possible to stop scipy.optimize.curve_fit according to the loss function?是否可以根据损失函数停止 scipy.optimize.curve_fit ?
【发布时间】:2021-07-06 06:45:48
【问题描述】:

我试图最小化两个函数之间的 mse 边界,curve_fit 做得很好,但是当两个函数之间的 mse 低于 0.1 时,我想停止计算。 这是一个简单的示例代码

import numpy as np
from scipy import optimize, integrate

def sir_model(y, x, beta, gamma):
    sus = -beta * y[0] * y[1] / N
    rec = gamma * y[1]
    inf = -(sus + rec)
    return sus, inf, rec

def fit_odeint(x, beta, gamma):
    return integrate.odeint(sir_model, (sus0, inf0, rec0), x, args=(beta, gamma))[:,1]

population = float(1000)
xdata = np.arange(0,335,dtype = float)
upper_bounds = np.array([1,0.7])

N = population
inf0 = 10
sus0 = N - inf0
rec0 = 0.0

#curve to approximate
ydata = fit_odeint(xdata, beta = 0.258, gamma = 0.612)

popt, pcov = optimize.curve_fit(fit_odeint, xdata, ydata,bounds=(0, upper_bounds))

问题是真正的问题更难。所以我想以固定的容差(mse = 0.1)停止函数curve_fit。我尝试使用 ftol,但它似乎不起作用。

【问题讨论】:

  • 欢迎来到 SO!请提供minimal reproducible example。否则,很难提供适当的帮助。
  • 完成了,希望越来越好
  • 这不是一个工作示例,例如sus0 取决于 ydata,它由函数 fit_odeint 计算得出,而 sus0 又需要 sus0
  • 对不起,现在我认为这个例子有效

标签: python optimization computer-science curve-fitting scipy-optimize


【解决方案1】:

如果我对您的理解正确,您希望在底层最小二乘优化问题的目标为 curve_fit 和 least_squares 都不支持目标值的回调或容差。但是,scipy.optimize.minimize 可以。所以让我们使用它。

为此,我们必须将您的曲线拟合问题表述为最小化问题:

min ||ydata - fit_odeint(xdata, *coeffs)||**2

s.t. lb <= coeffs <= ub

然后,我们通过minimize 解决问题,并使用回调函数在目标函数值为

from scipy.optimize import minimize
from numpy.linalg import norm

# the objective function
def obj(coeffs):
    return norm(ydata - fit_odeint(xdata, *coeffs))**2

# bounds
bnds = [(0, 1), (0, 0.7)]

# initial point
x0 = np.zeros(2)

# xk is the current parameter vector and state is an OptimizeResult object
def my_callback(xk, state):
    if state.fun <= 0.1:
        return True

# call the solver (res.x contains your coefficients)
res = minimize(obj, x0=x0, bounds=bnds, method="trust-constr", callback=my_callback)

这给了我:

 barrier_parameter: 0.1
 barrier_tolerance: 0.1
          cg_niter: 3
      cg_stop_cond: 4
            constr: [array([0.08205584, 0.44233162])]
       constr_nfev: [0]
       constr_nhev: [0]
       constr_njev: [0]
    constr_penalty: 1635226.9491785716
  constr_violation: 0.0
    execution_time: 0.09222197532653809
               fun: 0.007733264340965375
              grad: array([-3.99185467,  4.04015523])
               jac: [<2x2 sparse matrix of type '<class 'numpy.float64'>'
    with 2 stored elements in Compressed Sparse Row format>]
   lagrangian_grad: array([-0.03385145,  0.19847042])
           message: '`callback` function requested termination.'
            method: 'tr_interior_point'
              nfev: 12
              nhev: 0
               nit: 4
             niter: 4
              njev: 4
        optimality: 0.1984704226037759
            status: 3
           success: False
         tr_radius: 7.0
                 v: [array([ 3.95800322, -3.8416848 ])]
                 x: array([0.08205584, 0.44233162])

请注意,回调的签名仅适用于“trust-constr”方法,其他方法的签名为callback(xk) -&gt; bool,即您需要在回调中自行计算目标函数值。

【讨论】:

  • 真正的问题是21个参数的校准。我尝试了方法'trust-constr',但它似乎不起作用或用于大量计算。我想使用curve_fit,因为结果很好,你知道另一种停止这种方法的方法吗?我可以使用gtolftolxtol 吗?
  • @MaxenceDavid 正如我在回答中所述,curve_fit 不支持目标函数值的容差。您可以使用基于gtolftolxtol 的另一个停止标准(请参阅文档了解它们的含义),或者对minimize 使用另一种方法并重写回调。此外,您可以通过提供准确的目标梯度来加速求解器。
猜你喜欢
  • 2018-07-14
  • 2021-10-20
  • 2016-09-14
  • 2022-06-15
  • 2019-07-31
  • 1970-01-01
  • 2020-11-05
  • 2019-09-29
  • 1970-01-01
相关资源
最近更新 更多