Conversation
|
Found while sweeping the library(greta)
#>
#> Attaching package: 'greta'
#> The following objects are masked from 'package:stats':
#>
#> binomial, cov2cor, poisson
#> The following objects are masked from 'package:base':
#>
#> %*%, %o%, apply, backsolve, beta, chol2inv, colMeans, colSums,
#> diag, eigen, forwardsolve, gamma, identity, outer, rowMeans,
#> rowSums, sweep, tapply
x <- normal(0, 1)
#> ℹ Initialising python and checking dependencies, this may take a moment.
#> ✔ Initialising python and checking dependencies ... done!
#>
m_on <- model(x, compile = TRUE)
m_off <- model(x, compile = FALSE)It is stored on the dag and never read again. c(on = m_on$dag$compile, off = m_off$dag$compile)
#> on off
#> TRUE FALSEand that is the only thing that ever happens to it. Nothing reads it: ## $ grep -rn '\$compile' R/
## R/dag_class.R:39: self$compile <- compileWhat I expect
What happens insteadNeither does anything. The argument has been inert since Wiring it up is two lines
## self$tf_log_prob_function <- tensorflow::tf_function(
## f = self$generate_log_prob_function(),
## jit_compile = self$compile
## )With that applied, Why they breakThat needs the patch to reproduce, so here is the underlying operation library(tensorflow)
tfp <- reticulate::import("tensorflow_probability")
grad_through <- function(bijector, batch_shape, jit) {
f <- tf_function(
function(v) {
with(tf$GradientTape() %as% tape, {
tape$watch(v)
loss <- tf$reduce_sum(bijector$forward(v))
})
tape$gradient(loss, v)
},
input_signature = list(
tf$TensorSpec(shape = batch_shape, dtype = tf$float32)
),
jit_compile = jit
)
x <- tf$constant(matrix(c(0.5, 0.3, 0.8), nrow = 1), dtype = tf$float32)
tryCatch(
{
invisible(f(x))
cat("OK\n")
},
error = function(e) {
# first line, plus the node that failed - the rest is a stack trace of
# local paths
lines <- strsplit(conditionMessage(e), "\n")[[1]]
cat(lines[1], "\n")
cat(grep("node ", lines, value = TRUE)[1], "\n")
}
)
}With a static shape, XLA is perfectly happy: grad_through(tfp$bijectors$FillScaleTriL(), list(1L, 3L), jit = TRUE)
#> OKWith the dynamic batch dimension greta actually uses, it is not: grad_through(tfp$bijectors$FillScaleTriL(), list(NULL, 3L), jit = TRUE)
#> tensorflow.python.framework.errors_impl.InvalidArgumentError: Reading input as constant from a dynamic tensor is not yet supported. Xla shape: s32[<=3]
#> [[{{node gradient_tape/fill_scale_tril/forward/transform_diagonal/forward/zeros}}]]Same for the other cholesky bijector: grad_through(tfp$bijectors$CorrelationCholesky(), list(NULL, 3L), jit = TRUE)
#> tensorflow.python.framework.errors_impl.InvalidArgumentError: Reading input as constant from a dynamic tensor is not yet supported. Xla shape: s32[<=3]
#> [[{{node gradient_tape/correlation_cholesky/forward/zeros}}]]And both are fine with the dynamic shape as long as XLA is off, which is grad_through(tfp$bijectors$FillScaleTriL(), list(NULL, 3L), jit = FALSE)
#> OKSo: the gradients of Why this is a problem, and what wiring it buysToday a documented argument silently does nothing, and a user who sets Measured in That number needed 50 iterations to see. At 10 the same comparison gave 27 ms But Three options
Also worth fixing whichever way this goes: A test for this## test_that("compile = TRUE actually compiles with XLA", {
## m <- model(normal(0, 1), compile = TRUE)
## expect_true(m$dag$tf_log_prob_function$`_jit_compile`)
## }) |
The
compilearg ofmodel()didn't actually do anything, so exploring if this triggers warnings.