def _multi_gamma_sequence(self, a, p, name='multi_gamma_sequence'): """Creates sequence used in multivariate (di)gamma; shape = shape(a)+[p].""" with tf.name_scope(name): # Linspace only takes scalars, so we'll add in the offset afterwards. seq = ps.linspace(tf.constant(0., dtype=self.dtype), 0.5 - 0.5 * p, ps.cast(p, tf.int32)) return seq + a[..., tf.newaxis]
def resample_systematic(log_probs, event_size, sample_shape, seed=None, name=None): """A systematic resampler for sequential Monte Carlo. The value returned from this function is similar to sampling with ```python expanded_sample_shape = tf.concat([[event_size], sample_shape]), axis=-1) tfd.Categorical(logits=log_probs).sample(expanded_sample_shape)` ``` but with values sorted along the first axis. It can be considered to be sampling events made up of a length-`event_size` vector of draws from the `Categorical` distribution. However, although the elements of this event have the appropriate marginal distribution, they are not independent of each other. Instead they are drawn using a stratified sampling method that in some sense reduces variance and is suitable for use with Sequential Monte Carlo algorithms as described in [Doucet et al. (2011)][2]. The sortedness is an unintended side effect of the algorithm that is harmless in the context of simple SMC algorithms. This implementation is based on the algorithms in [Maskell et al. (2006)][1] where it is called minimum variance resampling. Args: log_probs: A tensor-valued batch of discrete log probability distributions. event_size: the dimension of the vector considered a single draw. sample_shape: the `sample_shape` determining the number of draws. seed: PRNG seed; see `tfp.random.sanitize_seed` for details. Default value: None (i.e. no seed). name: Python `str` name for ops created by this method. Default value: `None` (i.e., `'resample_systematic'`). Returns: resampled_indices: a tensor of samples. #### References [1]: S. Maskell, B. Alun-Jones and M. Macleod. A Single Instruction Multiple Data Particle Filter. In 2006 IEEE Nonlinear Statistical Signal Processing Workshop. http://people.ds.cam.ac.uk/fanf2/hermes/doc/antiforgery/stats.pdf [2]: A. Doucet & A. M. Johansen. Tutorial on Particle Filtering and Smoothing: Fifteen Years Later In 2011 The Oxford Handbook of Nonlinear Filtering https://www.stats.ox.ac.uk/~doucet/doucet_johansen_tutorialPF2011.pdf """ with tf.name_scope(name or 'resample_systematic') as name: log_probs = tf.convert_to_tensor(log_probs, dtype_hint=tf.float32) log_probs = dist_util.move_dimension(log_probs, source_idx=0, dest_idx=-1) working_shape = ps.concat( [sample_shape, ps.shape(log_probs)[:-1]], axis=0) points_shape = ps.concat([working_shape, [event_size]], axis=0) # Draw a single offset for each event. interval_width = ps.cast(1. / event_size, dtype=log_probs.dtype) offsets = uniform.Uniform(low=ps.cast(0., dtype=log_probs.dtype), high=interval_width).sample( working_shape, seed=seed)[..., tf.newaxis] even_spacing = ps.linspace(start=ps.cast(0., dtype=log_probs.dtype), stop=1 - interval_width, num=event_size) + offsets log_points = tf.broadcast_to(tf.math.log(even_spacing), points_shape) resampled = _resample_using_log_points(log_probs, sample_shape, log_points) return dist_util.move_dimension(resampled, source_idx=-1, dest_idx=0)