0

I'm tasked with fitting the model of ODE equations to data using MCMC but can't get past the error:

TypeError                                 Traceback (most recent call last)
<ipython-input-21-10d0a714b5f4> in <module>()
   26         proposed[j] = proposed[j] + np.random.normal(0,propsigma[j])
   27         if (proposed[j]>0): # automatically reject moves if proposed parameter <=0
---> 28             alpha = np.exp(logistic_loglik (proposed,time,ExRatio,sig)-logistic_loglik(par_out[i-1,],time,ExRatio,sig))
 29             u = np.random.rand()
 30             if (u < alpha):

<ipython-input-21-10d0a714b5f4> in logistic_loglik(params, t, data, sig)
    3 # set up a function to return the log likelihood
    4 def logistic_loglik(params,t,data,sig):
--> 5     return sum(norm.logpdf(logistic(params,t),data,sig))
    6 
    7 # set standard deviations to be 10% of the population values

TypeError: logistic() missing 1 required positional argument: 'params'

the issue is with these lines:

def logistic_loglik(params,t,data,sig):
    return sum(norm.logpdf(logistic(params,t),data,sig))

The function of these lines is set up a function to return the log likelihood obviously there is a logistic model involved.

It is my understanding that the issue is that the 'params' is not being called by the function but I am unsure of how to resolve this being a relative beginner to coding.

Rest of code is below to add context.

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint

%matplotlib inline

def logistic(x,t,params):    
    S, R, A = x
    r, Nmax, delta_s, beta, gamma, delta_r, delta_a, Emax, H, MICs, MICr = params
N = S + R
E_s = 1 - (Emax * A**H)/(MICs**H + A**H)
E_r = 1- (Emax * A**H)/(MICr**H + A**H)

derivs = [r * (1 - N / Nmax ) * E_s * S - delta_s * S - ((beta * S * R)/N), 
         r * (1 - gamma) * (1 - N/Nmax) * E_r * R  - delta_r * R + ((beta * S * R)/N), - delta_a * A]


return derivs

r = 0.5
Nmax = 10**7
delta_s = 0.025
beta = 10**-2
gamma = 0.5
delta_r = 0.025
delta_a = 0.003
Emax = 2
H = 2
MICs = 8
MICr = 2000

[r, Nmax, delta_s, beta, gamma, delta_r, delta_a, Emax, H, MICs, MICr] = params
S = 9 * 10**6
R = 10**5
A = 5.6
x0 = [S, R, A]

maxt = 2000
tstep = 1
t = np.arange(0,maxt,tstep)

def logistic_resid(params,t,data):
    return logistic(params,t)-data

logistic_out = odeint(logistic, x0, t, args=(params,))

time = np.array([0, 168, 336, 504, 672, 840, 1008, 1176, 1344, 1512, 1680, 1848, 2016, 2184, 2352, 2520, 2688, 2856])
ExRatio = np.array([2, 27, 43, 36, 39, 32, 27, 22, 13, 10, 14, 14, 4, 4, 7, 3, 3, 1])
ratio = 100* logistic_out[:,1]/(logistic_out[:,0]+logistic_out[:,1])
plt.plot(t,ratio)
plt.plot(time,ExRatio,'h')
xlabel('Position')
ylabel('Pollution')

New cell

from scipy.stats import norm

# set up a function to return the log likelihood
def logistic_loglik(params,t,data,sig):
    return sum(norm.logpdf(logistic(params,t),data,sig))

# set standard deviations to be 10% of the population values
sig = ExRatio/10

# parameters for the MCMC
reps = 50000
nparams = 3

# output matrix
par_out = np.ones(shape=(reps,nparams))
# acceptance 
accept = np.zeros(shape=(reps,nparams))
# proposal standard deviations. These have been pre-optimized.
propsigma = [0.05,20,5]

for i in range(1,reps):
    # make a copy of previous parameters
    par_out[i,] = par_out[i-1,]
    for j in range(npars):
        proposed = np.copy(par_out[i,:]) # we need to make a copy so that rejected moves don't affect the original matrix
    proposed[j] = proposed[j] + np.random.normal(0,propsigma[j])
    if (proposed[j]>0): # automatically reject moves if proposed parameter <=0 
        alpha = np.exp(logistic_loglik(proposed,time,ExRatio,sig)-logistic_loglik(par_out[i-1,],time,ExRatio,sig))
        u = np.random.rand()
        if (u < alpha):
            par_out[i,j] = proposed[j]
            accept[i,j] = 1

#print(sum(accept[range(101,reps),:])/(reps-100))


#plt.plot(par_out[:,0])
#plt.plot(par_out[range(101,reps),0])
#plt.plot(par_out[:,0],par_out[:,2])
plt.hist(par_out[range(101,reps),0],50)
print('\n')
a=np.mean(par_out[range(101,reps),0])

This my first question on here so if I have left any information out required for an answer please advise.

Any help would be greatly apprecieated

Matthew Freeman
  • 3
  • 1
  • 2
  • 7

1 Answers1

1

Your function looks like this:

def logistic(x,t,params)

It takes the arguments. But you call only with two:

def logistic_loglik(params,t,data,sig):
    return sum(norm.logpdf(logistic(params,t),data,sig))

Change it to:

def logistic_loglik(params,t,data,sig):
    return sum(norm.logpdf(logistic(data, t, params), sig))
Mike Müller
  • 82,630
  • 20
  • 166
  • 161
  • Having implemented the changes you suggested the error was solved thanks for that. I have spent the past few days trying to solve the next error 'ValueError: too many values to unpack (expected 3)' focused on the lines 'alpha = np.exp(logistic_loglik(proposed,time,ExRatio,sig)-logistic_loglik(par_out[i-1,],time,ExRatio,sig))' , 'def logistic_loglik(params,t,data,sig): ----> 5 return sum(norm.logpdf(logistic(ratio, t, params),sig))' and 'S, R, A = x' but have been unable to solve this issue so I was hoping you could offer some advice on how to proceed – Matthew Freeman Dec 15 '17 at 11:12
  • I feel that the error is it is only expecting values for S, R and A but is getting more it think this could be due to the structure of 'x' but am not sure how to improve this or it could be that the 'ratio' may ben needed somewhere in these lines but I cant work out where – Matthew Freeman Dec 15 '17 at 11:29
  • Great that it helped. BTW, you can [accept](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) an answer if it solves your problem. You can ask a new question if you have a new problem. – Mike Müller Dec 15 '17 at 11:52
  • Yes sorry im new to the site so didnt know about accepting answers also i have asked about this new error under that question ValueError: too many values to unpack (expected 3)? if you woouldnt mind taking a look. thanks again – Matthew Freeman Dec 15 '17 at 12:07
  • Do you have link to your new question? – Mike Müller Dec 15 '17 at 12:09
  • [link](https://stackoverflow.com/questions/47792503/valueerror-too-many-values-to-unpack-expected-3/47793867?noredirect=1#comment82624392_47793867) this is the link. thanks – Matthew Freeman Dec 15 '17 at 12:24