Intro to probabilistic programming | by Fabiana Clemente | Towards Data Science

The idea behind Probabilistic programming to bring the inference algorithms and theory from statistics combined with formal semantics, compilers, and other tools from programming languages to build efficient inference evaluators for models and applications from Machine Learning. In other words, probabilistic programming is a tool for statistical modeling. The idea is to borrow lessons from the world of programming languages and apply them to the problems of designing and using statistical models.
Probabilistic programming is about doing statistics using the tools of computer science.
In the above figure you can see a typical computer science programming pipeline: Write a program, specify the values of its arguments then evaluate the program to produce an output. The right-hand side illustrates the approach taken to modeling in statistics: Start with the output, the observations or data Y, then specify an abstract generative model p(X,Y), often denoted mathematically, and finally use algebra and inference techniques to characterize the posterior distribution, p(X | Y ), of the unknown quantities in the model given the observed quantities. Whereas in Probabilistic programming: a programming language for model definitions and statistical inference algorithms for computing the conditional distribution of the program inputs that could have given rise to the observed program output.
Note: Probabilistic programming is not about writing software that behaves probabilistically.
To implement such Ensemble Architecture Tensorflow introduces Tensorflow-probability.
TensorFlow Probability is a library for probabilistic reasoning and statistical analysis in TensorFlow. As part of the TensorFlow ecosystem, TensorFlow Probability provides integration of probabilistic methods with deep networks, gradient-based inference via automatic differentiation, and scalability to large datasets and models via hardware acceleration (e.g., GPUs) and distributed computation.Probabilistic Machine Learning tools in TensorFlow-probability are structured in different levels. In this blog, we’ll discuss Statistical building blocks and Model Building using TensorFlow-probability.
Let’s start with importing necessary modules:
A tfp.distributions.Distribution is a class with two core methods: sample and log_prob. This class contains many distributions which can be seen by writing:
print_subclasses_from_module(tfp.distributions, tfp.distributions.Distribution)
Let’s see how to sample a Normal Distribution which is a good starter in stat101 using tf-probability:
# A standard normalnormal = tfd.Normal(loc=0., scale=1.) # mean=0, std=3samples = normal.sample(1000)sns.distplot(samples)plt.title("Samples from a standard Normal")plt.show()'''log of the probability density/mass function evaluated at the given sample value.'''print("log(PDF):",normal.log_prob(0.))
Now in order to calculate other statistical parameters like cumulative distribution function and multiple distributions we can still utilize tf-probabilities native classes.
# Define a single scalar Normal distribution.dist = tfd.Normal(loc=0., scale=3.)  # mean=0, std=3# Evaluate the cdf at 1, returning a scalar.dist.cdf(1.)# Define a batch of two scalar valued Normals.# The first has mean 1 and standard deviation 11, the second 2 and 22.dist = tfd.Normal(loc=[1, 2.], scale=[11, 22.])# Evaluate the pdf of the first distribution on 0, and the second on 1.5,# returning a length two tensor.dist.prob([0, 1.5])# Get 3 samples, returning a 3 x 2 tensor.dist.sample([3])
Using the above code you can calculate CDFs and Multiple Normal Distributions on-the-fly.While using statistical-tools in your project you might also require declaring Multivariate Distributions, tf-probability has got you covered here as well!
mvn = tfd.MultivariateNormalDiag(loc=[0., 0.], scale_diag = [1., 1.])print("Batch shape:", mvn.batch_shape)print("Event shape:", mvn.event_shape)samples = mvn.sample(1000)print("Samples shape:", samples.shape)g = sns.jointplot(samples[:, 0], samples[:, 1], kind='scatter')plt.show()
There are tons of distributions like these inside the tfp module, LogNormal, Logistic, LogitNormal Mixture, Multinomial, MultivariateNormalDiag, to name a few. Every distribution comes with a plethora of statistical inferences and functions.
Bijectors represent invertible, smooth functions. They can be used to transform distributions, preserving the ability to take samples and compute log_probs. They can be accessed from the tfp.bijectors module.
Each bijector implements at least 3 methods:
forward
inverse, and
(at least) one of forward_log_det_jacobian and inverse_log_det_jacobian.
With these ingredients, we can transform a distribution and still get samples and log probs from the result!
print_subclasses_from_module(tfp.bijectors, tfp.bijectors.Bijector)
Using the code snippet above we can list all the bijector functions available in tf-probability.
Now let’s see how to declare a NormalCDF using bijectors and calculate the log of the determinant of the Jacobian in forward propagation.
normal_cdf = tfp.bijectors.NormalCDF()xs = np.linspace(-4., 4., 200)plt.plot(xs, normal_cdf.forward(xs))plt.show()plt.plot(xs, normal_cdf.forward_log_det_jacobian(xs, event_ndims=0))plt.show()
Bijectors are mainly used for transforming Distributions. Here’s a quick example where transformation is applied:
# creates a Y=g(X)=exp(X) transformexp_bijector = tfp.bijectors.Exp()# declare a Normal Distribution and Transform itlog_normal = exp_bijector(tfd.Normal(0., .5))samples = log_normal.sample(1000)xs = np.linspace(1e-10, np.max(samples), 200)sns.distplot(samples, norm_hist=True, kde=False)plt.plot(xs, log_normal.prob(xs), c='k', alpha=.75)plt.show()
After running the above snippet you’ll see a transformed distribution(bins in blue) and probability density estimation plot (curve in black)
We successfully implemented the building blocks of statistical inference in Tensorflow-probability, now let’s see how we can use the same framework with tabular time-series data.
TensorFlow-Probability (TFP) features built-in support for fitting and forecasting using structural time series models. This support includes the Bayesian inference of the model. Because they’re built-in TensorFlow, these methods naturally take advantage of vectorized hardware (GPUs and TPUs), can efficiently process many time series in parallel, and can be integrated with deep neural networks.
Let’s solve a time-series problem using TensorFlow-probability:
Now let’s define a time-series problem of Co2 concentration over the years (sampled by month):
We’ll model this series with a local linear trend, plus a month-of-year seasonal effect, and fit the model using variational inference. This involves running an optimizer to minimize a variational loss function, the negative evidence lower bound (ELBO). This fits a set of approximate posterior distributions for the parameters (in practice we assume these to be independent Normals transformed to the support space of each parameter).
The tfp.sts forecasting methods require posterior samples as inputs, so we'll finish by drawing a set of samples from the variational posterior.
After running the above script you’ll see a plot like this:
Now let’s use the fitted model to construct a forecast. We just call tfp.sts.forecast, which returns a TensorFlow Distribution instance representing the predictive distribution over future timesteps.
In particular, the mean and stddev of the forecast distribution give us a prediction with marginal uncertainty at each timestep, and we can also draw samples of possible futures.
Lets now visualize the forecast of the Co2 Concentration.
We can observe here that the forecast made by our model turned out pretty good. It was able to capture seasonal changes and the overall trend of the time-series and able to predict the Co2 concentrations as it happened.
Let’s now see the Trend and Seasonality of the Co2 concentration:
As we already discussed how statistical inferences and tools can be easily implemented through TFP. In the above plot, we can identify trends and seasonality from the data just as efficiently as other core stats modules.
Congratulations! we just learned about the use and importance of Probabilistic-programming and discussed statistical tools in TensorFlow-probability. Not to mention we just solved a structured time-series problem using models from Tensorflow-probability!
Fabiana Clemente is Chief Data Officer at YData.
Making data available with privacy by design.
YData helps data science teams deliver ML models, simplifying data acquisition, so data scientists can focus their time on things that matter.