Reputation: 3
I have defined an ode function, langmuir_ode, as follows:
def langmuir_ode(t, AL, Rmax, kon, koff):
A = np.interp(t, time, concs)
L = Rmax - AL
return kon * A * L - koff * AL
t is some time array (n,). concs is a (n,) array with values per timepoint in t. Since solve_ivp may want to evaluate time points not directly in t, I'm allowing interpolation to find a value A from the time and concs arrays. Rmax, kon and koff are parameters I would like to optimize using scipy minimize.
Next, I define the obj function to calculate the error between some simulated data ysim and the solution found by solve_ivp:
def obj(t, *args):
sol = solve_ivp(fun=langmuir_ode,
t_span=[0,t[-1]],
y0=[0.0],
t_eval=t,
args=args
)
sol = sol.y.ravel()
error = ysim - sol
res_sd = np.std(error)
print('Standard deviation of fit residuals:', format(res_sd,'.2f'))
SSQ = np.sum(error**2)
return SSQ
Using the parameters known to be correct for the simulated data, I get good values of SSQ as per:
print('Sum of squared fit residuals:', format(obj(time, 250, 1e5, 5e-3),'.2f'))
Standard deviation of fit residuals: 1.58
Sum of squared fit residuals: 848.23
My question: how do I use Scipy's minimize function to optimize parameters Rmax, kon and koff given some initial values and the above functions?
initial_values = 300, 5e4, 4e-5
fit = minimize(obj, initial_values)
gives:
Traceback (most recent call last):
File C:\Program Files\Spyder\pkgs\spyder_kernels\py3compat.py:356 in compat_exec
exec(code, globals, locals)
File c:\users\avdkadmin\untitled0.py:66
fit = minimize(obj, initial_values)
File C:\Program Files\Spyder\pkgs\scipy\optimize\_minimize.py:691 in minimize
res = _minimize_bfgs(fun, x0, args, jac, callback, **options)
File C:\Program Files\Spyder\pkgs\scipy\optimize\_optimize.py:1362 in _minimize_bfgs
sf = _prepare_scalar_function(fun, x0, jac, args=args, epsilon=eps,
File C:\Program Files\Spyder\pkgs\scipy\optimize\_optimize.py:332 in _prepare_scalar_function
sf = ScalarFunction(fun, x0, args, grad, hess,
File C:\Program Files\Spyder\pkgs\scipy\optimize\_differentiable_functions.py:158 in __init__
self._update_fun()
File C:\Program Files\Spyder\pkgs\scipy\optimize\_differentiable_functions.py:251 in _update_fun
self._update_fun_impl()
File C:\Program Files\Spyder\pkgs\scipy\optimize\_differentiable_functions.py:155 in update_fun
self.f = fun_wrapped(self.x)
File C:\Program Files\Spyder\pkgs\scipy\optimize\_differentiable_functions.py:137 in fun_wrapped
fx = fun(np.copy(x), *args)
File c:\users\avdkadmin\untitled0.py:50 in obj
sol = solve_ivp(fun=langmuir_ode,
File C:\Program Files\Spyder\pkgs\scipy\integrate\_ivp\ivp.py:540 in solve_ivp
raise ValueError("Values in `t_eval` are not within `t_span`.")
ValueError: Values in `t_eval` are not within `t_span`.
I'm probaby misunderstanding the syntax needed for correctly calling the minimize function. Any suggestions?
Upvotes: 0
Views: 65
Reputation: 9046
A full answer would require a minimal reproducible example on your part. But despite that, I can tell you what your issue is and a possible fix.
Your issue is that scipy.optimize.minimize
expects the function to be of the form f(x, *args)
, where x
is the term being optimized. Your function is in the same form but *args
is the argument being optimized.
What you need to do is to change your obj
function definition and how you're calling it with minimize
.
def obj(args, t): # not *args because there is a set number of arguments
...
initial_values = 300, 5e4, 4e-5
# time will be passed as the second argument and won't change between calls
fit = minimize(obj, initial_values, args=(time,))
Upvotes: 0