def _build_graph(self, raw_weights, raw_means, raw_covars, raw_inducing_inputs,
train_inputs, train_outputs, num_train, test_inputs):
# First transform all raw variables into their internal form.
# Use softmax(raw_weights) to keep all weights normalized.
weights = tf.exp(raw_weights) / tf.reduce_sum(tf.exp(raw_weights))
if self.diag_post:
# Use exp(raw_covars) so as to guarantee the diagonal matrix remains positive definite.
covars = tf.exp(raw_covars)
else:
# Use vec_to_tri(raw_covars) so as to only optimize over the lower triangular portion.
# We note that we will always operate over the cholesky space internally.
covars_list = [None] * self.num_components
for i in xrange(self.num_components):
mat = util.vec_to_tri(raw_covars[i, :, :])
diag_mat = tf.matrix_diag(tf.matrix_diag_part(mat))
exp_diag_mat = tf.matrix_diag(tf.exp(tf.matrix_diag_part(mat)))
covars_list[i] = mat - diag_mat + exp_diag_mat
covars = tf.stack(covars_list, 0)
# Both inducing inputs and the posterior means can vary freely so don't change them.
means = raw_means
inducing_inputs = raw_inducing_inputs
# Build the matrices of covariances between inducing inputs.
kernel_mat = [self.kernels[i].kernel(inducing_inputs[i, :, :])
for i in xrange(self.num_latent)]
kernel_chol = tf.stack([tf.cholesky(k) for k in kernel_mat], 0)
# Now build the objective function.
entropy = self._build_entropy(weights, means, covars)
cross_ent = self._build_cross_ent(weights, means, covars, kernel_chol)
ell = self._build_ell(weights, means, covars, inducing_inputs,
kernel_chol, train_inputs, train_outputs)
batch_size = tf.to_float(tf.shape(train_inputs)[0])
nelbo = -((batch_size / num_train) * (entropy + cross_ent) + ell)
# Build the leave one out loss function.
loo_loss = self._build_loo_loss(weights, means, covars, inducing_inputs,
kernel_chol, train_inputs, train_outputs)
# Finally, build the prediction function.
predictions = self._build_predict(weights, means, covars, inducing_inputs,
kernel_chol, test_inputs)
return nelbo, loo_loss, predictions
评论列表
文章目录