<jupyter_start><jupyter_text>Fitting a gauassian distribution using tensorflowThis lab showcases that tensorflow distributions can be paramatrized by variables. In particular, we will learn the mean and variance of a gaussian distribution based on data.*Special thanks to <NAME> for providing much of the underlying structure and code of this colab.*<jupyter_code>#@title Setup and imports.
!pip install dm-sonnet

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function


import tensorflow as tf
from tensorflow import distributions as tfd
import random
import numpy as np

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_style('ticks')


tf.reset_default_graph()<jupyter_output><empty_output><jupyter_text>Setting up the Target DistributionWe start by defining a distribution which we will try to match based on samples.<jupyter_code>data_dist = tfd.Normal(loc=-1., scale=0.1)
data_dist<jupyter_output><empty_output><jupyter_text>Let's visualize the pdf of this distribution.<jupyter_code># Points to evaluate the pdf on.
x_plot = tf.linspace(-2., 3., int(1e4))
# The pdf evaluated at these points.
data_dist_pdf = data_dist.prob(x_plot)<jupyter_output><empty_output><jupyter_text>So far we've been working with tensors. In order to plot the pdf, we get the values of the tensors by running them.<jupyter_code>with tf.Session() as sess:  
  x_vals, data_pdf_vals = sess.run([x_plot, data_dist_pdf])
plt.plot(x_vals, data_pdf_vals, 'g')
plt.show()<jupyter_output><empty_output><jupyter_text>Great. Let's take 1000 ssamples from this distribution: this will constitute the data we learn from.<jupyter_code>target_data = data_dist.sample(1000)
target_data<jupyter_output><empty_output><jupyter_text>Setting up the parametrized, learnable distributionWe start with a model that is initialized to be Gaussian with 0 mean and standard deviation of 1.<jupyter_code>mean = tf.Variable(tf.zeros(shape=(), dtype=tf.float32), name="mean")
std = tf.Variable(tf.ones(shape=(), dtype=tf.float32), name="std")
model = tfd.Normal(mean, std)<jupyter_output><empty_output><jupyter_text>We can compare the pdfs for the model and the target distributions.<jupyter_code>model_pdf = model.prob(x_plot)

init_op = tf.global_variables_initializer()
with tf.Session() as sess:
  sess.run(init_op)
  model_pdf_vals = sess.run(model_pdf)
  
plt.plot(x_vals, model_pdf_vals)
plt.plot(x_vals, data_pdf_vals, 'g')
plt.show()<jupyter_output><empty_output><jupyter_text>We can see these look very different. TrainingWe train the model to match the target distribution by minimizing the negative log probabilty of the observed data under the model. (This is similar to maximizing the probability of the data under the model.)<jupyter_code>optim = tf.train.AdamOptimizer(1e-3)
train_op = optim.minimize(-tf.reduce_mean(model.log_prob(target_data)))
init_op = tf.global_variables_initializer()<jupyter_output><empty_output><jupyter_text>While we train, we periodically visualize how the model changes.<jupyter_code>with tf.Session() as sess:
  sess.run(init_op)
  for _ in range(5):
    for _ in xrange(175):
      sess.run(train_op)

    model_pdf_vals = sess.run(model_pdf)

    plt.plot(x_vals, model_pdf_vals)
    plt.plot(x_vals, data_pdf_vals, 'g')
    plt.show()<jupyter_output><empty_output><jupyter_text>SuccessWe can see that in less than 1000 steps the model learns to nearly perfectly match the target distribution.<jupyter_code><jupyter_output><empty_output>