# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python [conda env:py36]
#     language: python
#     name: conda-env-py36-py
# ---

# # Fitting to Gamma and Beta distributions
# -------
#
# This is a tutorial on fitting to non-normal data. Specifically where data might be heavy-tailed and defined on $(0,\infty)$, where the Gamma distribution would be a suitable choice and where the data is defined on $(0,1)$, where Beta is a suitable choice. Notice that the support for this distributions don't include $0$ and so care must be taken when training to data. The Pydra package will try and check input data before training to ensure they are reasonable values.
#

# %pylab inline
import sys
sys.path.append('../')

# ## Load pydra library

import importlib
import keras.backend as K
import pydra
import gen_data_utils as gd
import seaborn as sns
import plot_utils as pu
importlib.reload(pydra)
importlib.reload(pu)

import tensorflow as tf
import tensorflow.contrib.distributions as dist

# # Fitting to a gamma distribution
#
# We begin with a very simple model where the output is a single gamma distribution and a single input variable changes its mean and variance.

# +
beta = 1.
x = np.random.uniform(low=0,high=5,size=1000);
y = np.random.gamma(x,x/beta) + 1e-10;

plt.figure(figsize=(12,8));
plt.plot(x,y,'bo');
# -

# Reshape data for training

x = x.reshape(x.size,1)
y = y.reshape(y.size,1)

# Instantiate a pydra model. Notice that we can specify the output distributions using the output_distributions keyword. This provides flexibility for if a multi-dimensional output model has different distributions for different outputs.

model = pydra.Pydra(cluster_size=3,output_size=1,output_distributions=['Gamma'],
                    layers=3,dense_layer_size=64,print_summary=False)
history = model.fit(x, y, epochs=100, batch_size=100,
          verbose=1)

plt.figure(figsize=(12,8));
plt.plot(history.history['loss']);

# ## compare sample of predictions to original data

x_test = np.linspace(0,5,num=1000);
output = model.predict(x_test)

y_test = pydra.generate_mdn_sample_from_ouput(output, x_test.size,distribution='Gamma')

plt.figure(figsize=(8, 8))
plt.plot(x_test,y_test,'bo',alpha=0.1,label='mdn output')
plt.plot(x,y,'ro',alpha=0.3,label='data')
plt.legend();plt.xlabel('x');plt.ylabel('y');

model.predict_plot(x_test)
plt.plot(x,y,'ro',alpha=0.3,label='data')
plt.legend();plt.xlabel('x');plt.ylabel('y');
plt.title('Prediction compared to fitted data.');

# # Fit to beta distribution
#
# In this section we instead consider a beta distribution. Once again the model fitting to is straightforward and suitable for testing purposes. 

# +
beta = 1.0
x = np.random.uniform(low=0,high=10,size=1000);
#Need to add a small epsilon to keep data points away from zero.
eps = 1e-10
y = np.random.beta(x,20)+1e-10
y[y<eps] = eps
y[y>1-eps] = eps

x = x.reshape(x.size,1)
y = y.reshape(y.size,1)
# -

plt.figure(figsize=(12,8));
plt.plot(x,y,'bo');
plt.ylabel('output'); plt.xlabel('input');

model = pydra.Pydra(cluster_size=1,output_size=1,output_distributions=['Beta'],dense_layer_size=64)

history = model.fit(x, y, epochs=100, batch_size=100,
          verbose=1)

plt.figure(figsize=(12,8));
plt.plot(history.history['loss']);
plt.ylabel('loss');plt.xlabel('Epoch');

# ## Predict using fitted model

x_test = np.linspace(0,10,num=1000);
output = model.predict(x_test)

y_test = pydra.generate_mdn_sample_from_ouput(output, x_test.size,distribution='Beta')
plt.figure(figsize=(8, 8))
plt.plot(x_test,y_test,'bo',alpha=0.1,label='mdn output')
plt.plot(x,y,'ro',alpha=0.3,label='data')
plt.legend();plt.xlabel('x');plt.ylabel('y');

model.predict_plot(x_test)
plt.plot(x,y,'ro',alpha=0.3,label='data')
plt.legend();plt.xlabel('x');plt.ylabel('y');
plt.title('Predicition compared to data.');

StarcoderdataJupyterScriptsDedupFiltered