Python – Use scipy.optimize.minimize with fixed parameters

Use scipy.optimize.minimize with fixed parameters… here is a solution to the problem.

Use scipy.optimize.minimize with fixed parameters

I’m currently using scipy optimize.minimize to get the minimum value of a function with 5 arguments. I want to put four of the inputs as fixed arguments to the function, and I want optimize.minimize to give me the value of the fifth input in order to get the lowest possible output from the function.

Here is my current code :

from numpy import array
import scipy.optimize as optimize
from scipy.optimize import minimize

def objective(speed, params):
    a,b,c,d=params
    return abs(rg.predict([[speed,params]]))

p0=np.array([[98.3,46.9,119.9,59.1]])

x0=np.array([[4]])
result = optimize.minimize(objective, x0, args=(p0,),method='nelder-mead')
print(result.x)

I’m looking for a way to be able to pass a fixed argument list or array inside the optimize.minimize function. But the above code gives me this error :

ValueError: not enough values to unpack (expected 4, got 1)

It seems that the only way I can get it to work is to hardcode in the input like this :

def objective(params):
 a=100
 b=20
 c=119.9
 d=params
 e=59.1
 return abs(rg.predict([[a,b,c,d,e]]))

x0=np.array([[4.5]])
result = optimize.minimize(objective, x0, method='nelder-mead')
print(result.x)

Am I doing it the right way? How do I pass a list or array as fixed input?

Solution

The tuple passed as args

is passed to the objective function as *args. If you define the objective function the way you do, it takes an input parameter (except for the speed to be minimized), so passing a single-element tuple (p0,) as the args keyword to minimize is perfect. Your error occurred after the function call:

ValueError: not enough values to unpack (expected 4, got 1)

This actually comes from the first line of your objective function:

a,b,c,d=params # params = np.array([[98.3,46.9,119.9,59.1]])

The array you pass as p0 has two sets of square brackets, so it has the shape (1,4). The array is unpacked along its first dimension, so during the unpacking process, it behaves like a 1-tuple (containing a 4-element array). That’s why you can’t unpack shape (1,4) into four variables, hence the error.

This is basically a typo (too many square brackets in one pair) and is not worth answering in full. After all, the reason I’m writing this is because depending on your use case, it might be easier to define these parameters directly in the function’s signature and pass them accordingly during minimization :

def objective(speed, a, b, c, d):
    ... # return stuff using a,b,c,d

# define a0, b0, c0, d0 as convenient
result = optimize.minimize(objective, x0, args=(a0,b0,c0,d0), method='nelder-mead')

Whether it is more elegant to define a function this way depends on how easily fixed parameters are defined and what happens to those parameters in Objective. If you’re just passing a list of parameters as you would in MCVE, there’s no need to separate the variables in the first place, but if the four inputs are involved in very different ways in the calculation, it might make sense to work with each variable starting with the definition of your objective function.

Related Problems and Solutions