kingaa / pomp

R package for statistical inference using partially observed Markov processes
https://kingaa.github.io/pomp
GNU General Public License v3.0
111 stars 27 forks source link

Error in is.nloptr(ret) : objective in x0 returns NA #88

Closed minjuner closed 5 years ago

minjuner commented 5 years ago

When estimating the SIR model parameters, I first set a parameter range, then use the trajectory matching to select some of the desirable parameters, but there is an error in running traj.match: Error in is.nloptr(ret) : objective in x0 returns NA.

Here is my code and data file.zip


model1<-pomp(data1, times = "time",
             t0=1999.915,
             rprocess = euler.sim(step.fun = Csnippet(seas.sir.step), delta.t = 1/12/30),
             dmeasure = Csnippet(dmeas),
             rmeasure = Csnippet(rmeas),
             toEstimationScale = toEst,
             fromEstimationScale = fromEst,
             covar = covar1,
             tcovar = "time",
             zeronames = c("H"),
             statenames = c("S", "I", "R", "H", "P"),
             paramnames = c("gamma", "popsize", "rho", "sigma", "S.0", "I.0",
                            "R.0","betas" , "betam", "iota","pha"),
             initializer = function(params, t0, ...) {
               fracs <- params[c("S.0", "I.0", "R.0")]
               setNames(c(round(params["popsize"] * c(fracs/sum(fracs), 1)), 0), c("S","I", "R", "P", "H"))
             },
             params = c(popsize = 126931430, iota = 92, betas = 0.25, betam = 1706, gamma = 52, pha=0.7,
                        rho = 1.94e-04,  sigma =0.0000001, S.0 = 0.0254, I.0 = 1.48e-04,R.0 = 0.9745)
)

library(foreach)
library(doParallel)
library(tgp)
registerDoParallel()

estpar_name<-c("iota","betas","betam","rho","pha","S.0","I.0","R.0")
para<- rbind(x1 = c(0,1000),               
             x2 = c(0,1),                  
             x3 = c(1,10000),                
             x4 = c(0,0.3),
             x5=c(0,1),
             x6=c(0,0.1),
             x7=c(0,0.1))
n <- 40000
set.seed(123)
parameters <- lhs(n, para)
estpar<-as.data.frame(parameters)
R_0<-1-estpar[6]-estpar[7]
estpar<-cbind(estpar,R_0)
colnames(estpar)<-estpar_name
estpar["popsize"]<-126931430
estpar["gamma"]=52
estpar["sigma"]=0.00001

p=estpar[1,]
model1%>% traj.match(start=unlist(p),est=estpar_name,method="nloptr",
                 algorithm="NLOPT_GN_MLSL",transform=TRUE)->out
 sessionInfo 
-----------------------------------
R version 3.5.1 (2018-07-02)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

Matrix products: default

locale:
[1] LC_COLLATE=Chinese (Simplified)_China.936  LC_CTYPE=Chinese (Simplified)_China.936   
[3] LC_MONETARY=Chinese (Simplified)_China.936 LC_NUMERIC=C                              
[5] LC_TIME=Chinese (Simplified)_China.936    

attached base packages:
[1] parallel  stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] doParallel_1.0.14 iterators_1.0.10  foreach_1.4.4     tgp_2.4-14        tidyr_0.8.3       readxl_1.2.0     
 [7] knitr_1.21        pomp_1.19         magrittr_1.5      reshape2_1.4.3    plyr_1.8.4        ggplot2_3.1.0    

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.0       cellranger_1.1.0 pillar_1.3.1     compiler_3.5.1   nloptr_1.2.1     tools_3.5.1     
 [7] rpart_4.1-13     digest_0.6.18    tibble_2.0.1     gtable_0.2.0     lattice_0.20-35  pkgconfig_2.0.2 
[13] rlang_0.3.1      rstudioapi_0.9.0 mvtnorm_1.0-8    xfun_0.4         coda_0.19-2      cluster_2.0.7-1 
[19] withr_2.1.2      dplyr_0.8.0.1    stringr_1.3.1    grid_3.5.1       tidyselect_0.2.5 maptree_1.4-7   
[25] deSolve_1.21     glue_1.3.0       R6_2.3.0         purrr_0.3.1      codetools_0.2-15 scales_1.0.0    
[31] assertthat_0.2.0 colorspace_1.4-0 labeling_0.3     subplex_1.5-4    stringi_1.2.4    lazyeval_0.2.1  
[37] munsell_0.5.0    crayon_1.3.4    
kingaa commented 5 years ago

The problem is that your deterministic skeleton is a vectorfield, not a map. That is, your deterministic model evolves in continuous time. See the following, which updates your code to pomp2.

set.seed(594709947L)
library(tidyverse)
theme_set(theme_bw())
library(pomp2)
library(readxl)
library(tgp)

demogra <- read_xls("demogra.xls")
data_1 <- read_excel("japan_data.xlsx",sheet=1)

skel<- "
  double rate[6];
  double term[6];
  double Beta;
  Beta = betam*(1 + betas * cos(M_2PI*(t+pha)));
  rate[0] = birthrate1;
  rate[1] = Beta * (I + iota)/pop;
  rate[2] = deathrate1;
  rate[3] = gamma;
  rate[4] = deathrate1;
  rate[5] = deathrate1;

  term[0]=rate[0];
  term[1]=rate[1]*S;
  term[2]=rate[2]*S;
  term[3]=rate[3]*I;
  term[4]=rate[4]*I;
  term[5]=rate[5]*R;

//  for (int k = 0; k < 6; k++) Rprintf(\"%lg \",rate[k]);
//  Rprintf(\"\\n\");

  DS= term[0] - term[1] - term[2];
  DI= term[1] - term[3] - term[4];
  DR= term[3] - term[5];
  DH= term[1];"

data_1 %>%
  mutate(
    date=as.Date(sprintf("%04d-%02d-01",year,month)),
    time=julian(date,origin=as.Date("2000-01-01"))/365.25+2000
  ) %>%
  select(time,case="Coxsackievirus A4") %>%
  filter(time<2015) %>%
  pomp(times = "time", t0=2000-1/12,
    skeleton=vectorfield((Csnippet(skel))),
    covar = covariate_table(
      time=with(demogra,seq(from=min(year)-1/12,to=max(year)+1/12,by=1/12)),
      pop=with(demogra,predict(smooth.spline(x=year,y=pop),x=time)$y),
      birthrate1=with(demogra,predict(smooth.spline(x=year,y=birth,spar = 0.2),x=time)$y),
      deathrate=with(demogra,predict(smooth.spline(x=year,y=death, spar = 0.2),x=time)$y),
      deathrate1=deathrate/pop,
      times="time"
    ),
    # covar = covariate_table(covar1,times="time"),
    accumvars = c("H"),
    statenames = c("S", "I", "R", "H"),
    paramnames = c("gamma", "rho", "sigma",
      "S.0", "I.0", "R.0",
      "betas" , "betam", "iota","pha"),
    rinit = function (S.0, I.0, R.0, pop, ...) {
      s <- pop/(S.0+I.0+R.0)
      c(S=round(s*S.0),I=round(s*I.0),R=round(s*R.0),H=0)
    },
    params = c(iota = 92, betas = 0.25, betam = 1706,
      gamma = 52, pha=0.7,
      rho = 1.94e-04,  sigma =0.0000001,
      S.0 = 0.0254, I.0 = 1.48e-04, R.0 = 0.9745)
  ) -> model1

estpar_name <- c("iota","betas","betam","rho","pha","S.0","I.0","R.0")

rbind(
  iota = c(0,1000),
  betas = c(0,1),
  betam = c(1,10000),
  rho = c(0,0.3),
  pha=c(0,1),
  S.0=c(0,0.1),
  I.0=c(0,0.1)
) -> para

lhs(40000,para) %>%
  as.data.frame() %>%
  setNames(rownames(para)) %>%
  mutate(
    R.0 = 1-S.0-I.0,
    gamma = 52,
    sigma = 1e-5
  ) -> estpar

model1 %>%
  trajectory(params=t(estpar[1:20,]),format="d",maxstep=0.001) %>%
  filter(time>2000) %>%
  ggplot(aes(x=time,y=H,group=.id))+
  geom_line()

This shows that the trajectory calculations are free of NaN and NA. From here, to do trajectory matching, you construct an objective function using traj_objfun (adding parameter transformations if needed). This is passed to the optimizer of your choice to do the optimization.

minjuner commented 5 years ago

Thank you, I will try it according to what you said.

kingaa commented 5 years ago

I'll close this issue now, but feel free to reopen it if appropriate.