I am trying to minimize my likelihood function with the par parameter only, the rest: n,T,r,log_x, gft_y are supposed to be fixed in the optimization. When I put them in the args to fix them I get back the following errors:

TypeError: float() argument must be a string or a number, not 'tuple'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):

  File "C:\Users\phelg\AppData\Local\Temp/ipykernel_16344/2785678381.py", line 4, in <module>
    result = fmin(mrg_lik,initial_guess, args)

  File "C:\Users\phelg\anaconda3\envs\Financial_Econometrics\lib\site-packages\scipy\optimize\optimize.py", line 580, in fmin
    res = _minimize_neldermead(func, x0, args, callback=callback, **opts)

  File "C:\Users\phelg\anaconda3\envs\Financial_Econometrics\lib\site-packages\scipy\optimize\optimize.py", line 750, in _minimize_neldermead
    fsim[k] = func(sim[k])

ValueError: setting an array element with a sequence.

The likelihood function:

def likelihood(par,n,T,r,log_x,gft_y):
    # takes inputs par, n, T, r,log_x and gft_y
    # returns F,log_h,gft_q,u,v,z and Gamma
    A=np.zeros(shape=(T,n,n))
    B=np.zeros(shape=(T,n,n))
    try:
        for t in range(0,T):
            A[t]= mapping(gft_q[t], 10e-8)[0]
        for t in range(0,T):
            B[t]= np.diag(np.sqrt(np.exp(log_h[t])))
        for t in range(0,T):
            lik = -0.5*(n*np.log(2*pi) + np.log(np.linalg.det(A[t]@B[t]@A[t])) +(z[t] /A[t] @z[t].T))
    except ValueError:
        print("Error: input is of wrong format")    
    F = -(np.sum(lik))
    return F,log_h,gft_q,u,v,z,Gamma
    print(F,log_h,gft_q,u,v,z,Gamma)
    
par= np.ones(shape=(26,))
result = likelihood(par,n,T,r,log_x,gft_y)

The optimization:

from scipy.optimize import fmin
initial_guess = np.full((126,), 0.1)
args = (n,T,r,log_x,gft_y) #fixed arguments in likelihood function during optimization
result = fmin(likelihood,initial_guess,args) #should give back the par which minimize the likelihood
fitted_params = result.x

Update: The likelihood function returned more than one result and the fmin function was trying to minimize them all. Correction:

return F

instead

return F,log_h,gft_q,u,v,z,Gamma

Now I finally got the fmin function running without errors. Note that my code is wrong in a way that the results for the optimization are incorrect (it gives me an array with the initial_guess in it). But that is another issue to solve...

1

There are 1 best solutions below

7
On

Your function call to fmin seems off. The docs say it should be fmin(function, guess, <tuple of other args>). So I would have expected you to use this: fmin(likelihood, initial_guess, args)

Note on how to understand the errors

In your first attempt you got TypeError: 'tuple' object is not callable, that indicates fmin was expecting a function (callable) but it received a tuple. Which was because you were calling likelihood with arguments: likelihood(...), instead of passing it as is.

In the second case you get the error: ValueError: setting an array element with a sequence. That tells you fmin was expecting an array, but it received a generic sequence. On looking at the arguments, you will notice you defined your initial_guess as [0.4*np.ones((1, 26))] which is a single item list with a 1x26 array as the value.

For the third case, ValueError: setting an array element with a sequence. means there's a array[i] = <value> somewhere, where instead of giving a <value> that matches the array type, it is a sequence. This is further clarified above in the stack trace in: TypeError: float() argument must be a string or a number, not 'tuple'. From this you can tell, the value is a tuple instead of float. The issue could be in likelihood. Are you sure the shape should be 1x26 instead of just a simple 1D array of length 26, so shape = (26,)?

Edit: see the scipy source code for _minimize_neldermead, lines 792-793, and 746. As I read that, a 1D array is expected. Even though it might seem otherwise, 1x26 is actually 2D. just look at initial_guess.ndim.