Computes N Gaussian expectation integrals of one or more functions using Monte Carlo samples. The Gaussians must be independent. `Fmu`, `Fvar`, `Ys` should all have same shape, with overall size `N`. :param funcs: the integrand(s): Callable or Iterable of Callables that op
(
funcs: Union[Callable[..., tf.Tensor], Iterable[Callable[..., tf.Tensor]]],
S: int,
Fmu: TensorType,
Fvar: TensorType,
logspace: bool = False,
epsilon: Optional[TensorType] = None,
**Ys: TensorType,
)
| 222 | "return: [broadcast n_funs, N, P]", |
| 223 | ) |
| 224 | def ndiag_mc( |
| 225 | funcs: Union[Callable[..., tf.Tensor], Iterable[Callable[..., tf.Tensor]]], |
| 226 | S: int, |
| 227 | Fmu: TensorType, |
| 228 | Fvar: TensorType, |
| 229 | logspace: bool = False, |
| 230 | epsilon: Optional[TensorType] = None, |
| 231 | **Ys: TensorType, |
| 232 | ) -> tf.Tensor: |
| 233 | """ |
| 234 | Computes N Gaussian expectation integrals of one or more functions |
| 235 | using Monte Carlo samples. The Gaussians must be independent. |
| 236 | |
| 237 | `Fmu`, `Fvar`, `Ys` should all have same shape, with overall size `N`. |
| 238 | |
| 239 | :param funcs: the integrand(s): |
| 240 | Callable or Iterable of Callables that operates elementwise |
| 241 | :param S: number of Monte Carlo sampling points |
| 242 | :param Fmu: array/tensor |
| 243 | :param Fvar: array/tensor |
| 244 | :param logspace: if True, funcs are the log-integrands and this calculates |
| 245 | the log-expectation of exp(funcs) |
| 246 | :param Ys: arrays/tensors; deterministic arguments to be passed by name |
| 247 | :return: shape is the same as that of the first Fmu |
| 248 | """ |
| 249 | N, D = tf.shape(Fmu)[0], tf.shape(Fvar)[1] |
| 250 | |
| 251 | if epsilon is None: |
| 252 | epsilon = tf.random.normal(shape=[S, N, D], dtype=default_float()) |
| 253 | |
| 254 | mc_x = Fmu[None, :, :] + tf.sqrt(Fvar[None, :, :]) * epsilon |
| 255 | mc_Xr = tf.reshape(mc_x, (S * N, D)) |
| 256 | |
| 257 | for name, Y in Ys.items(): |
| 258 | D_out = Y.shape[1] |
| 259 | # we can't rely on broadcasting and need tiling |
| 260 | mc_Yr = tf.tile(Y[None, ...], [S, 1, 1]) # [S, N, D]_out |
| 261 | Ys[name] = tf.reshape(mc_Yr, (S * N, D_out)) # S * [N, _]out |
| 262 | |
| 263 | def eval_func(func: Callable[..., tf.Tensor]) -> tf.Tensor: |
| 264 | feval = func(mc_Xr, **Ys) |
| 265 | feval = tf.reshape(feval, (S, N, -1)) |
| 266 | if logspace: |
| 267 | log_S = tf.math.log(to_default_float(S)) |
| 268 | return tf.reduce_logsumexp(feval, axis=0) - log_S # [N, D] |
| 269 | else: |
| 270 | return tf.reduce_mean(feval, axis=0) |
| 271 | |
| 272 | if isinstance(funcs, Iterable): |
| 273 | return [eval_func(f) for f in funcs] |
| 274 | else: |
| 275 | return eval_func(funcs) |
no test coverage detected
searching dependent graphs…