Dear Ben

I haven't looked at the profiles yet, I'm not sure how to.
I'm doing population reconstruction from age-at-harvest data. I'm using a multinomial distribution to model the observed harvest numbers. But I didn't know about the Dirichlet-Multinomial so far. I think that might really be a good option because overdispersion is likeliy to be an issue here. Below I have copied my code for the simulation of data (the first example works, the other gives poor fit) and subsequent optimization. I'm sorry the code is very long, but I didn't know how to short it down.

The problem:
Q=harvest rate -> if harvest rates are too small the model fits the data very bad.

Here is the R code:

library(boot)
library(bbmle)
library(demogR)
library(msm)

##########################################
##########################################
##Stochastic model -> DATA SIMULATION
##########################################

a<-8                                                                         # 
nr of age classes
y<-30                                                                           
     # nr of years

m<-c(rep(0.2,2),rep(0.75,4),0.5,0.2) # productivity -> nr of young/female
m.time<-matrix(rtnorm(a*y,m,0.1,lower=0),ncol=a,byrow=T)


############################################################
##TWO VERSIONS OF Q=HARVEST RATE->Q1 WORKS, Q2 GIVES BAD FIT
############################################################

Q<-c(rep(0.2,2),rep(0.3,3),0.4,0.6,0.9) #WORKS # true mean harvest mortality rates Q<-c(rep(0.02,2),rep(0.03,3),0.4,0.6,0.9) #BAD FIT # true mean harvest mortality rates

Q.time<-matrix(rtnorm(a*y,Q,0.06,lower=0,upper=1),ncol=a,byrow=T) # adding random noise
#############################################################
#############################################################


P<-c(0.5,rep(0.9,4),rep(0.8,2),0.7)                                  # natural 
survival rates
P.time<-matrix(rtnorm(a*y,P,0.06,lower=0,upper=1),ncol=a,byrow=T) # adding random noise


L.time<-(1-Q.time[,1:(a-1)])*P.time[,2:a] # Overall survival -> Derived parameter

F.time<-m.time*P.time[,1]                                            # Fecundity   
    -> Derived parameter

Lm.time<-array(0,c(a,a,y)) # Lesli-matrix-array -> for each year a new matrix
for (i in 1:y){
Lm.time[,,i]<-odiag(L.time[i,],-1)                                   # survival 
in the off-diagonal
}

for (i in 1:y){                                                         # 
fecundity in the first row
Lm.time[1,,i]<-F.time[i,]
}

Hm.time<-array(0,c(a,a,y)) # Harvest-matrix-array -> for each year a new matrix
for (i in 1:y){
Hm.time[,,i]<-odiag(Q.time[i,])                                      # 
mortality rates in the diagonal
}

N1<-rep(200,a)                                                               # 
Define the starting vector of cohort sizes
N.true<-matrix(rep(0,a*y),ncol=a)                                    # True 
abundance matrix
N.true[1,]<-N1
C<-matrix(rep(0,a*y),ncol=a)                                         # Harvest 
matrix

for (i in 1:(y-1)){
N.true[i+1,]<-Lm.time[,,i]%*%N.true[i,]
}
N.true<-round(N.true)                                                        # 
round the counts of the true population

for (i in 1:y){
C[i,]<-Hm.time[,,i]%*%N.true[i,]
}
C<-round(C)                                                                  
#round the counts of the harvest numbers

plot(rowSums(N.true)~seq(1:y),ylim=c(0,4000),col="red") # Plot the time series of the simulated data lines(rowSums(N.true)~seq(1:y),col="red") # true population and true harvest numbers
points(rowSums(C)~seq(1:y),ylim=c(0,4000),col="blue")
lines(rowSums(C)~seq(1:y),col="blue")


###########################################################################
###########################################################################

############################
##ANALYSIS OF SIMULATED DATA
############################

##Simulated harvest numbers of a cohort harvested over 30 years (including random noise)
pop<-N.true                                                  # True population 
size
cohort<-C                                                    # harvest matrix
R<-nrow(cohort)
L<-ncol(cohort)
        
h<-matrix(rep(Q,R),ncol=a,byrow=T)   # estimated harvest rates
S<-matrix(rep(P[-1],R),ncol=a-1,byrow=T)     # survival rates

##############################################
##Function to calculate the cell probabilities
##############################################

predprob <- function(S=S,h=h) {
  R<-nrow(cohort)
  L<-ncol(cohort)
  p <- matrix(rep(0,(R)*(L)),ncol=L)         # matrix of cell probabilities
        p[R,1]<-h[R,1]
        p[1,L]<-h[1,L]
ay<-rep(0,L+R+1) # vector of last cell probabilities -> 1-sum(rest));Gove(2002)
        ay[L+R]<-1-h[1,L]
        ay[2]<-1-h[R,1]
index<-3 # ay[1]=Null, ay[2]=1-h[R,1],ay[L+R]=1-h[1,L], ay[L+R+1]=Null


for (i in -(R-2):(L-2)){                                # Calculating the cell 
prob after Gove (2002)

p[row(p) == col(p) - i] <- odiag(h,i)*c(1,cumprod((1-odiag(h[1:(R-1),1:(L-1)],i))
                                                *odiag(S[1:(R-1),],i)))
        
        ay[index]<-1-sum(odiag(p[1:R,],i))
        
        index<-index+1
   }

        p<-rbind(p,ay[1:L])
        p<-cbind(p,ay[length(ay):(L+1)])
return(p)

 }

predprob(S,h)                                           #test the function

####################################
##Function to calculate the multinomial ->from Ben Bolker
####################################

## multinom WITHOUT ROUNDING & without error-checking
dmnom <- function(x,prob,log=FALSE) {
  r <- lgamma(sum(x) + 1) + sum(x * log(prob) - lgamma(x + 1))
  if (log) r else exp(r)
}

###########################
## function to be optimized
###########################

mfun <- function(logN,S=S,h=h,cohort=cohort) {
  L<-ncol(cohort)
  R<-nrow(cohort)
d<-matrix(rep(NA,(R+1)*(L+1)),ncol=L+1) # last row and last col of the matrix d[1:R,1:L]<-log(cohort) # are the values to be optimized->Log tranformed data!

  index<-1
  index1<-(R+L)

for (i in -(R-1):(L-1)){                                # values for the top row
if (i<= -(R-L) ){
d[(R+1),(index+1)]<-log(exp(logN[index])-sum(odiag(cohort,i)))} else
if (i> -(R-L)& i<1 ){
d[index1,(L+1)]<-log(exp(logN[index])-sum(odiag(cohort,i)))} else
if (i>0){
d[index1,(L+1)]<-log(exp(logN[index])-sum(odiag(cohort,i)))}

index<-index+1
index1<-index1-1
}
pp<-predprob(S,h)

lhood<-0                                                     # The Likelihood 
function -> to be maximized

for (i in -(R-1):(L-1)){
 lhood<-lhood+(-dmnom(exp(odiag(d,i)),prob=odiag(pp,i),log=TRUE))
}
return(lhood)
}

logN<-log(rep(1000,(R+L-1)))                         # Test the function with 
test-values
mfun(logN,S,h,cohort)

##########################################################################################
##########################################################################################

######################################
##Starting values for the optimization
######################################

N<-rep(500,(R+L-1))                                  # optimization,->N-x1-x2-x3
svec = log(N)                                           # transform to avoid 
constraints (x>0)
names(svec) <- paste("logN",1:(R+L-1),sep="")
parnames(mfun) <- names(svec)

######################################
##Lower bounds for the L-BFGS-B-method
######################################

index<-1
lower<-rep(0,(R+L-1))

for (i in -(R-1):(L-1)){
lower[index]<-log(sum(odiag(cohort,i)))
index<-index+1
}

lower<-lower+0.001
names(lower)<-names(svec)
exp(lower)                                                      # check lower 
bounds

#########################
##Optimization with mle2
#########################

## use bounded optimization

m1 = mle2(mfun,start=svec,
method="L-BFGS-B",lower=lower,upper=10, # lower=must be larger than "sum(odiag(x))"<-if smaller NANs are produced
  vecpar=TRUE,
  data=list(S=S,h=h,cohort=cohort))

coef(m1)

Nest<-exp(coef(m1))                                  # estimated cohort sizes 
for row and colum 1

############################################################################################
############################################################################################

#####################
##Analyse the Goodness of fit
#####################

Nya<-matrix(rep(0,length(cohort)),ncol=L) # project the N estimates into a matrix
Nya[1,1:L]<-Nest[R:length(Nest)]
Nya[2:R,1]<-rev(Nest[1:(R-1)])


stot<-(1-Q[1:(a-1)])*P[2:a] # derived survival -> product of (1-h(i)) amd s(i)
smat<-matrix(rep(stot,R),ncol=L-1,byrow=T)

for (i in 1:ncol(smat)){                                # project the N 
estimates trough time
Nya[2:R,i+1]<-Nya[1:(R-1),i]*smat[1:(R-1),i]
}


#######################
##Expected harvest values compared with observed harvest numbers
#######################

exp<-Nya*h
obs<-cohort

gof<-((obs-exp)^2)/exp # Goodness of fit for the single estimates # Overall GOF statistic
gof.stat<-sum(gof)                                   # GOF statistic
p.value<-1-pchisq(gof.stat,(length(obs)-1)) # p-value with appropriate degrees of freedom
p.value

plot(obs~exp,main="Observed harvest numbers vs expected from the model",xlim=c(0,200),ylim=c(0,200))
abline(0,1)

##################
##Plots
##################
##Plot true population trend <-> compare with estimated trend

plot(rowSums(N.true)~seq(1:y),ylim=c(0,5000),col="red",pch=17,main="True vs estimated population trend")
lines(rowSums(N.true)~seq(1:y),col="red")

points(rowSums(Nya)~seq(1:y),ylim=c(0,5000),col="blue",pch=16)
lines(rowSums(Nya)~seq(1:y),col="blue")

###############################################################
###############################################################
##########
##END#####
##########

Thanks a lot for the help!!!!

Benedikt



On Tue, 9 Mar 2010 15:34:09 +0000 (UTC)
 Ben Bolker <bol...@ufl.edu> wrote:
Benedikt Gehr <benedikt.gehr <at> ieu.uzh.ch> writes:


Hi there

I am using mle2 for a multinomial likelihood optimization problem. My function works fine when I'm using simulated data, however my cell probabilities of the true data for the multinomial likelihood are sometimes very small (in some cases <0.00...) and the estimated point estimates fit the true vlaues quite poorly. Is there a way how to handle near zero probabilities in maximum likelihood optimization?


 Hard to say without more detail.  Can you send a reproducible
example (your data, or a small subset of your data, or
some way of simulating the data that *does* create the problem)?

 Since you're using log-likelihoods already (within mle2) the
problem is unlikely (?) to be numerical -- R doesn't have any
problem with very large negative log-likelihoods.  Do your
likelihood profiles look reasonable?  If so then the problem
is more likely that your model doesn't fit the data well than
that you are having convergence problems.

 Have you considered the possibility of overdispersion
(non-homogeneity/non-independence), e.g. via a Dirichlet-multinomial
model?

______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
  • [... Benedikt Gehr
    • ... Ben Bolker
      • ... paaventhan jeyaganth
        • ... David Winsemius
          • ... Frank E Harrell Jr
      • ... Benedikt Gehr, Institut für Evolutionsbiologie und Umweltwissenschaften

Reply via email to