Ejemplo n.º 1
0
def scalar_constrainer(support):
    def nonzero(x):
        return tf.where(tf.equal(x, 0), 1e-6, x)

    constrainers = {
        Support.SCALAR_IN_0_1: tf.math.sigmoid,
        Support.SCALAR_GT_NEG1: tfp_hps.softplus_plus_eps(-1 + 1e-6),
        Support.SCALAR_NON_ZERO: nonzero,
        Support.SCALAR_IN_NEG1_1: lambda x: tf.math.tanh(x) * (1 - 1e-6),
        Support.SCALAR_NON_NEGATIVE: tf.math.softplus,
        Support.SCALAR_POSITIVE: tfp_hps.softplus_plus_eps(),
        Support.SCALAR_UNCONSTRAINED: tf.identity,
    }
    return constrainers[support]
def generalized_paretos(draw, batch_shape=None):
  if batch_shape is None:
    batch_shape = draw(tfp_hps.shapes())

  constraints = dict(
      loc=tfp_hps.identity_fn,
      scale=tfp_hps.softplus_plus_eps(),
      concentration=lambda x: tf.math.tanh(x) * 0.24)  # <.25==safe for variance

  params = draw(
      tfp_hps.broadcasting_params(
          batch_shape,
          params_event_ndims=dict(loc=0, scale=0, concentration=0),
          constraint_fn_for=constraints.get))
  dist = tfd.GeneralizedPareto(validate_args=draw(hps.booleans()), **params)
  if dist.batch_shape != batch_shape:
    raise AssertionError('batch_shape mismatch: expect {} but got {}'.format(
        batch_shape, dist))
  return dist
Ejemplo n.º 3
0
    # Ensure that low < high.
    return dict(d, high=tfp_hps.ensure_high_gt_low(d['low'], d['high']))


def fix_softclip(d):
    # Ensure that low < high.
    return dict(d, high=tfp_hps.ensure_high_gt_low(d['low'], d['high']))


def fix_rational_quadratic(d):
    return dict(d, range_min=-1)


CONSTRAINTS = {
    'concentration':
    tfp_hps.softplus_plus_eps(),
    'concentration0':
    tfp_hps.softplus_plus_eps(),
    'concentration1':
    tfp_hps.softplus_plus_eps(),
    'hinge_softness':
    tfp_hps.softplus_plus_eps(),
    'power':
    # Restrict to positive since `Invert(Power(...))` tests the negation.
    tfp_hps.softplus_plus_eps(),
    'rate':
    tfp_hps.softplus_plus_eps(),
    'scale':
    tfp_hps.softplus_plus_eps(),
    'tailweight':
    tfp_hps.softplus_plus_eps(),
          'method `inverse_log_det_jacobian` of {}'.format(bijector),
          max_permissible=max_permitted):
        tape.watch(wrt_vars)
        # TODO(b/73073515): Fix graph mode gradients with bijector caching.
        xs = bijector.inverse_log_det_jacobian(ys + 0, event_ndims=event_ndims)
    grads = tape.gradient(xs, wrt_vars)
    assert_no_none_grad(bijector, 'inverse_log_det_jacobian', wrt_vars, grads)


def ensure_nonzero(x):
  return tf.where(x < 1e-6, tf.constant(1e-3, x.dtype), x)


CONSTRAINTS = {
    'concentration':
        tfp_hps.softplus_plus_eps(),
    'concentration0':
        tfp_hps.softplus_plus_eps(),
    'concentration1':
        tfp_hps.softplus_plus_eps(),
    'scale':
        tfp_hps.softplus_plus_eps(),
    'tailweight':
        tfp_hps.softplus_plus_eps(),
    'AffineScalar.scale':
        tfp_hps.softplus_plus_eps(),
    'bin_widths':
        bijector_hps.spline_bin_size_constraint,
    'bin_heights':
        bijector_hps.spline_bin_size_constraint,
    'knot_slopes':
Ejemplo n.º 5
0
    return dict(d, peak=peak, high=high)


def fix_wishart(d):
    df = d['df']
    scale = d.get('scale', d.get('scale_tril'))
    return dict(d, df=tf.maximum(df, tf.cast(scale.shape[-1], df.dtype)))


CONSTRAINTS = {
    'atol':
        tf.math.softplus,
    'rtol':
        tf.math.softplus,
    'concentration':
        tfp_hps.softplus_plus_eps(),
    'GeneralizedPareto.concentration':  # Permits +ve and -ve concentrations.
        lambda x: tf.math.tanh(x) * 0.24,
    'concentration0':
        tfp_hps.softplus_plus_eps(),
    'concentration1':
        tfp_hps.softplus_plus_eps(),
    'covariance_matrix':
        tfp_hps.positive_definite,
    'df':
        tfp_hps.softplus_plus_eps(),
    'InverseGaussian.loc':
        tfp_hps.softplus_plus_eps(),
    'VonMisesFisher.mean_direction':  # max ndims is 5
        lambda x: tf.math.l2_normalize(tf.math.sigmoid(x[..., :5]) + 1e-6, -1),
    'Categorical.probs':
                tape.watch(wrt_vars)
                with tfp_hps.no_tf_rank_errors():
                    diag = kernel.apply(xs, xs, example_ndims=example_ndims)
        grads = tape.gradient(diag, wrt_vars)
        assert_no_none_grad(kernel, 'apply', wrt_vars, grads)

        # Check that reconstructing the kernel works
        with tfp_hps.no_tf_rank_errors():
            diag2 = type(kernel)(**kernel._parameters).apply(
                xs, xs, example_ndims=example_ndims)
        self.assertAllClose(diag, diag2)


CONSTRAINTS = {
    # Keep amplitudes large enough so that the matrices are well conditioned.
    'amplitude': tfp_hps.softplus_plus_eps(1.),
    'bias_variance': tfp_hps.softplus_plus_eps(1.),
    'slope_variance': tfp_hps.softplus_plus_eps(1.),
    'exponent': tfp_hps.softplus_plus_eps(),
    'length_scale': tfp_hps.softplus_plus_eps(),
    'period': tfp_hps.softplus_plus_eps(),
    'scale_mixture_rate': tfp_hps.softplus_plus_eps(),
}


def constraint_for(kernel_name=None, param=None):
    if param is not None:
        return CONSTRAINTS.get('{}.{}'.format(kernel_name, param),
                               CONSTRAINTS.get(param, tfp_hps.identity_fn))
    return CONSTRAINTS.get(kernel_name, tfp_hps.identity_fn)
  return dict(d, peak=peak, high=high)


def fix_wishart(d):
  df = d['df']
  scale = d.get('scale', d.get('scale_tril'))
  return dict(d, df=tf.maximum(df, tf.cast(scale.shape[-1], df.dtype)))


CONSTRAINTS = {
    'atol':
        tf.math.softplus,
    'rtol':
        tf.math.softplus,
    'concentration':
        tfp_hps.softplus_plus_eps(),
    'GeneralizedPareto.concentration':  # Permits +ve and -ve concentrations.
        lambda x: tf.math.tanh(x) * 0.24,
    'concentration0':
        tfp_hps.softplus_plus_eps(),
    'concentration1':
        tfp_hps.softplus_plus_eps(),
    'covariance_matrix':
        tfp_hps.positive_definite,
    'df':
        tfp_hps.softplus_plus_eps(),
    'Chi2WithAbsDf.df':
        tfp_hps.softplus_plus_eps(1),  # does floor(abs(x)) for some reason
    'InverseGaussian.loc':
        tfp_hps.softplus_plus_eps(),
    'VonMisesFisher.mean_direction':  # max ndims is 5
Ejemplo n.º 8
0
def feature_scaleds(draw,
                    batch_shape=None,
                    event_dim=None,
                    feature_dim=None,
                    feature_ndims=None,
                    enable_vars=None,
                    depth=None):
    """Strategy for drawing `FeatureScaled` kernels.

  The underlying kernel is drawn from the `kernels` strategy.

  Args:
    draw: Hypothesis strategy sampler supplied by `@hps.composite`.
    batch_shape: An optional `TensorShape`.  The batch shape of the resulting
      Kernel.  Hypothesis will pick a batch shape if omitted.
    event_dim: Optional Python int giving the size of each of the
      kernel's parameters' event dimensions.  This is shared across all
      parameters, permitting square event matrices, compatible location and
      scale Tensors, etc. If omitted, Hypothesis will choose one.
    feature_dim: Optional Python int giving the size of each feature dimension.
      If omitted, Hypothesis will choose one.
    feature_ndims: Optional Python int stating the number of feature dimensions
      inputs will have. If omitted, Hypothesis will choose one.
    enable_vars: TODO(bjp): Make this `True` all the time and put variable
      initialization in slicing_test.  If `False`, the returned parameters are
      all Tensors, never Variables or DeferredTensor.
    depth: Python `int` giving maximum nesting depth of compound kernel.

  Returns:
    kernels: A strategy for drawing `FeatureScaled` kernels with the specified
      `batch_shape` (or an arbitrary one if omitted).
  """
    if depth is None:
        depth = draw(depths())
    if batch_shape is None:
        batch_shape = draw(tfp_hps.shapes())
    if event_dim is None:
        event_dim = draw(hps.integers(min_value=2, max_value=6))
    if feature_dim is None:
        feature_dim = draw(hps.integers(min_value=2, max_value=6))
    if feature_ndims is None:
        feature_ndims = draw(hps.integers(min_value=2, max_value=6))

    base_kernel, kernel_variable_names = draw(
        kernels(batch_shape=batch_shape,
                event_dim=event_dim,
                feature_dim=feature_dim,
                feature_ndims=feature_ndims,
                enable_vars=False,
                depth=depth - 1))
    scale_diag = tfp_hps.softplus_plus_eps()(draw(
        kernel_input(batch_shape=batch_shape,
                     example_ndims=0,
                     feature_dim=feature_dim,
                     feature_ndims=feature_ndims)))

    hp.note(
        'Forming FeatureScaled kernel with scale_diag: {} '.format(scale_diag))

    if enable_vars and draw(hps.booleans()):
        kernel_variable_names.append('scale_diag')
        scale_diag = tf.Variable(scale_diag, name='scale_diag')
        # Don't enable variable counting. This is because rescaling is
        # done for each input, which will exceed two convert_to_tensor calls.
    result_kernel = tfp.positive_semidefinite_kernels.FeatureScaled(
        kernel=base_kernel, scale_diag=scale_diag, validate_args=True)
    return result_kernel, kernel_variable_names
Ejemplo n.º 9
0
def spectral_mixtures(draw,
                      batch_shape=None,
                      event_dim=None,
                      feature_dim=None,
                      feature_ndims=None,
                      enable_vars=None,
                      depth=None):
    """Strategy for drawing `SpectralMixture` kernels.

  The underlying kernel is drawn from the `kernels` strategy.

  Args:
    draw: Hypothesis strategy sampler supplied by `@hps.composite`.
    batch_shape: An optional `TensorShape`.  The batch shape of the resulting
      Kernel.  Hypothesis will pick a batch shape if omitted.
    event_dim: Optional Python int giving the size of each of the
      kernel's parameters' event dimensions.  This is shared across all
      parameters, permitting square event matrices, compatible location and
      scale Tensors, etc. If omitted, Hypothesis will choose one.
    feature_dim: Optional Python int giving the size of each feature dimension.
      If omitted, Hypothesis will choose one.
    feature_ndims: Optional Python int stating the number of feature dimensions
      inputs will have. If omitted, Hypothesis will choose one.
    enable_vars: TODO(bjp): Make this `True` all the time and put variable
      initialization in slicing_test.  If `False`, the returned parameters are
      all Tensors, never Variables or DeferredTensor.
    depth: Python `int` giving maximum nesting depth of compound kernel.

  Returns:
    kernels: A strategy for drawing `SchurComplement` kernels with the specified
      `batch_shape` (or an arbitrary one if omitted).
  """
    if depth is None:
        depth = draw(depths())
    if batch_shape is None:
        batch_shape = draw(tfp_hps.shapes())
    if event_dim is None:
        event_dim = draw(hps.integers(min_value=2, max_value=6))
    if feature_dim is None:
        feature_dim = draw(hps.integers(min_value=2, max_value=6))
    if feature_ndims is None:
        feature_ndims = draw(hps.integers(min_value=2, max_value=6))

    num_mixtures = draw(hps.integers(min_value=2, max_value=5))

    logits = draw(
        kernel_input(batch_shape=batch_shape,
                     example_ndims=0,
                     feature_dim=num_mixtures,
                     feature_ndims=1))

    locs = draw(
        kernel_input(batch_shape=batch_shape,
                     example_ndims=1,
                     example_dim=num_mixtures,
                     feature_dim=feature_dim,
                     feature_ndims=feature_ndims))

    scales = tfp_hps.softplus_plus_eps()(draw(
        kernel_input(batch_shape=batch_shape,
                     example_ndims=1,
                     example_dim=num_mixtures,
                     feature_dim=feature_dim,
                     feature_ndims=feature_ndims)))

    hp.note(f'Forming SpectralMixture kernel with logits: {logits} '
            f'locs: {locs} and scales: {scales}')

    spectral_mixture_params = {
        'locs': locs,
        'logits': logits,
        'scales': scales
    }

    kernel_variable_names = []
    for param_name in spectral_mixture_params:
        if enable_vars and draw(hps.booleans()):
            kernel_variable_names.append(param_name)
            spectral_mixture_params[param_name] = tf.Variable(
                spectral_mixture_params[param_name], name=param_name)
            if draw(hps.booleans()):
                spectral_mixture_params[
                    param_name] = tfp_hps.defer_and_count_usage(
                        spectral_mixture_params[param_name])
    result_kernel = tfpk.SpectralMixture(
        logits=spectral_mixture_params['logits'],
        locs=spectral_mixture_params['locs'],
        scales=spectral_mixture_params['scales'],
        feature_ndims=feature_ndims,
        validate_args=True)
    return result_kernel, kernel_variable_names
Ejemplo n.º 10
0
def changepoints(draw,
                 batch_shape=None,
                 event_dim=None,
                 feature_dim=None,
                 feature_ndims=None,
                 enable_vars=None,
                 depth=None):
    """Strategy for drawing `Changepoint` kernels.

  The underlying kernel is drawn from the `kernels` strategy.

  Args:
    draw: Hypothesis strategy sampler supplied by `@hps.composite`.
    batch_shape: An optional `TensorShape`.  The batch shape of the resulting
      Kernel.  Hypothesis will pick a batch shape if omitted.
    event_dim: Optional Python int giving the size of each of the
      kernel's parameters' event dimensions.  This is shared across all
      parameters, permitting square event matrices, compatible location and
      scale Tensors, etc. If omitted, Hypothesis will choose one.
    feature_dim: Optional Python int giving the size of each feature dimension.
      If omitted, Hypothesis will choose one.
    feature_ndims: Optional Python int stating the number of feature dimensions
      inputs will have. If omitted, Hypothesis will choose one.
    enable_vars: TODO(bjp): Make this `True` all the time and put variable
      initialization in slicing_test.  If `False`, the returned parameters are
      all Tensors, never Variables or DeferredTensor.
    depth: Python `int` giving maximum nesting depth of compound kernel.

  Returns:
    kernels: A strategy for drawing `Changepoint` kernels with the specified
      `batch_shape` (or an arbitrary one if omitted).
  """
    if depth is None:
        depth = draw(depths())
    if batch_shape is None:
        batch_shape = draw(tfp_hps.shapes())
    if event_dim is None:
        event_dim = draw(hps.integers(min_value=2, max_value=6))
    if feature_dim is None:
        feature_dim = draw(hps.integers(min_value=2, max_value=6))
    if feature_ndims is None:
        feature_ndims = draw(hps.integers(min_value=2, max_value=6))

    num_kernels = draw(hps.integers(min_value=2, max_value=4))

    inner_kernels = []
    kernel_variable_names = []
    for _ in range(num_kernels):
        base_kernel, variable_names = draw(
            kernels(batch_shape=batch_shape,
                    event_dim=event_dim,
                    feature_dim=feature_dim,
                    feature_ndims=feature_ndims,
                    enable_vars=False,
                    depth=depth - 1))
        inner_kernels.append(base_kernel)
        kernel_variable_names += variable_names

    constraints = dict(
        locs=lambda x: tf.cumsum(tf.math.abs(x) + 1e-3, axis=-1),
        slopes=tfp_hps.softplus_plus_eps())

    params = draw(
        tfp_hps.broadcasting_params(batch_shape,
                                    event_dim=num_kernels - 1,
                                    params_event_ndims=dict(locs=1, slopes=1),
                                    constraint_fn_for=constraints.get))
    params = {k: tf.cast(params[k], tf.float64) for k in params}

    if enable_vars and draw(hps.booleans()):
        kernel_variable_names.append('locs')
        kernel_variable_names.append('slopes')
        params['locs'] = tf.Variable(params['locs'], name='locs')
        params['slopes'] = tf.Variable(params['slopes'], name='slopes')
    result_kernel = tfpk.ChangePoint(kernels=inner_kernels,
                                     validate_args=True,
                                     **params)
    return result_kernel, kernel_variable_names
Ejemplo n.º 11
0
                max_permitted = (2 if hasattr(
                    bijector.bijector, '_forward_log_det_jacobian') else 4)
            with tfp_hps.assert_no_excessive_var_usage(
                    'method `inverse_log_det_jacobian` of {}'.format(bijector),
                    max_permissible=max_permitted):
                tape.watch(wrt_vars)
                # TODO(b/73073515): Fix graph mode gradients with bijector caching.
                xs = bijector.inverse_log_det_jacobian(ys + 0,
                                                       event_ndims=event_ndims)
        grads = tape.gradient(xs, wrt_vars)
        assert_no_none_grad(bijector, 'inverse_log_det_jacobian', wrt_vars,
                            grads)


CONSTRAINTS = {
    'concentration0': tfp_hps.softplus_plus_eps(),
    'concentration1': tfp_hps.softplus_plus_eps(),
    'scale': tfp_hps.softplus_plus_eps(),
    'tailweight': tfp_hps.softplus_plus_eps(),
    'AffineScalar.scale': tfp_hps.softplus_plus_eps(),
}


def constraint_for(bijector_name=None, param=None):
    if param is not None:
        return CONSTRAINTS.get('{}.{}'.format(bijector_name, param),
                               CONSTRAINTS.get(param, tfp_hps.identity_fn))
    return CONSTRAINTS.get(bijector_name, tfp_hps.identity_fn)


if __name__ == '__main__':