-2

I have been having issues with the code I am trying to right with the model I am trying to code the following error has appeared and being a relative novice I am unsure of how to resolve it.

ValueError                                Traceback (most recent call last)
<ipython-input-2-5f21a0ce8185> 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-2-5f21a0ce8185> 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(data, t, params),sig))
      6 
      7 # set standard deviations to be 10% of the population values

<ipython-input-1-c9480e66b7ef> in logistic(x, t, params)
      6 
      7 def logistic(x,t,params):
----> 8     S, R, A = x
      9     r, Nmax, delta_s, beta, gamma, delta_r, delta_a, Emax, H, MICs, MICr = params
     10     N = S + R

ValueError: too many values to unpack (expected 3) 

The model I am trying to code is an MCMC to fit some ODE's to some data I have added the code below for 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(data, t, params),sig))

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

# parameters for the MCMC
reps = 50000
npars = 3

# output matrix
par_out = np.ones(shape=(reps,npars))
# acceptance 
accept = np.zeros(shape=(reps,npars))
# 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])

I think its mistaking my parameters for something else but that might be wrong. I am using Jupyter notebook

Matthew Freeman
  • 3
  • 1
  • 2
  • 7
  • Your error is in this line in logistic method: S, R, A = x .. As I can see you are passing proposed to x.So, proposed should have a list having 3 elements. – Sumit S Chawla Dec 13 '17 at 12:19
  • Would I do this with code such as: S = x[0] R=x[1] A=x[2] or is that just converting them to a vector? – Matthew Freeman Dec 13 '17 at 12:40
  • If you have say, x=[0,1,2] or some other value. Then it would work as S,R,A =x but the problem is I suppose x is not having three values. – Sumit S Chawla Dec 13 '17 at 12:44
  • Do you have any working example for the procedure in the second cell that you have taken this code from and adapted? What is the theory behind it, what are the variables and what the constant of this fitting process? – Lutz Lehmann Dec 14 '17 at 11:50
  • Yes the code is adapted from code i was given. Not sure what you mean by theory as all i had to do was add the plot function. And am unsure of the last two as well though i could find and upload the original code i got it from if this would be helpful – Matthew Freeman Dec 14 '17 at 15:56

2 Answers2

1

You cannot use S, R, A = x, if x is empty or has not enough (too much) values to unpack.

For what I see, you are trying to define S, R and A values using the variable x. It is possible in that way only if x is the len of 3. If you want to assign certain x values to specific S, R or A use loop, or if you want to do this that way you can use:

S, R, *A = x,

this way the variable S and R will have the first and second element of x, and variable A the rest. You can put * before any variable to make it take the excessive values you store in x.

Sqoshu
  • 944
  • 2
  • 9
  • 16
0

The immediate syntax error

In your call

---> 28             alpha = np.exp(logistic_loglik(proposed,time,ExRatio,sig)-logistic_loglik(par_out[i-1,],time,ExRatio,sig))

to

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

where finally the paramerers are used as defined in

      7 def logistic(x,t,params):
----> 8     S, R, A = x

the x that causes the error is the data of the previous call which is set to exTatio in the first call which is defined in your first block as an array of several handful of values. There might be something wrong with the logic that you use, as the structure of exRatio is not the one of 3 state variables.


The correct implementation of the concept of the log-likelihood sum

What you want is to compute the log-likelihood of the computed ratios at your sample points where the distribution for ExTime[k] is given as a normal distribution with mean ExRatio[k] and variance sig[k] which is set to ExRatio[k]/10. In your code you need to do exactly that, solve the ODE with the proposed initial values, compute the ratios and sum the logs of the pdf values:

# set up a function to return the log likelihood
def logistic_loglik(SRA0,ExTime,ExRatio,sig):
    # solve the ODE with the trial values `SRA0` and 
    # output the samples at the sample times `ExTime`
    logistic_out = odeint(logistic, SRA0, ExTime, args=(params,))
    # compute the ratios
    ratio = 100* logistic_out[:,1]/(logistic_out[:,0]+logistic_out[:,1])
    # return the summed log-likelihood
    return sum(norm.logpdf(ratio, ExRatio, sig))

Trying variants of propsigma leads to initially rapid convergence to qualitatively reasonable fits.

propsigma       i       S, R, A = par_out[i]

[0.05,20.,5.]  59 [ 2.14767909    0.18163897   5.45312544]
[20,0.5,5.]    39 [ 56.48959836   0.50890498   5.80229728]
[5.,2.,5.]     79 [ 67.26394337   0.15865463   6.0213663 ]
Community
  • 1
  • 1
Lutz Lehmann
  • 25,219
  • 2
  • 22
  • 51
  • The S, R and A are in relation to the ODE equations for the model so I'm not sure what I need to do to fix this error. Do I need to change the structure of ExRatio or x to resolve the issue? – Matthew Freeman Dec 13 '17 at 15:22
  • Does your code work at all? I can't see that the assignment of `params` works in that direction. – Lutz Lehmann Dec 13 '17 at 16:10
  • The first cell produces a graph plotting both the model results (ratio) and experimental data (ExRatio) against time as expected but the second cell doesn't work I only received this error after solving the TypeError: logistic() missing 1 required positional argument: 'params' by modifying line 5 to how it appears above – Matthew Freeman Dec 13 '17 at 16:27
  • This does not make any sense. If ratio is `R/(S+R)*100`, then you would have to somehow reconstruct `S` and `R`, and probably also `A`, by some inversion of this formula. At least there should be a division by 100 somewhere. If you want to fit `ratio` to `ExRatio`, then this is a non-linear problem requiring an iterative solution that is not present in the code. – Lutz Lehmann Dec 13 '17 at 16:39
  • ratio is or at least should be coded as '100*R/(R+S)' not sure if this changes what is wrong with this code resulting in the error – Matthew Freeman Dec 13 '17 at 16:49
  • I think i understand what the first bock of code works but am unsure of where it fits in to the model as lines within it are similar to both cells also does the line 'logistic_out' need running again i already used it in the first cell where it appeared to solve the ODE fine – Matthew Freeman Dec 14 '17 at 15:51
  • Each try has different initial values and thus gives different solutions to the ODE. Thus the need for the integration. Which also means that you should avoid to recompute the same value over and over again. – Lutz Lehmann Dec 14 '17 at 16:47
  • Sorry im really a beginner to this so i don't really understand what that requires me to do? – Matthew Freeman Dec 14 '17 at 23:46
  • You seem to have the problem of insufficient knowledge in the mathematical and computational side of this. You need to get clarity on 1) that you are trying to maximize a function; 2) what the objective function is, it has to do with the log-likelihood sum; 3) what the objective has to do with the curve fitting task, it can be reduced to (the negative of) a weighted squared error sum; 4) the maximum search algorithm and how the semi-random search direction and random acceptance work together and 5) why a line search along a random search direction would give a result faster. – Lutz Lehmann Dec 15 '17 at 10:54