greta-dev / greta-dev/greta.distributions

some notes on interface design

Open
#4 3 comments 0 reactions 0 assignees View on GitHub
Constructor Tools
Dominant language
R
Stars
1
Forks
2
PR merge metrics
No merged PRs in 30d

Description

If the distribution is in tensorflow probability you (generally) need only two methods:
1. initialize
- lists the arguments, as well as dimension and truncation (if applicable?)
- e.g., normal has mu, sd, dim, and truncation
2. tf_distrib
- this calls the tensorflow distribution from tensorflow probability

BUT if you don't have the distribution in TFP or it isn't quite right, you need to add the following:
* log_prob
* sample

And you might need to add some extra functions to check things.

I can imagine A few kinds of interface

The first interface will take in arguments, and then it writes the code for you:

So writing

```r
write_greta_distribution(
name = "logistic",
arguments = c("location", "scale"),
tf_distrib_name = "Logistic",
truncation = c(-Inf, Inf), # this could be the default
tf_distrib_args = list(
"loc" = "location",
"scale" = "scale"
)
)
```

Would then generate the code:

```r
logistic_distribution <- R6Class(
"logistic_distribution",
inherit = distribution_node,
public = list(
initialize = function(location, scale, dim, truncation) {
location <- as.greta_array(location)
scale <- as.greta_array(scale)

# add the nodes as parents and parameters
dim <- check_dims(location, scale, target_dim = dim)
super$initialize("logistic", dim, truncation)
self$add_parameter(location, "location")
self$add_parameter(scale, "scale")
},
tf_distrib = function(parameters, dag) {
tfp$distributions$Logistic(
loc = parameters$location,
scale = parameters$scale
)
}
)
)

logistic <- function(location, scale, dim = NULL, truncation = c(-Inf, Inf)) {
distrib("logistic", location, scale, dim, truncation)
}
```

Could potentially use multiple assign from zeallot - `%<-%` to help do something like:

```r
c(quote(arguments)) %<-% lapply(quote(arguments), as.greta_array)
```

The second approach could look something like this:

```r
logistic <- create_greta_distribution(
name = "logistic",
arguments = c("location", "scale"),
tf_distrib_name = "Logistic",
truncation = c(-Inf, Inf), # this could be the default
tf_distrib_args = list(
"loc" = "location",
"scale" = "scale"
)
)
```

A third approach could involve some R6 generation methods? I'm not sure if this is possible/feasible. This is inspired by `distributional` and `dist6`

```r
logistic <- greta_distribution$new(
name = "logistic",
# this will check if this name exists in tfp
# if not, then you'll have to provide additional constructor details
tfp_name = "Logistic"
)

# rather neatly, it will know the name of the arguments from tfp
# ... somehow
# and you then need to specify the names you'd like on the right hand side
logistic$tf$args(
loc = location,
scale = scale
)

# to add new log_prob, cdf, etc, you do:

logistic$tf$log_prob$new(
f = function(x)
)

logistic$tf$cdf$new(
...
)

logistic$tf$sample$new(
...
)
```

Contributor guide

Open the contributing guide

Research direction

Start by comparing the proposed initialize and tf_distrib methods with the existing distribution interface, then review the alternatives named here: write_greta_distribution(), create_greta_distribution(), and greta_distribution$new(). The issue does not choose an approach or define tests, scope, or completion criteria; resolve those design questions before implementation.

Written by the indexing model from the issue text.

Assessment

Tech stack
r, tensorflow
Domain
backend-api-design, machine-learning
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.