SCM

Forum: developers

Monitor Forum | Start New Thread Start New Thread
RE: accessing the objective function [ Reply ]
By: Randall Pruim on 2016-03-02 15:47
[forum:42998]
Sorry for dropping out of the conversation recently. I've been dealing with some family medical issues and spent most of my time in the last week in hospitals. I remain interested and hope to resume participation in the conversation as I'm able.

RE: accessing the objective function [ Reply ]
By: Arne Henningsen on 2016-03-02 10:56
[forum:42997]
Very helpful examples and good ideas :-)

What's about:

library( "maxLik" )

maxLik2 <- function( ll, ... ) {
res <- maxLik( ll, ... )
dots <- list( ... )
res$ll <- function( par ) {
args <- formals( ll )
argList <- list()
argList[[1]] <- par
if( length( args ) >= 2 ) {
for( i in 2:length( args ) ) {
argList[[i]] <- dots[[ names( args )[i] ]]
}
}
names( argList ) <- names( args )
val <- do.call( ll, argList )
return( val )
}
return(res)
}

objectiveFn <- function(x) x$ll

cat("Case 1: no extra data\n")
fparab <- function(x) -x %*% x
r <- maxLik2(fparab, start=c(1,1))
print(coef(r))
f <- objectiveFn(r)
print(f(c(1,2)))

cat("Case 2: extra parameter\n")
fparab <- function(x, aa) -(x - aa) %*% (x - aa)
r <- maxLik2(fparab, start=c(1,1), aa=c(1,1))
print(coef(r))
f <- objectiveFn(r)
print(f(c(1,2)))
# print(f(c(1,2), c(3,3))) # no longer works

cat("Case 3: external data\n")
model <- function() {
fparab <- function(x) -(x - aa) %*% (x - aa)
aa <- c(1,1)
r <- maxLik2(fparab, start=c(1,1))
}
r <- model()
print(coef(r))
f <- objectiveFn(r)
print(f(c(1,2)))

cat("Case 4: extra parameter from inside of the function\n")
model <- function() {
fparab <- function(x, aa) -(x - aa) %*% (x - aa)
aa <- c(1,1)
r <- maxLik2(fparab, start=c(1,1), aa=aa)
}
r <- model()
print(coef(r))
f <- objectiveFn(r)
print(f(c(1,2))) # does not work
print(ls(envir=environment(f))) # "aa" "fparab" "r"
# print(f(1:2, aa=get("aa", envir=environment(f)))) # no longer works

RE: accessing the objective function [ Reply ]
By: Ott Toomet on 2016-02-18 02:38
[forum:42967]
So guys... To my surprise if I save the function, it also saves the corresponding environment. So the issues I was concerned about are gone. But I am not sure what to do with other problems...

Consider these 4 cases (and use the current svn version of maxLik):

cat("Case 1: no extra data\n")
fparab <- function(x) -x %*% x
r <- maxLik(fparab, start=c(1,1))
print(coef(r))
f <- objectiveFn(r)
print(f(c(1,2)))

cat("Case 2: extra parameter\n")
fparab <- function(x, aa) -(x - aa) %*% (x - aa)
r <- maxLik(fparab, start=c(1,1), aa=c(1,1))
print(coef(r))
f <- objectiveFn(r)
# print(f(c(1,2))) # does not work
print(f(c(1,2), c(3,3)))

cat("Case 3: external data\n")
model <- function() {
fparab <- function(x) -(x - aa) %*% (x - aa)
aa <- c(1,1)
r <- maxLik(fparab, start=c(1,1))
}
r <- model()
print(coef(r))
f <- objectiveFn(r)
print(f(c(1,2)))

cat("Case 4: extra parameter from inside of the function\n")
model <- function() {
fparab <- function(x, aa) -(x - aa) %*% (x - aa)
aa <- c(1,1)
r <- maxLik(fparab, start=c(1,1), aa=aa)
}
r <- model()
print(coef(r))
f <- objectiveFn(r)
# print(f(c(1,2))) # does not work
print(ls(envir=environment(f))) # "aa" "fparab" "r"
print(f(1:2, aa=get("aa", envir=environment(f)))) # this works...

Case 1 is trivial.

Case 2: should we save 'aa' somewhere? If yes, how should we call f() later? I don't consider it to be a big problem in this simple case...

Case 3: it just works (to my surprise :-)

Case 4: This is the most problematic case. 'aa' is there in the environment but it is unclear for the user what to do with it.

a) Should we put in place a wrapper, something like f1 <- function(param) { f(param, get("aa", ...)) }? Is this any less confusing?
b) Alternatively, should the author of 'model' provide the objective function (a similar wrapper) by hand?
c) maybe to return two extra objects: the objective function, and a list of extra parameters? The list is a bit hard to handle interactively (you need 'do.call') but in the plotting code it is rather straightforward.
d) any other ideas?

Ott

RE: accessing the objective function [ Reply ]
By: Arne Henningsen on 2016-02-16 11:53
[forum:42963]
1) Great :-)

2) It seems to me that this is not necessary:
https://r-forge.r-project.org/forum/message.php?msg_id=42961&group_id=254

4) I agree with logLikFn()

5) I think that logLik() should always return log likelihood values; so I prefer something like logLikFn(), logLikGrad(), and logLikHess() for naming the 'getter' functions.

accessing the objective function [ Reply ]
By: Ott Toomet on 2016-02-16 04:17
[forum:42955]
I implemented a 'first draft' of the objective function accessor.

1) It is called 'objectiveFn' and it is implemented for 'maxim' objects. (and by inheritance for maxLik objects too.) The name in the return list is 'objectiveFn' too but that will not be a part of the public API.
2) It does no attempt to play with extra parameters and environments. (Plan to work on that soon)
3) It has it's help page but the optimizers' pages do not mention it. Will add it there when you are happy with the name and implementation.
4) we may add another name for it for 'maxLik' objects. 'logLik' does not fit for general maximization objects anyway. In that case my favorite would be 'logLikFn' but I am open for options.
5) Squeezing 'Fn' into the name opens the possibility to introduce getters like 'objectiveGradient', or 'logLik(., type="Hessian") if you wish ;-) in case that will be needed at one point of time.

Passed all tests.
Comments?
Ott

Thanks to:
Vienna University of Economics and Business Powered By FusionForge