greta-dev / greta-dev/greta.distributions
some notes on interface design
- 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
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