-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Development NumericalDerivatives #7
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good stuff @yuchuan2016! A few general comments here, and some more specific stuff below.
- Use Jacobian instead of Jacob in the documentation.
- Could you explain why you left off the check of whether the
func
argument is empty?
NumericalDerivatives/DESCRIPTION
Outdated
person("Matthew", "Gentzkow", email = "gentzkow@stanford.edu", role = c("aut", "cre")), | ||
person("Jesse", "Shapiro", email = "jesse_shapiro_1@brown.edu", role = c("aut")) | ||
) | ||
Description: Functions to calculate Jacob and Hessian matrix numerically. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe
Functions to numerically calculate Jacobian and Hessian matrices.
NumericalDerivatives/LICENSE
Outdated
@@ -0,0 +1,7 @@ | |||
Copyright (c) 2016 Matthew Gentzkow, Jesse M. Shapiro |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the copyright year.
NumericalDerivatives/R/numHess.R
Outdated
#' evaluated at given values of arguments. | ||
#' @param func The function on which Hessian matrix is calculated. | ||
#' @param x0 The values of arguments at which the Hessian matrix is evaluated. | ||
#' @param xTol The tolerance, where a small \code{xTol} corresponds to increased accuracy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try
where a smaller
NumericalDerivatives/R/numJacob.R
Outdated
#' evaluated at given values of arguments. | ||
#' @param func The function on which Jacob matrix is calculated. | ||
#' @param x0 The values of arguments at which the Jacob matrix is evaluated. | ||
#' @param xTol The tolerance, where a small \code{xTol} corresponds to increased accuracy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try
where a smaller
NumericalDerivatives/R/numJacob.R
Outdated
paramdim <- nparam | ||
} | ||
Jacobian <- matrix(0, noutput, nparam) | ||
for (j in 1:nparam) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to see a more "R-like" implementation, rather than a direct translation of the Matlab code. Later users will thank you. So, I wouldn't pre-instantiate the Jacobian and fill it in columnwise. Instead, I'd use sapply
or lapply
followed by do.call(cbind, <list_name>)
to create the final Jacobian matrix directly. (Be careful with the dimensions if you use sapply
and make sure to try it on single-row matrices)
|
||
expect_equal(hess1, truehess1, tolerance = 1e-3) | ||
expect_equal(hess2, truehess2, tolerance = 1e-3) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Carriage return
test_check("NumericalDerivatives") | ||
|
||
sprintf("Tests end at %s", Sys.time()) | ||
sink() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Carriage return
NumericalDerivatives/R/numHess.R
Outdated
|
||
for (i in 1:length(ind_rowvar)) { | ||
row <- ind_rowvar[i] | ||
for (j in 1:length(ind_colvar)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As for the Jacobian, I'd like to see a more R-style implementation using sapply
or lapply
with do.call(cbind, )
@arosenbe , thanks for the comments! I have implemented all sugegstions. Could you take a look? About the check of empty function argument, I'm not sure what's the parallel test in R. I don't know how to create an empty function. The closest I can think of is |
Thanks @yuchuan2016. I like the new I have one more comment: All arguments should be passed explicitly to |
@arosenbe , thanks! I don't quite understand your last comment. Could you explain it a little? Thanks a lot! |
Yeah, definitely @yuchuan2016! The inner A solution is to enumerate these dependencies explicitly as arguments in the # Good practice (pass y explicitly)
f_good <- function(x, y){
out <- c(x, y)
return(out)
}
out_good <- sapply(1:10, f_good, 0)
# Bad practice (check parent scope for implicit dependency on `y`)
f_bad <- function(x){
out <- c(x, y)
return(out)
}
y <- 0
out_bad <- sapply(1:10, f_bad)
# Check for equality
all.equal(out_good, out_bad) # True |
@arosenbe , thanks! Your explanation is very clear. I have updated the relevant part. |
Looking better @yuchuan2016! I especially love that the way that the argument positions line up. I do have another comment (sorry!) about your implementation of my suggestion above #7 (comment). It looks like you moved some steps that only need to be done once (e.g., function evaluation at base argument values) into the inner |
@arosenbe , very good point! Thanks. I have modified the function. |
Thanks @yuchuan2016! I'm happy with the format of the code now. I wonder if we don't want to have some error checking though. I was playing around with the code and was surprised by the result below. # Assumes you've already loaded numJacob
f <- function(x) x[1]^2 + x[2]^3 + x[3]^4
out <- NumericalDerivatives::numJacob(f, c(1, 2), .5)
print(out)
# [1] NA NA I think this occurs because f <- function(x) x[1]^2 + x[2]^3 + x[3]^4
out <- NumericalDerivatives::numJacob(f, c(1, 2, 3, 4), .5)
print(out)
# [1] 2.500 19.000 219.375 0.000 If the Matlab implementation was fine with these edge cases, then I think we can ignore them. Could you check and report back? |
@arosenbe , good point! I think the second case is fine. It just means the function does not depend on the fourth argument, so the derivative is 0. The MATLAB implementation also return a 1*4 matrix. For the first case, MATLAB function will raise an error "Index exceeds matrix dimensions". The difference comes from that in MARLAB, you have
While in R, you have
Can we raise an error if |
I think that's a great solution @yuchuan2016. |
@yuchuan2016 I was taking a closer look at
f <- function(x) x[1]^2 + x[2]^3 + x[3]^4
x0 <- c(1, 2, 3)
ind_colvar <- length(x0) + 1 # same for row
out <- NumericalDerivatives::numHess(f, x0, .5, ind_colvar = ind_colvar)
print(out)
warnings()
f <- function(x) x[1]^2 + x[2]^3 + x[3]^4
x0 <- c(1, 2, 3)
out_row <- NumericalDerivatives::numHess(f, x0, .5, ind_rowvar = 1)
is.matrix(out) # False
out_col <- NumericalDerivatives::numHess(f, x0, .5, ind_colvar = 1)
is.matrix(out) # True |
@arosenbe , thanks! I incorporate your comments. Could you take a look? |
Sorry for my delay in getting back to you @yuchuan2016! Your commit above does address my comments. However, I think it introduces a new bug in fun_vctr <- function(x){
out <- c(x[1]^2, x[2]^2, x[3]^2)
}
fun_sclr <- function(x){
out <- c(x[1]^2 + x[2]^2 + x[3]^2)
}
dim(numHess(fun_sclr, c(2, 3, 4), .5)) # Square
dim(numHess(fun_vctr, c(2, 3, 4), .5)) # Not square |
@arosenbe , thanks! The MATLAB version does not allow a vector
since we assign Do you think we want to allow |
Good thought going back to the MATLAB @yuchuan2016! I think we want to be as faithful to that implementation as possible. So let's raise an error if
Do you know if this same requirement is put on |
@arosenbe , actually Do you mean "a given scalar-valued function" in your previous comment? |
Yes I did @yuchuan2016. |
@arosenbe , thanks! I'm going to merge to master if no other issues arise. |
@arosenbe , could you kindly take a look at this? This package is simply a translation of this MATLAB library. It should be straightforward. Thanks!