Transform diagonal of [batch-]matrix, leave rest of matrix unchanged. Create a trainable covariance defined by a Cholesky factor: ```python # Transform network layer into 2 x 2 array. matrix_values = tf.contrib.layers.fully_connected(activations, 4) matrix = tf.reshape(matrix_values, (ba
(matrix, transform=None, name=None)
| 519 | |
| 520 | |
| 521 | def matrix_diag_transform(matrix, transform=None, name=None): |
| 522 | """Transform diagonal of [batch-]matrix, leave rest of matrix unchanged. |
| 523 | |
| 524 | Create a trainable covariance defined by a Cholesky factor: |
| 525 | |
| 526 | ```python |
| 527 | # Transform network layer into 2 x 2 array. |
| 528 | matrix_values = tf.contrib.layers.fully_connected(activations, 4) |
| 529 | matrix = tf.reshape(matrix_values, (batch_size, 2, 2)) |
| 530 | |
| 531 | # Make the diagonal positive. If the upper triangle was zero, this would be a |
| 532 | # valid Cholesky factor. |
| 533 | chol = matrix_diag_transform(matrix, transform=tf.nn.softplus) |
| 534 | |
| 535 | # LinearOperatorLowerTriangular ignores the upper triangle. |
| 536 | operator = LinearOperatorLowerTriangular(chol) |
| 537 | ``` |
| 538 | |
| 539 | Example of heteroskedastic 2-D linear regression. |
| 540 | |
| 541 | ```python |
| 542 | tfd = tfp.distributions |
| 543 | |
| 544 | # Get a trainable Cholesky factor. |
| 545 | matrix_values = tf.contrib.layers.fully_connected(activations, 4) |
| 546 | matrix = tf.reshape(matrix_values, (batch_size, 2, 2)) |
| 547 | chol = matrix_diag_transform(matrix, transform=tf.nn.softplus) |
| 548 | |
| 549 | # Get a trainable mean. |
| 550 | mu = tf.contrib.layers.fully_connected(activations, 2) |
| 551 | |
| 552 | # This is a fully trainable multivariate normal! |
| 553 | dist = tfd.MultivariateNormalTriL(mu, chol) |
| 554 | |
| 555 | # Standard log loss. Minimizing this will "train" mu and chol, and then dist |
| 556 | # will be a distribution predicting labels as multivariate Gaussians. |
| 557 | loss = -1 * tf.reduce_mean(dist.log_prob(labels)) |
| 558 | ``` |
| 559 | |
| 560 | Args: |
| 561 | matrix: Rank `R` `Tensor`, `R >= 2`, where the last two dimensions are |
| 562 | equal. |
| 563 | transform: Element-wise function mapping `Tensors` to `Tensors`. To be |
| 564 | applied to the diagonal of `matrix`. If `None`, `matrix` is returned |
| 565 | unchanged. Defaults to `None`. |
| 566 | name: A name to give created ops. Defaults to "matrix_diag_transform". |
| 567 | |
| 568 | Returns: |
| 569 | A `Tensor` with same shape and `dtype` as `matrix`. |
| 570 | """ |
| 571 | with ops.name_scope(name, "matrix_diag_transform", [matrix]): |
| 572 | matrix = ops.convert_to_tensor(matrix, name="matrix") |
| 573 | if transform is None: |
| 574 | return matrix |
| 575 | # Replace the diag with transformed diag. |
| 576 | diag = array_ops.matrix_diag_part(matrix) |
| 577 | transformed_diag = transform(diag) |
| 578 | transformed_mat = array_ops.matrix_set_diag(matrix, transformed_diag) |
nothing calls this directly
no test coverage detected