1

When using Scipy's fmin function, I keep encountering the error message: ValueError: setting an array element with a sequence I have seen that this question has been asked already some times, and I have read interesting posts such as:

..and have tried implementing the suggested solutions, such as adding '*args' to the cost function, appending the variables in the cost function to a list and vectorizing the variables. But nothing has worked for me so far.

I am quite new to programming in Python, so it is possible that I have read the solution and not known how to apply it.

A simplified version of the code, which I used to try to find the problem, is as follows:

import numpy as np
import scipy.optimize
from scipy.optimize import fmin
fcm28=40
M_test=np.array([32.37,62.54,208,410,802])
R_test=np.array([11.95,22.11,33.81,39.18,50.61])
startParams=np.array([fcm28,1,1])

def func(xarray):
   x=xarray[0]
   y=xarray[1]
   z=xarray[2]
   expo3=x*np.exp(-(y/M_test)**z)
   cost=expo3-R_test
   return cost 
### If I write the following lines of code:
# xarray=(100,290,0.3)
# print(func(xarray))
# >> [ 2.557 -1.603 -0.684 1.423 -2.755] #I would obtain this output

func_optimised=fmin(func,x0=[fcm28,1,1],xtol=0.000001)

Objective: I am trying to obtain an exponential function 'expo3' (that takes 5 adjustment points, defined by vector 'M_test' on the horizontal axis and 'R_test' in the vertical axis. Adjustment points (M_test,R_test) What I am trying to minimise is the difference between the function 'expo3' and the adjustment points. So, the exponential graph is meant to go as close as possible to the adjustment points, such as: Exponential curve that accomplishes the minimisation of 'expo3-R_test'

I obtain the following error message:

File "Example2.py", line 20, in <module>
   func_optimised=fmin(func,x0=[fcm28,1,1],xtol=0.000001)
File "/home/.../python3.6/site-packages/scipy/optimize/optimize.py", line 443, in fmin
 res=_minimize_neldermead(func,x0,args,callback=callback,**opts)
File "/home/.../python3.6/site-packages/scipy/optimize/optimize.py" line 586, in _minimize_neldermead
   fsim[k] = func(sim[k])
ValueError: setting an array element with a sequence.

Can fmin be used to accomplish this task? Are there any viable alternatives? Any help on how to solve this would be really appreciated.

enricw
  • 263
  • 4
  • 19
  • 1
    `M_test` and `R_test` are arrays with length 5, so the return value of your function `func` is an array with length 5. `fmin` requires the objective function to return a scalar. – Warren Weckesser Jun 11 '20 at 12:52
  • Would a viable solution be to place the object funcion and the fmin function in a loop that goes from 0 to the length of M_test? – enricw Jun 11 '20 at 13:35
  • 1
    That depends. I think it will be easier for someone to help you if you provide more context about the problem you are trying to solve. What are you trying to accomplish? Independent of its implementation in Python code, what are you trying to minimize, and why? (If you can answer that, it would be better to provide that context in the question and not here in the comments.) – Warren Weckesser Jun 11 '20 at 13:45
  • Noted. I modified the question so it includes the objective. – enricw Jun 12 '20 at 09:03

1 Answers1

1

As noted in the commments, your function must return a single value. Assuming that you want to perform a classic least squares fit, you could modify func to return just that:

  def func(...):
      # ... identical lines skipped
      cost = sum((expo3-R_test)**2)
      return cost

With that change, func_optimised becomes:

  array([1.10633369e+02, 3.85674857e+02, 2.97121854e-01])
  # or approximately (110.6, 385.6, 0.3)

Just as a pointer: you could alternatively use scipy.optimize.curve_fit for basically doing the same thing, but with a nicer API that allows you to directly provide the function skeleton + the sample points to fit.

ojdo
  • 8,280
  • 5
  • 37
  • 60