Re: [R] optim() argument scoping: passing parameter values into user's subfunction

2009-09-09 Thread Bert Gunter
Inline below.

Bert Gunter
Genentech Nonclinical Biostatistics

-Original Message-
From: r-help-boun...@r-project.org [mailto:r-help-boun...@r-project.org] On
Behalf Of Ben Bolker
Sent: Tuesday, September 08, 2009 7:29 PM
To: r-help@r-project.org
Subject: Re: [R] optim() argument scoping: passing parameter values into
user's subfunction




Szumiloski, John wrote:
 
 Dear useRs,
 
 I have a complicated function to be optimized with optim(), and whose
 parameters are passed to another function within its evaluation.  This
 function allows for the parameters to enter as arguments to various
 probability distribution functions.
 
 However, I am violating some scoping convention, as somewhere within the
 hierarchy of calls a variable is not visible.  I will give a genericized
 example here.
 
 myFxn - function(parms, Y, phi, other args) {body of function}
 ### I want to optimize this over its first argument
 
  optim(par=numeric(2), fn=myFxn, ### end of named args, next are
 all in ...
  Y=data,  other args, 
  phi=function(r) pnorm(r, mean=parms[2], sd=parms[1])
  )

This is complicated, but I believe this is what's happening (corrections
from wiser folks would be appreciated if I misstate the situation below):

parms is visible only within the scope of myFxn; by lexical scoping, when
phi is called within myFxn, it goes looking for parms within the environment
it was _defined_, which is optim's, and doesn't find it. Hence the error
message.  Ben's solution below works because it explicitly makes myFxn phi's
closure, thereby giving it access to parms. 

An alternative is to pass parms as a named argument to myFxn. Then it will
look for parms in the _calling_ environment, which will be that of myFxn,
where it will find parms. That is, modify Ben's original version to:

myFxn2 - function(parms, Y,phi,X) {
 ## phi(1) ## not necessary
  sum((Y-(parms[1]+parms[2]*X))^2)
}

set.seed(1001)
X = 1:10
Y = 1+2*X+rnorm(10)
  
optim(par=c(1,2), fn=myFxn2,
  phi = function(r,parms) pnorm(r, mean=parms[2], sd=parms[1]),
  Y=Y, X=X)


This works just fine.

Given the complexity of the original query, I'm not sure this helps, but
maybe ...

--


 Error in pnorm(r, mean = parms[2], sd = parms[1]) : 
   object 'parms' not found
 debugger()## options(error=expression(dump.frames())) in
 .RProfile
 Message:  Error in pnorm(r, mean = parms[2], sd = parms[1]) : 
   object 'parms' not found
 Available environments had calls:
 1: optim(par = numeric(2), fn = myFxn, Y=data, other args, ..
 2: function (par) 
 3: fn(par, ...)
 4: ifelse(logical vector, phi(Y), other stuff within myFxn
 5: phi(Y)
 6: pnorm(r, mean = parms[2], sd = parms[1])
 
 Now, when using the debugger in environments 1 and 2, I can see the
 value of 'par' correctly.  I cannot access environment 4 as it just
 returns the original error message.  Trying to access environment 3
 gives the (to me) cryptic  'Error in get(.obj, envir =
 dump[[.selection]]) :  argument ... is missing, with no default' and
 returns to the top level without debugging.  
 
 I will try to explain to the best of my ability what I think is
 happening here.  Environments 2 and 3 are from the first lines of
 optim(), where it is building an internal function to evaluate the
 candidate parameter values.  When accessing environment 3, it seems like
 when it fills out the ... argument of fn(), it is passing
 phi=function(r) pnorm(r, mean=parms[2], sd=parms[1]) but upon trying to
 evaluate the variable 'parms', it cannot see it in the search path.
 When actually running the original call, 'parms' is apparently not
 evaluated yet, but is once the pnorm call is hit.  It appears the
 'parms' variable is being evaluated before the fn(par) is evaluated into
 myFxn(parms=par).   
 
 A point which is probably, but not certainly, irrelevant:  myFxn() has
 ... as its final argument, so as to pass tuning arguments to
 integrate().  The function being integrated contains phi(), as well as
 other stuff, of a dummy variable.  The calls in the debugging tree,
 however, are *not* those involving integrate().  
 
 It would probably be possible to include some
 substitute/eval/as.name/etc. constructions within the function myFxn, in
 order to avoid this problem, but as myFxn already involves numeric
 integrations whose integrand involves the optimized parameters
 themselves, computing on the language at each step of the optimization
 seems like a bad idea.  
 
 My question: is there a straightforward and efficient way of
 constructing this function and optimizing it with optim(), allowing for
 the argument phi to pass an arbitrary distribution function whose
 parameters are the global ones being optimized?  In particular, in the
 third environment of the debugger tree, is there a way to force the
 fn(par, ...)  myFxn(parms=par, ...) evaluation before the ... get
 evaluated?
 
 Thanks, John
 
 John  Szumiloski,  Ph.D.
 
 Senior Biometrician

[R] optim() argument scoping: passing parameter values into user's subfunction

2009-09-08 Thread Szumiloski, John
Dear useRs,

I have a complicated function to be optimized with optim(), and whose
parameters are passed to another function within its evaluation.  This
function allows for the parameters to enter as arguments to various
probability distribution functions.

However, I am violating some scoping convention, as somewhere within the
hierarchy of calls a variable is not visible.  I will give a genericized
example here.

 myFxn - function(parms, Y, phi, other args) {body of function}
### I want to optimize this over its first argument

  optim(par=numeric(2), fn=myFxn, ### end of named args, next are
all in ...
 Y=data,  other args, 
 phi=function(r) pnorm(r, mean=parms[2], sd=parms[1])
 )
Error in pnorm(r, mean = parms[2], sd = parms[1]) : 
  object 'parms' not found
 debugger()## options(error=expression(dump.frames())) in
.RProfile
Message:  Error in pnorm(r, mean = parms[2], sd = parms[1]) : 
  object 'parms' not found
Available environments had calls:
1: optim(par = numeric(2), fn = myFxn, Y=data, other args, ..
2: function (par) 
3: fn(par, ...)
4: ifelse(logical vector, phi(Y), other stuff within myFxn
5: phi(Y)
6: pnorm(r, mean = parms[2], sd = parms[1])

Now, when using the debugger in environments 1 and 2, I can see the
value of 'par' correctly.  I cannot access environment 4 as it just
returns the original error message.  Trying to access environment 3
gives the (to me) cryptic  'Error in get(.obj, envir =
dump[[.selection]]) :  argument ... is missing, with no default' and
returns to the top level without debugging.  

I will try to explain to the best of my ability what I think is
happening here.  Environments 2 and 3 are from the first lines of
optim(), where it is building an internal function to evaluate the
candidate parameter values.  When accessing environment 3, it seems like
when it fills out the ... argument of fn(), it is passing
phi=function(r) pnorm(r, mean=parms[2], sd=parms[1]) but upon trying to
evaluate the variable 'parms', it cannot see it in the search path.
When actually running the original call, 'parms' is apparently not
evaluated yet, but is once the pnorm call is hit.  It appears the
'parms' variable is being evaluated before the fn(par) is evaluated into
myFxn(parms=par).   

A point which is probably, but not certainly, irrelevant:  myFxn() has
... as its final argument, so as to pass tuning arguments to
integrate().  The function being integrated contains phi(), as well as
other stuff, of a dummy variable.  The calls in the debugging tree,
however, are *not* those involving integrate().  

It would probably be possible to include some
substitute/eval/as.name/etc. constructions within the function myFxn, in
order to avoid this problem, but as myFxn already involves numeric
integrations whose integrand involves the optimized parameters
themselves, computing on the language at each step of the optimization
seems like a bad idea.  

My question: is there a straightforward and efficient way of
constructing this function and optimizing it with optim(), allowing for
the argument phi to pass an arbitrary distribution function whose
parameters are the global ones being optimized?  In particular, in the
third environment of the debugger tree, is there a way to force the
fn(par, ...)  myFxn(parms=par, ...) evaluation before the ... get
evaluated?

Thanks, John

John  Szumiloski,  Ph.D.

Senior Biometrician
Biometrics Research
WP53B-120
Merck Research Laboratories
P.O. Box 0004
West Point, PA 19486-0004

 (215) 652-7346 (PH)
 (215) 993-1835 (FAX)
 
 
#
  obligatory session info

  Windows XP 2002 sp3, customized by corporate IT

 version
   _  
platform   i386-pc-mingw32
arch   i386   
os mingw32
system i386, mingw32  
status Patched
major  2  
minor  9.2
year   2009   
month  09 
day05 
svn rev49600  
language   R  
version.string R version 2.9.2 Patched (2009-09-05 r49600)

 search()
 [1] .GlobalEnvpackage:geometry  package:datasets
mylib1   mylib2  
 [6] package:VGAM  package:stats4package:Design
package:Hmisc package:boot 
[11] package:splines   package:MASS  package:nnet
package:utils package:stats
[16] package:graphics  package:grDevices mylib3
mylib4   mylib5   
[21] mylib6  package:methods   Autoloads
package:base 

Re: [R] optim() argument scoping: passing parameter values into user's subfunction

2009-09-08 Thread Ben Bolker



Szumiloski, John wrote:
 
 Dear useRs,
 
 I have a complicated function to be optimized with optim(), and whose
 parameters are passed to another function within its evaluation.  This
 function allows for the parameters to enter as arguments to various
 probability distribution functions.
 
 However, I am violating some scoping convention, as somewhere within the
 hierarchy of calls a variable is not visible.  I will give a genericized
 example here.
 
 myFxn - function(parms, Y, phi, other args) {body of function}
 ### I want to optimize this over its first argument
 
  optim(par=numeric(2), fn=myFxn, ### end of named args, next are
 all in ...
  Y=data,  other args, 
  phi=function(r) pnorm(r, mean=parms[2], sd=parms[1])
  )
 Error in pnorm(r, mean = parms[2], sd = parms[1]) : 
   object 'parms' not found
 debugger()## options(error=expression(dump.frames())) in
 .RProfile
 Message:  Error in pnorm(r, mean = parms[2], sd = parms[1]) : 
   object 'parms' not found
 Available environments had calls:
 1: optim(par = numeric(2), fn = myFxn, Y=data, other args, ..
 2: function (par) 
 3: fn(par, ...)
 4: ifelse(logical vector, phi(Y), other stuff within myFxn
 5: phi(Y)
 6: pnorm(r, mean = parms[2], sd = parms[1])
 
 Now, when using the debugger in environments 1 and 2, I can see the
 value of 'par' correctly.  I cannot access environment 4 as it just
 returns the original error message.  Trying to access environment 3
 gives the (to me) cryptic  'Error in get(.obj, envir =
 dump[[.selection]]) :  argument ... is missing, with no default' and
 returns to the top level without debugging.  
 
 I will try to explain to the best of my ability what I think is
 happening here.  Environments 2 and 3 are from the first lines of
 optim(), where it is building an internal function to evaluate the
 candidate parameter values.  When accessing environment 3, it seems like
 when it fills out the ... argument of fn(), it is passing
 phi=function(r) pnorm(r, mean=parms[2], sd=parms[1]) but upon trying to
 evaluate the variable 'parms', it cannot see it in the search path.
 When actually running the original call, 'parms' is apparently not
 evaluated yet, but is once the pnorm call is hit.  It appears the
 'parms' variable is being evaluated before the fn(par) is evaluated into
 myFxn(parms=par).   
 
 A point which is probably, but not certainly, irrelevant:  myFxn() has
 ... as its final argument, so as to pass tuning arguments to
 integrate().  The function being integrated contains phi(), as well as
 other stuff, of a dummy variable.  The calls in the debugging tree,
 however, are *not* those involving integrate().  
 
 It would probably be possible to include some
 substitute/eval/as.name/etc. constructions within the function myFxn, in
 order to avoid this problem, but as myFxn already involves numeric
 integrations whose integrand involves the optimized parameters
 themselves, computing on the language at each step of the optimization
 seems like a bad idea.  
 
 My question: is there a straightforward and efficient way of
 constructing this function and optimizing it with optim(), allowing for
 the argument phi to pass an arbitrary distribution function whose
 parameters are the global ones being optimized?  In particular, in the
 third environment of the debugger tree, is there a way to force the
 fn(par, ...)  myFxn(parms=par, ...) evaluation before the ... get
 evaluated?
 
 Thanks, John
 
 John  Szumiloski,  Ph.D.
 
 Senior Biometrician
 Biometrics Research
 WP53B-120
 Merck Research Laboratories
 P.O. Box 0004
 West Point, PA 19486-0004
 
 (215) 652-7346 (PH)
 (215) 993-1835 (FAX)
 
 
 #
   obligatory session info
 
   Windows XP 2002 sp3, customized by corporate IT
 
 version
_  
 platform   i386-pc-mingw32
 arch   i386   
 os mingw32
 system i386, mingw32  
 status Patched
 major  2  
 minor  9.2
 year   2009   
 month  09 
 day05 
 svn rev49600  
 language   R  
 version.string R version 2.9.2 Patched (2009-09-05 r49600)
 
 search()
  [1] .GlobalEnvpackage:geometry  package:datasets
 mylib1   mylib2  
  [6] package:VGAM  package:stats4package:Design
 package:Hmisc package:boot 
 [11] package:splines   package:MASS  package:nnet
 package:utils package:stats
 [16]