16e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# Copyright 2016 The TensorFlow Authors. All Rights Reserved. 26e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# 36e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# Licensed under the Apache License, Version 2.0 (the "License"); 46e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# you may not use this file except in compliance with the License. 56e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# You may obtain a copy of the License at 66e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# 76e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# http://www.apache.org/licenses/LICENSE-2.0 86e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# 96e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# Unless required by applicable law or agreed to in writing, software 106e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# distributed under the License is distributed on an "AS IS" BASIS, 116e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 126e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# See the License for the specific language governing permissions and 136e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# limitations under the License. 146e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon# ============================================================================== 156e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon"""CholeskyOuterProduct bijector.""" 166e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon 176e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillonfrom __future__ import absolute_import 186e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillonfrom __future__ import division 196e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillonfrom __future__ import print_function 206e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon 214972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlowerimport numpy as np 226e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon 234972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlowerfrom tensorflow.python.framework import ops 244972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlowerfrom tensorflow.python.framework import tensor_util 254972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlowerfrom tensorflow.python.ops import array_ops 264972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlowerfrom tensorflow.python.ops import check_ops 274972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlowerfrom tensorflow.python.ops import control_flow_ops 284972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlowerfrom tensorflow.python.ops import linalg_ops 294972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlowerfrom tensorflow.python.ops import math_ops 304972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlowerfrom tensorflow.python.ops.distributions import bijector 314972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlowerfrom tensorflow.python.ops.distributions import util as distribution_util 326e63cd2afb9e47a7e4f236c42786f94450be04ecJoshua V. Dillon 334972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 344972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower__all__ = [ 354972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower "CholeskyOuterProduct", 364972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower] 374972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 384972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 394972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlowerclass CholeskyOuterProduct(bijector.Bijector): 404972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower """Compute `g(X) = X @ X.T`; X is lower-triangular, positive-diagonal matrix. 414972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 424972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower `event_ndims` must be 0 or 2, i.e., scalar or matrix. 434972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 444972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower Note: the upper-triangular part of X is ignored (whether or not its zero). 454972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 464972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower The surjectivity of g as a map from the set of n x n positive-diagonal 474972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower lower-triangular matrices to the set of SPD matrices follows immediately from 484972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower executing the Cholesky factorization algorithm on an SPD matrix A to produce a 494972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower positive-diagonal lower-triangular matrix L such that `A = L @ L.T`. 504972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 514972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower To prove the injectivity of g, suppose that L_1 and L_2 are lower-triangular 524972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower with positive diagonals and satisfy `A = L_1 @ L_1.T = L_2 @ L_2.T`. Then 534972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower `inv(L_1) @ A @ inv(L_1).T = [inv(L_1) @ L_2] @ [inv(L_1) @ L_2].T = I`. 544972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower Setting `L_3 := inv(L_1) @ L_2`, that L_3 is a positive-diagonal 554972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower lower-triangular matrix follows from `inv(L_1)` being positive-diagonal 564972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower lower-triangular (which follows from the diagonal of a triangular matrix being 574972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower its spectrum), and that the product of two positive-diagonal lower-triangular 584972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower matrices is another positive-diagonal lower-triangular matrix. 594972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 604972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower A simple inductive argument (proceding one column of L_3 at a time) shows 614972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower that, if `I = L_3 @ L_3.T`, with L_3 being lower-triangular with positive- 624972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower diagonal, then `L_3 = I`. Thus, `L_1 = L_2`, proving injectivity of g. 634972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 644972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower Examples: 654972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 664972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower ```python 674972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower bijector.CholeskyOuterProduct(event_ndims=2).forward(x=[[1., 0], [2, 1]]) 684972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # Result: [[1., 2], [2, 5]], i.e., x @ x.T 694972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 704972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower bijector.CholeskyOuterProduct(event_ndims=2).inverse(y=[[1., 2], [2, 5]]) 714972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # Result: [[1., 0], [2, 1]], i.e., cholesky(y). 724972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower ``` 734972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 744972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower """ 754972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 764972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower def __init__(self, event_ndims=2, validate_args=False, 774972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower name="cholesky_outer_product"): 784972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower """Instantiates the `CholeskyOuterProduct` bijector. 794972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 804972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower Args: 814972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower event_ndims: `constant` `int32` scalar `Tensor` indicating the number of 824972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower dimensions associated with a particular draw from the distribution. Must 834972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower be 0 or 2. 844972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower validate_args: Python `bool` indicating whether arguments should be 854972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower checked for correctness. 864972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower name: Python `str` name given to ops managed by this object. 874972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 884972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower Raises: 894972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower ValueError: if event_ndims is neither 0 or 2. 904972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower """ 914972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower self._graph_parents = [] 924972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower self._name = name 934972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower with self._name_scope("init", values=[event_ndims]): 944972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower event_ndims = ops.convert_to_tensor(event_ndims, name="event_ndims") 954972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower event_ndims = tensor_util.constant_value(event_ndims) 964972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower if event_ndims is None or event_ndims not in [0, 2]: 974972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower raise ValueError("`event_ndims` must be a TF constant which is 0 or 2") 984972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower self._static_event_ndims = event_ndims 994972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower super(CholeskyOuterProduct, self).__init__( 1004972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower event_ndims=event_ndims, 1014972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower validate_args=validate_args, 1024972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower name=name) 1034972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 1044972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower def _forward(self, x): 1054972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower if self._static_event_ndims == 0: 1064972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower return math_ops.square(x) 1074972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower if self.validate_args: 1084972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower is_matrix = check_ops.assert_rank_at_least(x, 2) 1094972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower shape = array_ops.shape(x) 1104972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower is_square = check_ops.assert_equal(shape[-2], shape[-1]) 1114972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower x = control_flow_ops.with_dependencies([is_matrix, is_square], x) 1124972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # For safety, explicitly zero-out the upper triangular part. 1134972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower x = array_ops.matrix_band_part(x, -1, 0) 1144972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower return math_ops.matmul(x, x, adjoint_b=True) 1154972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 1164972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower def _inverse(self, y): 1174972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower return (math_ops.sqrt(y) if self._static_event_ndims == 0 1184972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower else linalg_ops.cholesky(y)) 1194972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 1204972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower def _inverse_log_det_jacobian(self, y): 1214972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower return -self._forward_log_det_jacobian(x=self._inverse(y)) 1224972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 1234972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower def _forward_log_det_jacobian(self, x): 1244972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # Let Y be a symmetric, positive definite matrix and write: 1254972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # Y = X X.T 1264972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # where X is lower-triangular. 1274972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # 1284972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # Observe that, 1294972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # dY[i,j]/dX[a,b] 1304972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # = d/dX[a,b] { X[i,:] X[j,:] } 1314972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # = sum_{d=1}^p { I[i=a] I[d=b] X[j,d] + I[j=a] I[d=b] X[i,d] } 1324972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # 1334972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # To compute the Jacobian dX/dY we must represent X,Y as vectors. Since Y is 1344972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # symmetric and X is lower-triangular, we need vectors of dimension: 1354972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # d = p (p + 1) / 2 1364972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # where X, Y are p x p matrices, p > 0. We use a row-major mapping, i.e., 1374972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # k = { i (i + 1) / 2 + j i>=j 1384972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # { undef i<j 1394972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # and assume zero-based indexes. When k is undef, the element is dropped. 1404972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # Example: 1414972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # j k 1424972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # 0 1 2 3 / 1434972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # 0 [ 0 . . . ] 1444972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # i 1 [ 1 2 . . ] 1454972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # 2 [ 3 4 5 . ] 1464972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # 3 [ 6 7 8 9 ] 1474972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # Write vec[.] to indicate transforming a matrix to vector via k(i,j). (With 1484972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # slight abuse: k(i,j)=undef means the element is dropped.) 1494972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # 1504972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # We now show d vec[Y] / d vec[X] is lower triangular. Assuming both are 1514972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # defined, observe that k(i,j) < k(a,b) iff (1) i<a or (2) i=a and j<b. 1524972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # In both cases dvec[Y]/dvec[X]@[k(i,j),k(a,b)] = 0 since: 1534972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # (1) j<=i<a thus i,j!=a. 1544972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # (2) i=a>j thus i,j!=a. 1554972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # 1564972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # Since the Jacobian is lower-triangular, we need only compute the product 1574972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # of diagonal elements: 1584972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # d vec[Y] / d vec[X] @[k(i,j), k(i,j)] 1594972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # = X[j,j] + I[i=j] X[i,j] 1604972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # = 2 X[j,j]. 1614972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # Since there is a 2 X[j,j] term for every lower-triangular element of X we 1624972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # conclude: 1634972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # |Jac(d vec[Y]/d vec[X])| = 2^p prod_{j=0}^{p-1} X[j,j]^{p-j}. 1644972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower if self._static_event_ndims == 0: 1654972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower if self.validate_args: 1664972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower is_positive = check_ops.assert_positive( 1674972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower x, message="All elements must be positive.") 1684972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower x = control_flow_ops.with_dependencies([is_positive], x) 1694972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower return np.log(2.) + math_ops.log(x) 1704972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 1714972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower diag = array_ops.matrix_diag_part(x) 1724972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 1734972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # We now ensure diag is columnar. Eg, if `diag = [1, 2, 3]` then the output 1744972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # is `[[1], [2], [3]]` and if `diag = [[1, 2, 3], [4, 5, 6]]` then the 1754972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # output is unchanged. 1764972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower diag = self._make_columnar(diag) 1774972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 1784972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower if self.validate_args: 1794972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower is_matrix = check_ops.assert_rank_at_least( 1804972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower x, 2, message="Input must be a (batch of) matrix.") 1814972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower shape = array_ops.shape(x) 1824972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower is_square = check_ops.assert_equal( 1834972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower shape[-2], shape[-1], 1844972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower message="Input must be a (batch of) square matrix.") 1854972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # Assuming lower-triangular means we only need check diag>0. 1864972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower is_positive_definite = check_ops.assert_positive( 1874972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower diag, message="Input must be positive definite.") 1884972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower x = control_flow_ops.with_dependencies( 1894972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower [is_matrix, is_square, is_positive_definite], x) 1904972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 1914972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower # Create a vector equal to: [p, p-1, ..., 2, 1]. 1924972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower if x.get_shape().ndims is None or x.get_shape()[-1].value is None: 1934972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower p_int = array_ops.shape(x)[-1] 1944972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower p_float = math_ops.cast(p_int, dtype=x.dtype) 1954972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower else: 1964972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower p_int = x.get_shape()[-1].value 1974972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower p_float = np.array(p_int, dtype=x.dtype.as_numpy_dtype) 1984972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower exponents = math_ops.linspace(p_float, 1., p_int) 1994972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 2004972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower sum_weighted_log_diag = array_ops.squeeze( 2014972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower math_ops.matmul(math_ops.log(diag), 2024972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower exponents[..., array_ops.newaxis]), 2034972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower squeeze_dims=-1) 2044972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower fldj = p_float * np.log(2.) + sum_weighted_log_diag 2054972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 2064972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower return fldj 2074972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 2084972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower def _make_columnar(self, x): 2094972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower """Ensures non-scalar input has at least one column. 2104972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 2114972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower Example: 2124972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower If `x = [1, 2, 3]` then the output is `[[1], [2], [3]]`. 2134972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 2144972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower If `x = [[1, 2, 3], [4, 5, 6]]` then the output is unchanged. 2154972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 2164972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower If `x = 1` then the output is unchanged. 2174972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 2184972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower Args: 2194972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower x: `Tensor`. 2204972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower 2214972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower Returns: 2224972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower columnar_x: `Tensor` with at least two dimensions. 2234972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower """ 2244972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower if x.get_shape().ndims is not None: 2254972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower if x.get_shape().ndims == 1: 2264972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower x = x[array_ops.newaxis, :] 2274972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower return x 2284972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower shape = array_ops.shape(x) 2294972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower maybe_expanded_shape = array_ops.concat([ 2304972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower shape[:-1], 2314972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower distribution_util.pick_vector( 2324972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower math_ops.equal(array_ops.rank(x), 1), 2334972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower [1], np.array([], dtype=np.int32)), 2344972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower shape[-1:], 2354972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower ], 0) 2364972095bb594c238de90688f1209ae8aeb7a1312A. Unique TensorFlower return array_ops.reshape(x, maybe_expanded_shape) 237