import numpy as np import tensorflow as tf import tensorflow_probability as tfp import os import matplotlib.pyplot as plt plt.style.use('seaborn') tfd = tfp.distributions tfb = tfp.bijectors class Cubic(tfb.Bijector): def __init__(self, a, b, validate_args=False, name='Cubic'): self.a = tf.cast(a, tf.float32) self.b = tf.cast(b, tf.float32) if validate_args: assert tf.reduce_mean(tf.cast(tf.math.greater_equal(tf.abs(self.a), 1e-5), tf.float32)) == 1.0 assert tf.reduce_mean(tf.cast(tf.math.greater_equal(tf.abs(self.b), 1e-5), tf.float32)) == 1.0 super(Cubic, self).__init__( validate_args=validate_args, forward_min_event_ndims=0, name=name) def _forward(self, x): x = tf.cast(x, tf.float32) return tf.squeeze(tf.pow(self.a*x + self.b, 3)) def _inverse(self, y): y = tf.cast(y, tf.float32) return (tf.math.sign(y) * tf.pow(tf.abs(y), 1/3) - self.b) / self.a def _forward_log_det_jacobian(self, x): x = tf.cast(x, tf.float32) return tf.math.log(3. * tf.abs(self.a)) + 2. * tf.math.log(tf.abs(self.a*x + self.b)) def _inverse_log_det_jacobian(self, x): return -self._forward_log_det_jacobian(self._inverse(x))