[R] optim works on command-line but not inside a function

Damokun dmroijer at students.cs.uu.nl
Wed Nov 3 15:10:39 CET 2010


Dear all, 

I am trying to optimize a logistic function using optim, inside the
following functions: 
#Estimating a and b from thetas and outcomes by ML

IRT.estimate.abFromThetaX <- function(t, X, inits, lw=c(-Inf,-Inf),
up=rep(Inf,2)){

  optRes <- optim(inits, method="L-BFGS-B", fn=IRT.llZetaLambdaCorrNan, 

      gr=IRT.gradZL, 

      lower=lw, upper=up, t=t, X=X)

  c(optRes$par[2], -(optRes$par[1]/optRes$par[2]) )

}

#Estimating a and b from thetas and outcomes by ML, avoiding 0*log(0)
IRT.estimate.abFromThetaX2 <- function(tar, Xes, inits, lw=c(-Inf,-Inf),
up=rep(Inf,2)){

  optRes <- optim(inits, method="L-BFGS-B", fn=IRT.llZetaLambdaCorrNan, 

      gr=IRT.gradZL, 

      lower=lw, upper=up, t=tar, X=Xes)

  c(optRes$par[2], -(optRes$par[1]/optRes$par[2]) )

}

The problem is that this does not work: 
> IRT.estimate.abFromThetaX(sx, st, c(0,0))
Error in optim(inits, method = "L-BFGS-B", fn = IRT.llZetaLambdaCorrNan,  : 
  L-BFGS-B needs finite values of 'fn'
But If I try the same optim call on the command line, with the same data, it
works fine:
> optRes <- optim(c(0,0), method="L-BFGS-B", fn=IRT.llZetaLambdaCorrNan, 
+       gr=IRT.gradZL, 
+       lower=c(-Inf, -Inf), upper=c(Inf, Inf), t=st, X=sx)
> optRes
$par
[1] -0.6975157  0.7944972
$convergence
[1] 0
$message
[1] "CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH"

Does anyone have an idea what this could be, and what I could try to avoid
this error? I tried bounding the parameters, with lower=c(-10, -10) and
upper=... but that made no difference. 

Thanks, 
Diederik Roijers
Utrecht University MSc student. 
------
PS: the other functions I am using are: 

#IRT.p is the function that represents the probability 
#of a positive outcome of an item with difficulty b, 
#discriminativity a, in combination with a student with
#competence theta. 

IRT.p <- function(theta, a, b){

   epow <- exp(-a*(theta-b))

   result <- 1/(1+epow)

   result

}


# = IRT.p^-1 ; for usage in the loglikelihood

IRT.oneOverP <- function(theta, a, b){

   epow <- exp(-a*(theta-b))

   result <- (1+epow)

   result

}

# = (1-IRT.p)^-1 ; for usage in the loglikelihood
IRT.oneOverPneg <- function(theta, a, b){

   epow <- exp(a*(theta-b))

   result <- (1+epow)

   result

}


#simulation-based sample generation of thetas and outcomes
#based on a given a and b. (See IRT.p) The sample-size is n

IRT.generateSample <- function(a, b, n){

   x<-rnorm(n, mean=b, sd=b/2)

   t<-IRT.p(x,a,b)

   ch<-runif(length(t))

   t[t>=ch]=1

   t[t<ch]=0

   cbind(x,t)

}


#This loglikelihood function is based on the a and be parameters, 
#and requires thetas as input in X, and outcomes in t
#prone to give NaN errors due to 0*log(0)

IRT.logLikelihood2 <- function(params, t, X){

   pos<- sum(t * log(IRT.p(X,params[1],params[2])))

   neg<- sum(  (1-t) * log( (1-IRT.p(X,params[1],params[2])) )  )

   -pos-neg

}

#Avoiding NaN problems due to 0*log(0) 
#otherwise equivalent to IRT.logLikelihood2
IRT.logLikelihood2CorrNan <- function(params, t, X){

   pos<- sum(t * log(IRT.oneOverP(X,params[1],params[2])))

   neg<- sum((1-t) * log(IRT.oneOverPneg(X,params[1],params[2])))

   -pos-neg

}

#IRT.p can also be espressed in terms of z and l 
#where z=-ab and l=a <- makes it a standard logit function

IRT.pZL <- function(theta, z, l){

   epow <- exp(-(z+l*theta))

   result <- 1/(1+epow)

   result

}

#as IRT.oneOverP but now for IRT.pZL 
IRT.pZLepos <- function(theta, z, l){

   epow <- exp(-(z+l*theta))

   result <- (1+epow)

   result

}


#as IRT.oneOverPneg but now for IRT.pZL 
IRT.pZLeneg <- function(theta, z, l){

   epow <- exp(z+l*theta)

   result <- (1+epow)

   result

}



#The loglikelihood of IRT, but now expressed in terms of z and l

IRT.llZetaLambda <- function(params, t, X){

   pos<- sum(t * log(IRT.pZL( X,params[1],params[2]) ))

   neg<- sum(  (1-t) * log( (1-IRT.pZL(X,params[1],params[2] )) )  )

   -pos-neg

}

#Same as IRT.logLikelihood2CorrNan but for IRT.llZetaLambda
IRT.llZetaLambdaCorrNan <- function(params, t, X){

   pos <- sum(t * log(IRT.pZLepos( X,params[1],params[2]) ))

   neg <- sum((1-t) * log(IRT.pZLeneg(X,params[1],params[2]) ))

   pos+neg

}


#Gradient of IRT.llZetaLambda

IRT.gradZL <- function(params, t, X){

  res<-numeric(length(params))

  res[1] <- sum(t-IRT.pZL( X,params[1],params[2] ))

  res[2] <- sum(X*(t-IRT.pZL( X,params[1],params[2] )))

  -res

}

#And to create the sample: 
s <- IRT.generateSample(0.8, 1, 50)
sx <- s[,1]
st <- s[,2]
IRT.estimate.abFromThetaX(sx, st, c(0,0))


-- 
View this message in context: http://r.789695.n4.nabble.com/optim-works-on-command-line-but-not-inside-a-function-tp3025414p3025414.html
Sent from the R help mailing list archive at Nabble.com.



More information about the R-help mailing list