0

I'm trying to maximise a function using the following code:

from scipy.optimize import minimize
from scipy.stats import lognorm, norm
import numpy as np

np.random.seed(123)
obs = np.random.normal(loc=20, scale=3, size=20)

# Log-Posterior optimisation objectiv 
def objective(params, y):
    mu = params[0]
    sigma = params[1]
    llikelihood = np.sum(np.log(norm.pdf(y, mu, sigma)))
    lpost = llikelihood + np.log(norm.pdf(mu, 0, 100)) + np.log(lognorm.pdf(sigma, loc= 0, s = 4))
    return -1*lpost

starting_mu = 0
starting_sigma = 1
optim_res = minimize(fun = objective, x0=(starting_mu, starting_sigma), args=(obs))

The code runs fine up to the final optimisation line. I'm quite confident that the error is how I am trying to do the optimisation as in R, using identical setup and observations, objective() evaluates to the same value. Additionally, using optim() the function does optimise to value of mu=21.6 and sigma=3.28.

I can use the R code, however, it would be easier to run the code in Python so that it could integrate with everything else that I am doing.

EDIT: The traceback message is:

dert2@ma0phd201803:~$ python laplace_approx.py 
laplace_approx.py:12: RuntimeWarning: divide by zero encountered in log
    lpost = llikelihood + np.log(norm.pdf(mu, 0, 100)) + np.log(lognorm.pdf(sigma, loc= 0, s = 4))
laplace_approx.py:12: RuntimeWarning: divide by zero encountered in log
    lpost = llikelihood + np.log(norm.pdf(mu, 0, 100)) + np.log(lognorm.pdf(sigma, loc= 0, s = 4))
laplace_approx.py:12: RuntimeWarning: divide by zero encountered in log
    lpost = llikelihood + np.log(norm.pdf(mu, 0, 100)) + np.log(lognorm.pdf(sigma, loc= 0, s = 4))
/opt/anaconda3/lib/python3.7/site-packages/numpy/core/fromnumeric.py:83:     RuntimeWarning: invalid value encountered in reduce
    return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
Tom Pinder
  • 131
  • 6
  • *"The code runs fine up to the final optimisation line."* And then what happens? Please explain the problem. Do you get an error? If so, include the *complete* error message (i.e. the complete traceback) in the question. – Warren Weckesser Oct 12 '18 at 16:27
  • One problem I can see makes this question a duplicate of https://stackoverflow.com/questions/31388319/passing-args-in-scipy-optimize-minimize-objective-function-getting-error-on-nu, but I don't know if that is the issue that you are dealing with. – Warren Weckesser Oct 12 '18 at 16:31
  • Slightly different @WarrenWeckesser . I have now added the traceback. – Tom Pinder Oct 12 '18 at 17:40
  • This error happens when you call `np.log(0)`. You need to protect your logarithms against zero values. – Erwin Kalvelagen Oct 13 '18 at 00:15

1 Answers1

0

Some quick stepping in the debugger reveals that norm.pdf(y, mu, sigma) returns a nan array on one iteration. On that same iteration, lognorm.pdf(sigma, loc=0, s=4) returns zero. Even before that, sigma was assigned to a negative value. This is really where the problem starts. It would take some effort to track exactly why the function gets called with a negative params[1] value, but that does happen. I would use a debugger to step through the minimize function to see what is going on. I believe the negative value is passed on the 9th call to the function, if that helps. It is possible that the method that is being used to optimize the function does not work well for your particular function. You could try to use a different method, chosen by assigning to the method parameter (see the documentation for more details).

HackerBoss
  • 829
  • 7
  • 16