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...
Your function call to
fmin
seems off. The docs say it should befmin(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 indicatesfmin
was expecting a function (callable
) but it received a tuple. Which was because you were callinglikelihood
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 youfmin
was expecting an array, but it received a generic sequence. On looking at the arguments, you will notice you defined yourinitial_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 aarray[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 atuple
instead offloat
. The issue could be inlikelihood
. Are you sure the shape should be1x26
instead of just a simple 1D array of length 26, soshape = (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 atinitial_guess.ndim
.