razimbres
razimbres

Reputation: 5015

Tensorflow Probability returns unstable Predictions

I'm using a Tensorflow Probability model. Of course is a probabilistic outcome, and the derivative of error does not go to zero (otherwise the model would be deterministic). The prediction is not stable, because we have a range in the derivative of loss, let's say, in a convex optimization, from 1.2 to 0.2 as an example.

This interval generates a different prediction each time the model is trained. Sometimes I get an excellent fit (red=real, blue lines=predicted +2 std deviation and -2 std deviation):

Good fit

Sometimes not, with same hyper-parameters:

Bad fit

Sometimes mirrored:

Mirrored

For business purposes, this is quite problematic, given that it is expected that a prediction presents a stable output.

Here is the code:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
import tensorflow_probability as tfp
np.random.seed(42)
dataframe = pd.read_csv('Apple_Data_300.csv').ix[0:800,:]
dataframe.head()

plt.plot(range(0,dataframe.shape[0]),dataframe.iloc[:,1])

x1=np.array(dataframe.iloc[:,1]+np.random.randn(dataframe.shape[0])).astype(np.float32).reshape(-1,1)

y=np.array(dataframe.iloc[:,1]).T.astype(np.float32).reshape(-1,1)

tfd = tfp.distributions

model = tf.keras.Sequential([
  tf.keras.layers.Dense(1,kernel_initializer='glorot_uniform'),
  tfp.layers.DistributionLambda(lambda t: tfd.Normal(loc=t, scale=1)),
  tfp.layers.DistributionLambda(lambda t: tfd.Normal(loc=t, scale=1)),
  tfp.layers.DistributionLambda(lambda t: tfd.Normal(loc=t, scale=1))
])
negloglik = lambda x, rv_x: -rv_x.log_prob(x)

model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.0001), loss=negloglik)

model.fit(x1,y, epochs=500, verbose=True)

yhat = model(x1)
mean = yhat.mean()

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    mm = sess.run(mean)    
    mean = yhat.mean()
    stddev = yhat.stddev()
    mean_plus_2_std = sess.run(mean - 2. * stddev)
    mean_minus_2_std = sess.run(mean + 2. * stddev)


plt.figure(figsize=(8,6))
plt.plot(y,color='red',linewidth=1)
#plt.plot(mm)
plt.plot(mean_minus_2_std,color='blue',linewidth=1)
plt.plot(mean_plus_2_std,color='blue',linewidth=1)

Loss:

Epoch 498/500
801/801 [==============================] - 0s 32us/sample - loss: 2.4169
Epoch 499/500
801/801 [==============================] - 0s 30us/sample - loss: 2.4078
Epoch 500/500
801/801 [==============================] - 0s 31us/sample - loss: 2.3944

Is there a way to control the prediction output for a probabilistic model? The loss stops at 1.42, even decreasing learning rate and increasing training epochs. What am I missing here ?

WORKING CODE AFTER ANSWER:

init = tf.global_variables_initializer()

with tf.Session() as sess:

    model = tf.keras.Sequential([
      tf.keras.layers.Dense(1,kernel_initializer='glorot_uniform'),
      tfp.layers.DistributionLambda(lambda t: tfd.Normal(loc=t, scale=1))
    ])
    negloglik = lambda x, rv_x: -rv_x.log_prob(x)

    model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.0001), loss=negloglik)

    model.fit(x1,y, epochs=500, verbose=True, batch_size=16)

    yhat = model(x1)
    mean = yhat.mean()

    sess.run(init)
    mm = sess.run(mean)    
    mean = yhat.mean()
    stddev = yhat.stddev()
    mean_plus_2_std = sess.run(mean - 3. * stddev)
    mean_minus_2_std = sess.run(mean + 3. * stddev)

Upvotes: 2

Views: 766

Answers (1)

Scott Skiles
Scott Skiles

Reputation: 3847

Are you running tf.global_variables_initializer too late?

I found this in the answer of Understanding tf.global_variables_initializer:

Variable initializers must be run explicitly before other ops in your model can be run. The easiest way to do that is to add an op that runs all the variable initializers, and run that op before using the model.

Upvotes: 3

Related Questions