This vignette showcases the basic functionality of distributions in
torch. Currently the distributions modules are considered ‘work in
progress’ and are still experimental features in the torch package. You
can see the progress in this link.

## Basic univariate distributions

Let’s start and create a new instance of a normal distribution:

```
n <- distr_normal(loc = 0, scale = 1)
n
```

We can draw samples from it with:

or, draw multiple samples:

We can evaluate the log probability of values:

```
n$log_prob(0)
log(dnorm(0)) # equivalent R code
```

or, evaluate multiple log probabilities:

## Multiple distributions

A distribution can take a tensor as it’s parameters:

```
b <- distr_bernoulli(probs = torch_tensor(c(0.25, 0.5, 0.75)))
b
```

This object represents 3 independent Bernoulli distributions, one for
each element of the tensor.

We can sample a single observation:

or, a batch of `n`

observations:

## Using distributions within models

The `log_prob`

method of distributions can be
differentiated, thus, distributions can be used to train models in
torch.

Let’s implement a Gaussian linear model, but first let’s simulate
some data

```
x <- torch_randn(100, 1)
y <- 2*x + 1 + torch_randn(100, 1)
```

and plot:

`plot(as.numeric(x), as.numeric(y))`

We can now define our model:

```
GaussianLinear <- nn_module(
initialize = function() {
# this linear predictor will estimate the mean of the normal distribution
self$linear <- nn_linear(1, 1)
# this parameter will hold the estimate of the variability
self$scale <- nn_parameter(torch_ones(1))
},
forward = function(x) {
# we estimate the mean
loc <- self$linear(x)
# return a normal distribution
distr_normal(loc, self$scale)
}
)
model <- GaussianLinear()
```

We can now train our model with:

```
opt <- optim_sgd(model$parameters, lr = 0.1)
for (i in 1:100) {
opt$zero_grad()
d <- model(x)
loss <- torch_mean(-d$log_prob(y))
loss$backward()
opt$step()
if (i %% 10 == 0)
cat("iter: ", i, " loss: ", loss$item(), "\n")
}
```

We can see the parameter estimates with:

and quickly compare with the `glm()`

function:

`summary(glm(as.numeric(y) ~ as.numeric(x)))`