Basic usage

All Torchflow models are constructed as a combination of a bijection and a base distribution. Both the bijection and base distribution objects work on events (tensors) with a set event shape. A bijection and a distribution instance are are packaged together into a Flow object, creating a trainable torch module. The simplest way to create a normalizing flow is to import an existing architecture and wrap it with a Flow object. In the example below, we use the Real NVP architecture. We do not specify a base distribution, so the default standard Gaussian is chosen.

from torchflows.flows import Flow
from torchflows.architectures import RealNVP

event_shape = (10,)  # suppose our data are 10-dimensional vectors
flow = Flow(RealNVP(event_shape))

Normalizing flows learn the distributions of unlabeled data. We provide an example on how to train a flow for a dataset of 50-dimensional vectors.

import torch
from torchflows.flows import Flow
from torchflows.architectures import RealNVP

torch.manual_seed(0)

n_data = 1000
n_dim = 50

x = torch.randn(n_data, n_dim)  # Generate synthetic training data
flow = Flow(RealNVP(n_dim))  # Create the normalizing flow
flow.fit(x, show_progress=True)  # Fit the normalizing flow to training data

After fitting the flow, we can use it to sample new data and compute the log probability density of data points.

x_new = flow.sample(50)  # Sample 50 new data points
print(x_new.shape)  # (50, 3)

log_prob = flow.log_prob(x)  # Compute the data log probability
print(log_prob.shape)  # (100,)