def _build_entropy(self, weights, means, covars):
# First build half a square matrix of normals. This avoids re-computing symmetric normals.
log_normal_probs = util.init_list(0.0, [self.num_components, self.num_components])
for i in xrange(self.num_components):
for j in xrange(i, self.num_components):
for k in xrange(self.num_latent):
if self.diag_post:
normal = util.DiagNormal(means[i, k, :], covars[i, k, :] +
covars[j, k, :])
else:
if i == j:
# Compute chol(2S) = sqrt(2)*chol(S).
covars_sum = tf.sqrt(2.0) * covars[i, k, :, :]
else:
# TODO(karl): Can we just stay in cholesky space somehow?
covars_sum = tf.cholesky(util.mat_square(covars[i, k, :, :]) +
util.mat_square(covars[j, k, :, :]))
normal = util.CholNormal(means[i, k, :], covars_sum)
log_normal_probs[i][j] += normal.log_prob(means[j, k, :])
# Now compute the entropy.
entropy = 0.0
for i in xrange(self.num_components):
weighted_log_probs = util.init_list(0.0, [self.num_components])
for j in xrange(self.num_components):
if i <= j:
weighted_log_probs[j] = tf.log(weights[j]) + log_normal_probs[i][j]
else:
weighted_log_probs[j] = tf.log(weights[j]) + log_normal_probs[j][i]
entropy -= weights[i] * util.logsumexp(tf.stack(weighted_log_probs))
return entropy
评论列表
文章目录