def testInitialValueOfMaskedTimeSeries(self):

        if not self.use_static_shape:
            return  # Dynamic rank is not currently supported.

        series = tf.random.stateless_normal(
            [2, 1, 3, 4], seed=test_util.test_seed(sampler_type='stateless'))
        mask = np.array([
            [False, True, False, True],
            [True, False, True, False],
            # Ensure no error if a batch element is fully masked.
            [True, True, True, True]
        ])
        expected_initial_values = distribution_util.move_dimension(
            tf.convert_to_tensor(
                [series[..., 0, 0], series[..., 1, 1], series[..., 2, 3]]),
            source_idx=0,
            dest_idx=-1)

        initial_values = missing_values_util.initial_value_of_masked_time_series(
            self._build_tensor(self.evaluate(series)),
            broadcast_mask=self._build_tensor(self.evaluate(
                tf.broadcast_to(mask, series.shape)),
                                              dtype=np.bool_))

        self.assertAllClose(self.evaluate(initial_values),
                            expected_initial_values)
Exemple #2
0
def empirical_statistics(observed_time_series):
  """Compute statistics of a provided time series, as heuristic initialization.

  Args:
    observed_time_series: `Tensor` representing a time series, or batch of time
       series, of shape either `batch_shape + [num_timesteps, 1]` or
       `batch_shape + [num_timesteps]` (allowed if `num_timesteps > 1`).

  Returns:
    observed_mean: `Tensor` of shape `batch_shape`, giving the empirical
      mean of each time series in the batch.
    observed_stddev: `Tensor` of shape `batch_shape`, giving the empirical
      standard deviation of each time series in the batch.
    observed_initial_centered: `Tensor of shape `batch_shape`, giving the
      initial value of each time series in the batch after centering
      (subtracting the mean).
  """

  with tf.name_scope('empirical_statistics'):

    [
        observed_time_series,
        mask
    ] = canonicalize_observed_time_series_with_mask(observed_time_series)

    squeezed_series = observed_time_series[..., 0]
    if mask is None:
      observed_mean, observed_variance = tf.nn.moments(
          x=squeezed_series, axes=-1)
      observed_initial = squeezed_series[..., 0]
    else:
      broadcast_mask = tf.broadcast_to(tf.cast(mask, tf.bool),
                                       tf.shape(input=squeezed_series))
      observed_mean, observed_variance = (
          missing_values_util.moments_of_masked_time_series(
              squeezed_series, broadcast_mask=broadcast_mask))
      try:
        observed_initial = (
            missing_values_util.initial_value_of_masked_time_series(
                squeezed_series, broadcast_mask=broadcast_mask))
      except NotImplementedError:
        tf1.logging.warn(
            'Cannot compute initial values for a masked time series'
            'with dynamic shape; using the mean instead. This will'
            'affect heuristic priors and may change the results of'
            'inference.')
        observed_initial = observed_mean

    observed_stddev = tf.sqrt(observed_variance)
    observed_initial_centered = observed_initial - observed_mean
    return observed_mean, observed_stddev, observed_initial_centered
  def testInitialValueOfMaskedTimeSeries(self):

    if not self.use_static_shape:
      return  # Dynamic rank is not currently supported.

    series = np.random.randn(2, 4)
    mask = np.array([[False, True, False, True],
                     [True, False, True, False]])
    expected_initial_values = [series[0, 0], series[1, 1]]

    initial_values = missing_values_util.initial_value_of_masked_time_series(
        self._build_tensor(series),
        broadcast_mask=self._build_tensor(mask, dtype=np.bool))

    self.assertAllClose(self.evaluate(initial_values), expected_initial_values)
Exemple #4
0
def empirical_statistics(observed_time_series):
    """Compute statistics of a provided time series, as heuristic initialization.

  If a series is entirely unobserved (all values are masked), default statistics
  `mean == 0.`, `stddev == 1.`, and `initial_centered == 0.` are returned.

  To avoid degenerate models, a value of `1.` is returned for `stddev` whenever
  the input series is entirely constant (when the true `stddev` is `0.`).

  Args:
    observed_time_series: `Tensor` representing a time series, or batch of time
       series, of shape either `batch_shape + [num_timesteps, 1]` or
       `batch_shape + [num_timesteps]` (allowed if `num_timesteps > 1`).

  Returns:
    observed_mean: `Tensor` of shape `batch_shape`, giving the empirical
      mean of each time series in the batch.
    observed_stddev: `Tensor` of shape `batch_shape`, giving the empirical
      standard deviation of each time series in the batch.
    observed_initial_centered: `Tensor of shape `batch_shape`, giving the
      initial value of each time series in the batch after centering
      (subtracting the mean).
  """

    with tf.name_scope('empirical_statistics'):

        [observed_time_series, mask
         ] = canonicalize_observed_time_series_with_mask(observed_time_series)

        squeezed_series = observed_time_series[..., 0]
        if mask is None:
            observed_mean, observed_variance = tf.nn.moments(x=squeezed_series,
                                                             axes=-1)
            observed_initial = squeezed_series[..., 0]
        else:
            broadcast_mask = tf.broadcast_to(tf.cast(mask, tf.bool),
                                             ps.shape(squeezed_series))
            observed_mean, observed_variance = (
                missing_values_util.moments_of_masked_time_series(
                    squeezed_series, broadcast_mask=broadcast_mask))
            try:
                observed_initial = (
                    missing_values_util.initial_value_of_masked_time_series(
                        squeezed_series, broadcast_mask=broadcast_mask))
            except NotImplementedError:
                tf1.logging.warn(
                    'Cannot compute initial values for a masked time series'
                    'with dynamic shape; using the mean instead. This will'
                    'affect heuristic priors and may change the results of'
                    'inference.')
                observed_initial = observed_mean

        observed_stddev = tf.sqrt(observed_variance)
        observed_initial_centered = observed_initial - observed_mean

        # Dividing by zero will estimate `inf` or `nan` for the mean and stddev
        # (and thus initial_centered) if a series is entirely masked. Replace these
        # with default values.
        replace_nans = (lambda x, v: tf.where(tf.math.is_finite(x), x,
                                              tf.cast(v, x.dtype)))
        # Avoid stddev of zero from a constant series.
        replace_zeros = (
            lambda x, v: tf.where(tf.equal(x, 0.), tf.cast(v, x.dtype), x))
        return (replace_nans(observed_mean, 0.),
                replace_zeros(replace_nans(observed_stddev, 1.),
                              1.), replace_nans(observed_initial_centered, 0.))