I would like to know where I made a mistake in the following code. I suspect it is some basic python mistake that has nothing to do with scipy. I am trying to pass a function to optimize to scipy.optimize.differential_evolution.
def func_to_opt(x, TRANS_MIN_BV=TRANS_MIN_BV, SUBS_VAL=100, model=model):
"""Returns Rsp if BV is above TRANS_MIN_BV, SUBS_VAL if not. Rsp and BV is calculated by model
"""
y = model.predict(np.array([x]))
y = np.array(y)[:, : ,0]
y = np.swapaxes(y, 0, 1)
print(y)
print(TRANS_MIN_BV)
if y[0, 0] > TRANS_MIN_BV:
Rsp = y[0, 1]
else:
Rsp = SUBS_VAL
return Rsp
GA = scipy.optimize.differential_evolution(func_to_opt(), bounds=trans_bounds.T.tolist(), maxiter=1e4)
And I get the error:
func_to_opt() missing 1 required positional argument: 'x'
But if I write there x, gives me of course the error
name 'x' is not defined
And finally, if I put there some arbitrary sequence like [0.8, 8, 5e16, 2.001] (which is in bounds, and y = model.predict(..) with it gives valid results), it gives a cryptic error:
The map-like callable must be of the form f(func, iterable), returning a sequence of numbers the same length as 'iterable'
The thing is, according to those examples at the bottom of https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.differential_evolution.html, it was used exactly as I am trying to use it – they defined a function like ackley(x) or used scipy.optimize.rosen, but they passed it without the "x" argument into the method and supposedly it worked.
>Solution :
You have to pass the function object itsself and not the evaluated function.
Remove the paranthesis () of func_to_opt:
GA = scipy.optimize.differential_evolution(func_to_opt, bounds=trans_bounds.T.tolist(), maxiter=1e4)
Regarding your call of model.predict:
You need to find out the input shape of your model. You have to input a list with one element per input. Usually you have only one input. So you have to feed a list with one element into your model. The shape of the element within this list is usually something like (None, N, C, H, W). First dimension is the batch size, second the channel size, H=Height, W= Width. If you are not working with images, you probably have an input shape of (None, N). Try the following input object:
data = [0.8, 8, 5e16, 2.001]
batch_size = 1
[np.array(data).reshape(batch_size, len(data))]
So you need to change
np.array([x])
to
[np.array(x).reshape(1,len(x))]
you could also check the input shape of your model with
model.inputs[0].shape