示例#1
0
 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)