Module WUT.SVI
Expand source code
import numpy as np
import tensorflow as tf
import types
from tensorflow.python.keras.layers.ops import core as core_ops
import mdn
from tensorflow.compat.v1.keras import layers
from tensorflow.python.keras import activations
from tensorflow_probability import distributions as tfd
from keras import backend as K
from keras import activations, initializers
import tensorflow_probability as tfp
class SVI():
def __init__(self, Model, kl_weight=1., prior_sigma_1=1.5, prior_sigma_2=0.1, prior_pi=0.5, SVI_Layers=[tf.keras.layers.Dense], normalize = True, task = 'regression', one_hot = True, **kwargs):
"""SVI Initializer. Turns a neural network into an SVI network.
Args:
Model: Input Keras Model.
kl_weight: Weight Parameter for KL Divergence.
prior_sigma_1: First sigma for prior on weights
prior_sigma_2: Second sigma for prior on weights
prior_pi: First pi for prior on weights, second is 1 - prior_pi
SVI_Layers: Layer types for which SVI can be applied-- the defaults, dense are garunteed safe, add others at your own risk
normalize: Whether to normalize input and output values before using-- if you get nans, trying switching! Regression only
task: regression or classification
one_hot: are the input targets in one hot format. True if they inputs are one hot. Classification only.
Returns:
Nothing lol
"""
self.model = Model()
self.SVI_Layers = SVI_Layers
self.one_hot = one_hot
self.use_normalization = normalize
self.task = task
self.train_std = 0
self.xmean, self.xstd = 0., 1.
self.ymean, self.ystd = 0., 1.
if task == 'regression':
last_layer = self.model.layers[-1]
self.dim = last_layer.units
last_layer.units = 2 * last_layer.units
if task == 'classification':
self.dim = self.model.layers[-1].units
def compute_output_shape(self, input_shape):
return input_shape[0], self.units
def kl_loss(self, w, mu, sigma):
variational_dist = tfp.distributions.Normal(mu, sigma)
return self.kl_weight * K.sum(variational_dist.log_prob(w) - self.log_prior_prob(w))
def build(self, input_shape):
self.kernel_mu = self.add_weight(name='kernel_mu',
shape=(input_shape[1], self.units),
initializer=initializers.RandomNormal(stddev=self.init_sigma),
trainable=True)
self.bias_mu = self.add_weight(name='bias_mu',
shape=(self.units,),
initializer=initializers.RandomNormal(stddev=self.init_sigma),
trainable=True)
self.kernel_rho = self.add_weight(name='kernel_rho',
shape=(input_shape[1], self.units),
initializer=initializers.Constant(0.0),
trainable=True)
self.bias_rho = self.add_weight(name='bias_rho',
shape=(self.units,),
initializer=initializers.Constant(0.0),
trainable=True)
self._trainable_weights = [self.kernel_mu, self.bias_mu, self.kernel_rho, self.bias_rho]#
def call(self, inputs, **kwargs):
if self.built == False:
self.build(inputs.shape)
self.built = True
kernel_sigma = tf.math.softplus(self.kernel_rho)
kernel = self.kernel_mu + kernel_sigma * tf.random.normal(self.kernel_mu.shape)
bias_sigma = tf.math.softplus(self.bias_rho)
bias = self.bias_mu + bias_sigma * tf.random.normal(self.bias_mu.shape)
self.add_loss(self.kl_loss(kernel, self.kernel_mu, kernel_sigma) +
self.kl_loss(bias, self.bias_mu, bias_sigma))
return self.activation(K.dot(inputs, kernel) + bias)
def log_prior_prob(self, w):
comp_1_dist = tfp.distributions.Normal(0.0, self.prior_sigma_1)
comp_2_dist = tfp.distributions.Normal(0.0, self.prior_sigma_2)
return K.log(self.prior_pi_1 * comp_1_dist.prob(w) +
self.prior_pi_2 * comp_2_dist.prob(w))
for layer in self.model.layers:
if layer.__class__ in SVI_Layers:
layer.kl_weight = kl_weight
layer.prior_sigma_1 = prior_sigma_1
layer.prior_sigma_2 = prior_sigma_2
layer.prior_pi_1 = prior_pi
layer.prior_pi_2 = 1.0 - prior_pi
layer.init_sigma = np.sqrt(layer.prior_pi_1 * layer.prior_sigma_1 ** 2 +
layer.prior_pi_2 * layer.prior_sigma_2 ** 2)
layer.compute_output_shape = types.MethodType(compute_output_shape, layer)
layer.build = types.MethodType(build, layer)
layer.call = types.MethodType(call, layer)
layer.kl_loss = types.MethodType(kl_loss, layer)
layer.log_prior_prob = types.MethodType(log_prior_prob, layer)
layer.built = False
def fit_normalize(self, X):
"""fit_normalize. helper function to normalize input values and generate future normalizations
Returns:
normalized X, mean, std
"""
mean = tf.math.reduce_mean(X, axis=0, keepdims=True)
std = tf.math.reduce_std(X, axis=0, keepdims=True)
return (X - mean)/std, mean, std
def unnormalize(self, Y):
"""unnormalize. helper function to unnormalize output values
Returns:
unnormalized Y
"""
return (Y*self.ystd) + self.ymean
def Y_normalize(self, Y):
"""Y_normalize. helper function to normalize output values in training set
Returns:
normalized Y
"""
return (Y - self.ymean)/self.ystd
def std_unnormalize(self, Y):
"""unnormalize. helper function to unnormalize output values by varying std-- used for std predictions.
Returns:
unnormalized Y
"""
return Y * self.ystd
def normalize(self, X):
"""normalize. helper function to normalize input values
Returns:
normalized X
"""
return (X - self.xmean)/self.xstd
def compile(self, *args, loss=None, **kwargs):
"""compile. Literally use this as you'd use the normal compile, but don't use your own loss functions, unless your really deep in this. Let the default one go
Args:
loss: if you really wanna make your own loss function
Returns:
Nothing lol
"""
if loss is None:
loss = self.neg_log_likelihood
else:
print("Warning: you might be in for a rocky ride here, you specified your own loss function. If you don't know what your doing, don't do this! Loss functions have to be in the style of neg_log_likelihood in the source code/")
kwargs['loss'] = loss
self.model.compile(*args, **kwargs)
def elu_plus_one_plus_epsilon(self, x):
"""ELU activation with a very small addition to help prevent
NaN in loss."""
return tf.keras.backend.elu(x) + 1 + .00001
def neg_log_likelihood(self, y_obs, y_pred):
if self.task == 'regression':
y_means, y_stds = tf.split(y_pred, [self.dim, self.dim], axis = 1)
if self.train_std == 1:
pass
y_stds = (y_stds)**2. + .1
else:
y_stds = tf.constant(1.0)
dist = tfp.distributions.Normal(loc=y_means, scale=y_stds )
return K.sum(-dist.log_prob(tf.dtypes.cast(y_obs, tf.float32)))
if self.task == 'classification':
y_pred = (tf.reshape(y_pred, [-1, self.dim]))
y_obs = tf.reshape(y_obs, [-1, self.dim, 1])
dist = tfp.distributions.Categorical(logits = y_pred)
return K.sum(-dist.log_prob(tf.dtypes.cast(y_obs, tf.int32)))
def evaluate(self, *args, **kwargs):
"""evaluate. Literally use this as you'd use the normal keras evaluate.
Returns:
The model's score, evaluated on whatever inputs you just fed it.
"""
if self.use_normalization is True:
args = list(args)
args[0] = self.normalize(args[0])
if self.task == 'regression':
args[1] = self.Y_normalize(args[1])
args = tuple(args)
if (self.one_hot == False) and self.task == 'classification':
args = list(args)
data_amnt = args[1].shape[0]
args[1] = tf.one_hot(args[1] , tf.dtypes.cast(tf.reduce_max(args[1] ) + 1, tf.int32))
args[1] = tf.reshape(args[1], [data_amnt, -1])
args = tuple(args)
return self.model.evaluate( *args, **kwargs)
def fit(self, *args, **kwargs):
"""fit. Literally use this as you'd use the normal keras fit.
Returns:
Nothing lol.
"""
if self.use_normalization is True:
args = list(args)
args[0], self.xmean, self.xstd = self.fit_normalize(args[0])
if self.task == 'regression':
args[1], self.ymean, self.ystd = self.fit_normalize(args[1])
args = tuple(args)
if 'batch_size' not in kwargs.keys():
kwargs['batch_size'] = 42
for layer in self.model.layers:
if layer.__class__ in self.SVI_Layers:
layer.kl_weight = kwargs['batch_size'] * layer.kl_weight/args[0].shape[0]
if (self.one_hot == False) and self.task == 'classification':
args = list(args)
data_amnt = args[1].shape[0]
args[1] = tf.one_hot(args[1] , tf.dtypes.cast(tf.reduce_max(args[1] ) + 1, tf.int32))
args[1] = tf.reshape(args[1], [data_amnt, -1])
args = tuple(args)
if 'validation_data' in kwargs.keys():
kwargs['validation_data'] = list(kwargs['validation_data'])
data_amnt = kwargs['validation_data'][1].shape[0]
args[1] = tf.one_hot(kwargs['validation_data'][1] , tf.dtypes.cast(tf.reduce_max(kwargs['validation_data'][1] ) + 1, tf.int32))
args[1] = tf.reshape(kwargs['validation_data'][1], [data_amnt, -1])
args = tuple(args)
self.model.fit(*args, **kwargs)
if self.task == 'regression':
self.train_std = 1
self.model.fit(*args, **kwargs)
self.train_std = 0
for layer in self.model.layers:
if layer.__class__ in self.SVI_Layers:
layer.kl_weight = layer.kl_weight*args[0].shape[0]/kwargs['batch_size']
def predict(self, *args, return_std = True, **kwargs):
"""predict. Literally use this as you'd use the normal keras predict.
Returns:
a probability distribution over outputs, for each input.
"""
if self.use_normalization is True:
args = list(args)
args[0] = self.normalize(args[0])
args = tuple(args)
y_pred = self.model.predict(*args, **kwargs)
if self.task == 'regression':
y_means, y_stds = tf.split(y_pred, [self.dim, self.dim], axis = 1)
if self.use_normalization is True:
y_means = self.unnormalize(y_means)
y_stds = self.std_unnormalize(tf.exp(y_stds))
dist = tfp.distributions.Normal(loc=y_means, scale=y_stds)
return dist
if self.task == 'classification':
y_pred = tf.reshape(y_pred, [-1, self.dim])
dist = tfp.distributions.Categorical(logits= y_pred)
return dist
Classes
class SVI (Model, kl_weight=1.0, prior_sigma_1=1.5, prior_sigma_2=0.1, prior_pi=0.5, SVI_Layers=[<class 'tensorflow.python.keras.layers.core.Dense'>], normalize=True, task='regression', one_hot=True, **kwargs)-
SVI Initializer. Turns a neural network into an SVI network.
Args
Model- Input Keras Model.
kl_weight- Weight Parameter for KL Divergence.
prior_sigma_1- First sigma for prior on weights
prior_sigma_2- Second sigma for prior on weights
prior_pi- First pi for prior on weights, second is 1 - prior_pi
SVI_Layers- Layer types for which SVI can be applied– the defaults, dense are garunteed safe, add others at your own risk
normalize- Whether to normalize input and output values before using– if you get nans, trying switching! Regression only
task- regression or classification
one_hot- are the input targets in one hot format. True if they inputs are one hot. Classification only.
Returns
Nothing lol
Expand source code
class SVI(): def __init__(self, Model, kl_weight=1., prior_sigma_1=1.5, prior_sigma_2=0.1, prior_pi=0.5, SVI_Layers=[tf.keras.layers.Dense], normalize = True, task = 'regression', one_hot = True, **kwargs): """SVI Initializer. Turns a neural network into an SVI network. Args: Model: Input Keras Model. kl_weight: Weight Parameter for KL Divergence. prior_sigma_1: First sigma for prior on weights prior_sigma_2: Second sigma for prior on weights prior_pi: First pi for prior on weights, second is 1 - prior_pi SVI_Layers: Layer types for which SVI can be applied-- the defaults, dense are garunteed safe, add others at your own risk normalize: Whether to normalize input and output values before using-- if you get nans, trying switching! Regression only task: regression or classification one_hot: are the input targets in one hot format. True if they inputs are one hot. Classification only. Returns: Nothing lol """ self.model = Model() self.SVI_Layers = SVI_Layers self.one_hot = one_hot self.use_normalization = normalize self.task = task self.train_std = 0 self.xmean, self.xstd = 0., 1. self.ymean, self.ystd = 0., 1. if task == 'regression': last_layer = self.model.layers[-1] self.dim = last_layer.units last_layer.units = 2 * last_layer.units if task == 'classification': self.dim = self.model.layers[-1].units def compute_output_shape(self, input_shape): return input_shape[0], self.units def kl_loss(self, w, mu, sigma): variational_dist = tfp.distributions.Normal(mu, sigma) return self.kl_weight * K.sum(variational_dist.log_prob(w) - self.log_prior_prob(w)) def build(self, input_shape): self.kernel_mu = self.add_weight(name='kernel_mu', shape=(input_shape[1], self.units), initializer=initializers.RandomNormal(stddev=self.init_sigma), trainable=True) self.bias_mu = self.add_weight(name='bias_mu', shape=(self.units,), initializer=initializers.RandomNormal(stddev=self.init_sigma), trainable=True) self.kernel_rho = self.add_weight(name='kernel_rho', shape=(input_shape[1], self.units), initializer=initializers.Constant(0.0), trainable=True) self.bias_rho = self.add_weight(name='bias_rho', shape=(self.units,), initializer=initializers.Constant(0.0), trainable=True) self._trainable_weights = [self.kernel_mu, self.bias_mu, self.kernel_rho, self.bias_rho]# def call(self, inputs, **kwargs): if self.built == False: self.build(inputs.shape) self.built = True kernel_sigma = tf.math.softplus(self.kernel_rho) kernel = self.kernel_mu + kernel_sigma * tf.random.normal(self.kernel_mu.shape) bias_sigma = tf.math.softplus(self.bias_rho) bias = self.bias_mu + bias_sigma * tf.random.normal(self.bias_mu.shape) self.add_loss(self.kl_loss(kernel, self.kernel_mu, kernel_sigma) + self.kl_loss(bias, self.bias_mu, bias_sigma)) return self.activation(K.dot(inputs, kernel) + bias) def log_prior_prob(self, w): comp_1_dist = tfp.distributions.Normal(0.0, self.prior_sigma_1) comp_2_dist = tfp.distributions.Normal(0.0, self.prior_sigma_2) return K.log(self.prior_pi_1 * comp_1_dist.prob(w) + self.prior_pi_2 * comp_2_dist.prob(w)) for layer in self.model.layers: if layer.__class__ in SVI_Layers: layer.kl_weight = kl_weight layer.prior_sigma_1 = prior_sigma_1 layer.prior_sigma_2 = prior_sigma_2 layer.prior_pi_1 = prior_pi layer.prior_pi_2 = 1.0 - prior_pi layer.init_sigma = np.sqrt(layer.prior_pi_1 * layer.prior_sigma_1 ** 2 + layer.prior_pi_2 * layer.prior_sigma_2 ** 2) layer.compute_output_shape = types.MethodType(compute_output_shape, layer) layer.build = types.MethodType(build, layer) layer.call = types.MethodType(call, layer) layer.kl_loss = types.MethodType(kl_loss, layer) layer.log_prior_prob = types.MethodType(log_prior_prob, layer) layer.built = False def fit_normalize(self, X): """fit_normalize. helper function to normalize input values and generate future normalizations Returns: normalized X, mean, std """ mean = tf.math.reduce_mean(X, axis=0, keepdims=True) std = tf.math.reduce_std(X, axis=0, keepdims=True) return (X - mean)/std, mean, std def unnormalize(self, Y): """unnormalize. helper function to unnormalize output values Returns: unnormalized Y """ return (Y*self.ystd) + self.ymean def Y_normalize(self, Y): """Y_normalize. helper function to normalize output values in training set Returns: normalized Y """ return (Y - self.ymean)/self.ystd def std_unnormalize(self, Y): """unnormalize. helper function to unnormalize output values by varying std-- used for std predictions. Returns: unnormalized Y """ return Y * self.ystd def normalize(self, X): """normalize. helper function to normalize input values Returns: normalized X """ return (X - self.xmean)/self.xstd def compile(self, *args, loss=None, **kwargs): """compile. Literally use this as you'd use the normal compile, but don't use your own loss functions, unless your really deep in this. Let the default one go Args: loss: if you really wanna make your own loss function Returns: Nothing lol """ if loss is None: loss = self.neg_log_likelihood else: print("Warning: you might be in for a rocky ride here, you specified your own loss function. If you don't know what your doing, don't do this! Loss functions have to be in the style of neg_log_likelihood in the source code/") kwargs['loss'] = loss self.model.compile(*args, **kwargs) def elu_plus_one_plus_epsilon(self, x): """ELU activation with a very small addition to help prevent NaN in loss.""" return tf.keras.backend.elu(x) + 1 + .00001 def neg_log_likelihood(self, y_obs, y_pred): if self.task == 'regression': y_means, y_stds = tf.split(y_pred, [self.dim, self.dim], axis = 1) if self.train_std == 1: pass y_stds = (y_stds)**2. + .1 else: y_stds = tf.constant(1.0) dist = tfp.distributions.Normal(loc=y_means, scale=y_stds ) return K.sum(-dist.log_prob(tf.dtypes.cast(y_obs, tf.float32))) if self.task == 'classification': y_pred = (tf.reshape(y_pred, [-1, self.dim])) y_obs = tf.reshape(y_obs, [-1, self.dim, 1]) dist = tfp.distributions.Categorical(logits = y_pred) return K.sum(-dist.log_prob(tf.dtypes.cast(y_obs, tf.int32))) def evaluate(self, *args, **kwargs): """evaluate. Literally use this as you'd use the normal keras evaluate. Returns: The model's score, evaluated on whatever inputs you just fed it. """ if self.use_normalization is True: args = list(args) args[0] = self.normalize(args[0]) if self.task == 'regression': args[1] = self.Y_normalize(args[1]) args = tuple(args) if (self.one_hot == False) and self.task == 'classification': args = list(args) data_amnt = args[1].shape[0] args[1] = tf.one_hot(args[1] , tf.dtypes.cast(tf.reduce_max(args[1] ) + 1, tf.int32)) args[1] = tf.reshape(args[1], [data_amnt, -1]) args = tuple(args) return self.model.evaluate( *args, **kwargs) def fit(self, *args, **kwargs): """fit. Literally use this as you'd use the normal keras fit. Returns: Nothing lol. """ if self.use_normalization is True: args = list(args) args[0], self.xmean, self.xstd = self.fit_normalize(args[0]) if self.task == 'regression': args[1], self.ymean, self.ystd = self.fit_normalize(args[1]) args = tuple(args) if 'batch_size' not in kwargs.keys(): kwargs['batch_size'] = 42 for layer in self.model.layers: if layer.__class__ in self.SVI_Layers: layer.kl_weight = kwargs['batch_size'] * layer.kl_weight/args[0].shape[0] if (self.one_hot == False) and self.task == 'classification': args = list(args) data_amnt = args[1].shape[0] args[1] = tf.one_hot(args[1] , tf.dtypes.cast(tf.reduce_max(args[1] ) + 1, tf.int32)) args[1] = tf.reshape(args[1], [data_amnt, -1]) args = tuple(args) if 'validation_data' in kwargs.keys(): kwargs['validation_data'] = list(kwargs['validation_data']) data_amnt = kwargs['validation_data'][1].shape[0] args[1] = tf.one_hot(kwargs['validation_data'][1] , tf.dtypes.cast(tf.reduce_max(kwargs['validation_data'][1] ) + 1, tf.int32)) args[1] = tf.reshape(kwargs['validation_data'][1], [data_amnt, -1]) args = tuple(args) self.model.fit(*args, **kwargs) if self.task == 'regression': self.train_std = 1 self.model.fit(*args, **kwargs) self.train_std = 0 for layer in self.model.layers: if layer.__class__ in self.SVI_Layers: layer.kl_weight = layer.kl_weight*args[0].shape[0]/kwargs['batch_size'] def predict(self, *args, return_std = True, **kwargs): """predict. Literally use this as you'd use the normal keras predict. Returns: a probability distribution over outputs, for each input. """ if self.use_normalization is True: args = list(args) args[0] = self.normalize(args[0]) args = tuple(args) y_pred = self.model.predict(*args, **kwargs) if self.task == 'regression': y_means, y_stds = tf.split(y_pred, [self.dim, self.dim], axis = 1) if self.use_normalization is True: y_means = self.unnormalize(y_means) y_stds = self.std_unnormalize(tf.exp(y_stds)) dist = tfp.distributions.Normal(loc=y_means, scale=y_stds) return dist if self.task == 'classification': y_pred = tf.reshape(y_pred, [-1, self.dim]) dist = tfp.distributions.Categorical(logits= y_pred) return distMethods
def Y_normalize(self, Y)-
Y_normalize. helper function to normalize output values in training set
Returns
normalized Y
Expand source code
def Y_normalize(self, Y): """Y_normalize. helper function to normalize output values in training set Returns: normalized Y """ return (Y - self.ymean)/self.ystd def compile(self, *args, loss=None, **kwargs)-
compile. Literally use this as you'd use the normal compile, but don't use your own loss functions, unless your really deep in this. Let the default one go
Args
loss- if you really wanna make your own loss function
Returns
Nothing lol
Expand source code
def compile(self, *args, loss=None, **kwargs): """compile. Literally use this as you'd use the normal compile, but don't use your own loss functions, unless your really deep in this. Let the default one go Args: loss: if you really wanna make your own loss function Returns: Nothing lol """ if loss is None: loss = self.neg_log_likelihood else: print("Warning: you might be in for a rocky ride here, you specified your own loss function. If you don't know what your doing, don't do this! Loss functions have to be in the style of neg_log_likelihood in the source code/") kwargs['loss'] = loss self.model.compile(*args, **kwargs) def elu_plus_one_plus_epsilon(self, x)-
ELU activation with a very small addition to help prevent NaN in loss.
Expand source code
def elu_plus_one_plus_epsilon(self, x): """ELU activation with a very small addition to help prevent NaN in loss.""" return tf.keras.backend.elu(x) + 1 + .00001 def evaluate(self, *args, **kwargs)-
evaluate. Literally use this as you'd use the normal keras evaluate.
Returns
The model's score, evaluated on whatever inputs you just fed it.
Expand source code
def evaluate(self, *args, **kwargs): """evaluate. Literally use this as you'd use the normal keras evaluate. Returns: The model's score, evaluated on whatever inputs you just fed it. """ if self.use_normalization is True: args = list(args) args[0] = self.normalize(args[0]) if self.task == 'regression': args[1] = self.Y_normalize(args[1]) args = tuple(args) if (self.one_hot == False) and self.task == 'classification': args = list(args) data_amnt = args[1].shape[0] args[1] = tf.one_hot(args[1] , tf.dtypes.cast(tf.reduce_max(args[1] ) + 1, tf.int32)) args[1] = tf.reshape(args[1], [data_amnt, -1]) args = tuple(args) return self.model.evaluate( *args, **kwargs) def fit(self, *args, **kwargs)-
fit. Literally use this as you'd use the normal keras fit.
Returns
Nothing lol.
Expand source code
def fit(self, *args, **kwargs): """fit. Literally use this as you'd use the normal keras fit. Returns: Nothing lol. """ if self.use_normalization is True: args = list(args) args[0], self.xmean, self.xstd = self.fit_normalize(args[0]) if self.task == 'regression': args[1], self.ymean, self.ystd = self.fit_normalize(args[1]) args = tuple(args) if 'batch_size' not in kwargs.keys(): kwargs['batch_size'] = 42 for layer in self.model.layers: if layer.__class__ in self.SVI_Layers: layer.kl_weight = kwargs['batch_size'] * layer.kl_weight/args[0].shape[0] if (self.one_hot == False) and self.task == 'classification': args = list(args) data_amnt = args[1].shape[0] args[1] = tf.one_hot(args[1] , tf.dtypes.cast(tf.reduce_max(args[1] ) + 1, tf.int32)) args[1] = tf.reshape(args[1], [data_amnt, -1]) args = tuple(args) if 'validation_data' in kwargs.keys(): kwargs['validation_data'] = list(kwargs['validation_data']) data_amnt = kwargs['validation_data'][1].shape[0] args[1] = tf.one_hot(kwargs['validation_data'][1] , tf.dtypes.cast(tf.reduce_max(kwargs['validation_data'][1] ) + 1, tf.int32)) args[1] = tf.reshape(kwargs['validation_data'][1], [data_amnt, -1]) args = tuple(args) self.model.fit(*args, **kwargs) if self.task == 'regression': self.train_std = 1 self.model.fit(*args, **kwargs) self.train_std = 0 for layer in self.model.layers: if layer.__class__ in self.SVI_Layers: layer.kl_weight = layer.kl_weight*args[0].shape[0]/kwargs['batch_size'] def fit_normalize(self, X)-
fit_normalize. helper function to normalize input values and generate future normalizations
Returns
normalized X, mean, std
Expand source code
def fit_normalize(self, X): """fit_normalize. helper function to normalize input values and generate future normalizations Returns: normalized X, mean, std """ mean = tf.math.reduce_mean(X, axis=0, keepdims=True) std = tf.math.reduce_std(X, axis=0, keepdims=True) return (X - mean)/std, mean, std def neg_log_likelihood(self, y_obs, y_pred)-
Expand source code
def neg_log_likelihood(self, y_obs, y_pred): if self.task == 'regression': y_means, y_stds = tf.split(y_pred, [self.dim, self.dim], axis = 1) if self.train_std == 1: pass y_stds = (y_stds)**2. + .1 else: y_stds = tf.constant(1.0) dist = tfp.distributions.Normal(loc=y_means, scale=y_stds ) return K.sum(-dist.log_prob(tf.dtypes.cast(y_obs, tf.float32))) if self.task == 'classification': y_pred = (tf.reshape(y_pred, [-1, self.dim])) y_obs = tf.reshape(y_obs, [-1, self.dim, 1]) dist = tfp.distributions.Categorical(logits = y_pred) return K.sum(-dist.log_prob(tf.dtypes.cast(y_obs, tf.int32))) def normalize(self, X)-
normalize. helper function to normalize input values
Returns
normalized X
Expand source code
def normalize(self, X): """normalize. helper function to normalize input values Returns: normalized X """ return (X - self.xmean)/self.xstd def predict(self, *args, return_std=True, **kwargs)-
predict. Literally use this as you'd use the normal keras predict.
Returns
a probability distribution over outputs, for each input.
Expand source code
def predict(self, *args, return_std = True, **kwargs): """predict. Literally use this as you'd use the normal keras predict. Returns: a probability distribution over outputs, for each input. """ if self.use_normalization is True: args = list(args) args[0] = self.normalize(args[0]) args = tuple(args) y_pred = self.model.predict(*args, **kwargs) if self.task == 'regression': y_means, y_stds = tf.split(y_pred, [self.dim, self.dim], axis = 1) if self.use_normalization is True: y_means = self.unnormalize(y_means) y_stds = self.std_unnormalize(tf.exp(y_stds)) dist = tfp.distributions.Normal(loc=y_means, scale=y_stds) return dist if self.task == 'classification': y_pred = tf.reshape(y_pred, [-1, self.dim]) dist = tfp.distributions.Categorical(logits= y_pred) return dist def std_unnormalize(self, Y)-
unnormalize. helper function to unnormalize output values by varying std– used for std predictions.
Returns
unnormalized Y
Expand source code
def std_unnormalize(self, Y): """unnormalize. helper function to unnormalize output values by varying std-- used for std predictions. Returns: unnormalized Y """ return Y * self.ystd def unnormalize(self, Y)-
unnormalize. helper function to unnormalize output values
Returns
unnormalized Y
Expand source code
def unnormalize(self, Y): """unnormalize. helper function to unnormalize output values Returns: unnormalized Y """ return (Y*self.ystd) + self.ymean