[R] Integration in R
Rui Barradas
ruipbarradas at sapo.pt
Tue Oct 2 20:01:32 CEST 2012
Hello,
Yes, it's possible to remove the loop. Since the loop is used to compute
a running product and all we want is the final result, use the
vectorized behavior of R and a final ?prod().
Seedup: another 2x. And 4x2 == 8 == 1 [decimal] order of magnitude.
lf2 <-function (x) {
v<-1
x1 <- x[1]
x2 <- x[2]
x3 <- x[3]
x4 <- x[4]
z1 <- exp(x1+x2*dose)
z2 <- exp(x3+x4*dose)
psi0<-1/((1+z1)*(1+z2))
psi1<-z1*psi0
v <- (psi0^y0)*(psi1^y1)*((1-psi0-psi1)^y2)
return( prod(v) )
}
lf2.c <- cmpfun(lf2)
Hope this helps,
Rui Barradas
Em 02-10-2012 18:21, Berend Hasselman escreveu:
> On 02-10-2012, at 17:23, Naser Jamil <jamilnaser79 at gmail.com> wrote:
>
>> Dear R-users,
>> I am facing problem with integrating in R a likelihood function which is a
>> function of four parameters. It's giving me the result at the end but
>> taking more than half an hour to run. I'm wondering is there any other
>> efficient way deal with. The following is my code. I am ready to provide
>> any other description of my function if you need to move forward.
>>
>> ------------------------------------------------------------------------------------------------------------------------------------
>>
>> library(cubature)
>> dose<-c(2,3,5)
>> y0<-c(2,1,0)
>> y1<-c(1,1,1)
>> y2<-c(0,1,2)
>>
>> lf<-function (x) {
>> v<-1
>> for (i in 1:length(dose)) {
>> psi0<-1/((1+exp(x[1]+x[2]*dose[i]))*(1+exp(x[3]+x[4]*dose[i])))
>>
>> psi1<-exp(x[1]+x[2]*dose[i])/((1+exp(x[1]+x[2]*dose[i]))*(1+exp(x[3]+x[4]*dose[i])))
>> v<-v*(psi0^y0[i])*(psi1^y1[i])*((1-psi0-psi1)^y2[i])
>> }
>> return(v)
>> }
>>
>> adaptIntegrate(lf, lowerLimit = c(-20, 0,-20,0), upperLimit = c(0,10,0,10))
>>
> There are several things you could do.
>
> 1. Use the compiler package to make a compiled version of your function.
> 2. rewrite your function by putting x[1] etc. in separate variables x1, x2,... so avoiding the [..] indexing. You can do the same for dose[i].
> And also compiling this version of the function.
> 3. do not recompute expressions such as exp(x1+x2*dose.i) several times. Store the result in a temporary variable and use that variable.
>
> With these functions
>
> library(compiler)
>
> lf.c <- cmpfun(lf)
>
> lf1 <-function (x) {
> v<-1
> x1 <- x[1]
> x2 <- x[2]
> x3 <- x[3]
> x4 <- x[4]
> for (i in 1:length(dose)) {
> dose.i <- dose[i]
> z1 <- exp(x1+x2*dose.i)
> z2 <- exp(x3+x4*dose.i)
> psi0<-1/((1+z1)*(1+z2))
> psi1<-z1*psi0
> v<-v*(psi0^y0[i])*(psi1^y1[i])*((1-psi0-psi1)^y2[i])
> }
> return(v)
> }
>
> lf1.c <- cmpfun(lf1)
>
> I tested relative speeds with this code (small tolerance and max. function evaluations)
>
> library(rbenchmark)
>
> f1 <- function() adaptIntegrate(lf , lowerLimit = c(-20, 0,-20,0), upperLimit = c(0,10,0,10), tol=1e-3,maxEval=50000)
> f2 <- function() adaptIntegrate(lf.c , lowerLimit = c(-20, 0,-20,0), upperLimit = c(0,10,0,10), tol=1e-3,maxEval=50000)
> f3 <- function() adaptIntegrate(lf1 , lowerLimit = c(-20, 0,-20,0), upperLimit = c(0,10,0,10), tol=1e-3,maxEval=50000)
> f4 <- function() adaptIntegrate(lf1.c, lowerLimit = c(-20, 0,-20,0), upperLimit = c(0,10,0,10), tol=1e-3,maxEval=50000)
> benchmark(z1 <- f1(),z2 <- f2(), z3 <- f3(),z4 <- f4(),replications=1)
>
> Result:
>
>> benchmark(z1 <- f1(),z2 <- f2(), z3 <- f3(),z4 <- f4(),replications=1)
> test replications elapsed relative user.self sys.self user.child
> 1 z1 <- f1() 1 3.197 4.535 3.177 0.008 0
> 2 z2 <- f2() 1 1.240 1.759 1.235 0.003 0
> 3 z3 <- f3() 1 2.171 3.079 2.167 0.002 0
> 4 z4 <- f4() 1 0.705 1.000 0.700 0.004 0
>
> As you can see you should be able to get at least a fourfold speedup by using the compiled version of the optimized function.
> I would certainly set tol and maxEval to something reasonable initially.
> Checking that z1, z2, z3, and z4 are equal is left to you.
>
> Finally, it may even be possible to eliminate the for loop in your function but I'll leave that for someone else.
>
> Berend
>
> ______________________________________________
> R-help at 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.
More information about the R-help
mailing list