I'm using scipy.opimize.minimize to find the best fit parameters for the negative log-likelihood of a dataset (which has a given pdf). The functions for calculating the pdf and the negative log-likelihood are given below:
def density(time, x, y, z):
w = (z/x)*mt.exp(-time/x) + ((1-z)/y)*mt.exp(-time/y)
return w
def NLL2(params):
sig = 0
a, b, c = params[0], params[1], params[2]
for i in range(0, 100):
sig = sig - mt.log(density(xval[i], a, b, c))
return sig
where xval is the dataset (list of 100time values between 0-10). For what it's worth, the pdf is of a double decay process.
I have been given starting values for x, y and z (stored in a list called "initial_guesses" which is given to the NLL2 function as the "param" argument), and I have to find the best-fit values of x, y and z (i.e. those values which minimise NLL2 for a given dataset xval).
I try to do this with the following line of code:
initial_guesses = [1.30719636, 0.19783642, 0.25150731]
best_fit = sci.optimize.minimize(NLL2, initial_guesses, bounds = [(0.1, 20), (0.1, 20), (0.1, 1)], method = 'L-BFGS-B').x
The bounds have been chosen as what I'm "supposed" to come up with is something like [1.3, 0.2, 0.25] i.e. close to the initial values. However, when I do this, I often end up with this error message:
File "newcode2.py", line 125, in NLL2 sig = sig - mt.log(density(xval[i], x, y, z)) ValueError: math domain error
I know this is happening because the logarithm is being taken of a negative value, but the bounds I've given to the minimizer should prevent this from happening.
To investigate further, I changed the NLL2 function to the following:
def NLL2(params):
sig = 0
a, b, c = params[0], params[1], params[2]
for i in range(0, 100):
if density(xval[i], a, b, c) > 0:
sig = sig - mt.log(density(xval[i], a, b, c))
else:
print density(xval[i], a, b, c), xval[i], params, '\n'
return sig
An example of what the terminal prints out now is the following:
-4.25654045048e-10 2.76533572107 [ 0.1 20. 1.00000001]
So somehow the parameters are going to the limits of the bounds that I've set, in the last case actually going over by 1e-8. This is causing the density function to return a minutely negative number, which is causing a crash.
Does anyone know how I can stop the minimizer doing this? I've also tried using the SLSQP method, but with the same problem.
I apologize if I've given too much detail, but I'm tired and I also want to give out any information which might be useful.
NB I've imported the math class as mt.
Aucun commentaire:
Enregistrer un commentaire