Example #1
0
def true_mean_confidence_interval_by_dkwm(
    samples, low, high, error_rate=1e-6, name=None):
  """Computes a confidence interval for the mean of a scalar distribution.

  In batch mode, computes confidence intervals for all distributions
  in the batch (which need not be identically distributed).

  Relies on the [Dvoretzky-Kiefer-Wolfowitz-Massart inequality]
  (https://en.wikipedia.org/wiki/CDF-based_nonparametric_confidence_interval).

  The probability (over the randomness of drawing the given samples)
  that any true mean is outside the corresponding returned interval is
  no more than the given `error_rate`.  The size of the intervals
  scale as
  `O(1 / sqrt(#samples))`, as `O(high - low)`, and as `O(-log(error_rate))`.

  Note that `error_rate` is a total error rate for all the confidence
  intervals in the batch.  As such, if the batch is nontrivial, the
  error rate is not broadcast but divided (evenly) among the batch
  members.

  Args:
    samples: Floating-point `Tensor` of samples from the distribution(s)
      of interest.  Entries are assumed IID across the 0th dimension.
      The other dimensions must broadcast with `low` and `high`.
      The support is bounded: `low <= samples <= high`.
    low: Floating-point `Tensor` of lower bounds on the distributions'
      supports.
    high: Floating-point `Tensor` of upper bounds on the distributions'
      supports.
    error_rate: *Scalar* floating-point `Tensor` admissible total rate
      of mistakes.
    name: A name for this operation (optional).

  Returns:
    low: A floating-point `Tensor` of stochastic lower bounds on the
      true means.
    high: A floating-point `Tensor` of stochastic upper bounds on the
      true means.
  """
  with tf.name_scope(name, "true_mean_confidence_interval_by_dkwm",
                     [samples, low, high, error_rate]):
    dtype = dtype_util.common_dtype(
        [samples, low, high, error_rate], tf.float32)
    samples = tf.convert_to_tensor(samples, name="samples", dtype=dtype)
    low = tf.convert_to_tensor(low, name="low", dtype=dtype)
    high = tf.convert_to_tensor(high, name="high", dtype=dtype)
    error_rate = tf.convert_to_tensor(
        error_rate, name="error_rate", dtype=dtype)
    samples = _check_shape_dominates(samples, [low, high])
    tf.assert_scalar(error_rate)  # Static shape
    error_rate = _itemwise_error_rate(error_rate, [low, high], samples)
    n = tf.shape(samples)[0]
    envelope = _dkwm_cdf_envelope(n, error_rate)
    min_mean = _minimum_mean(samples, envelope, low)
    max_mean = _maximum_mean(samples, envelope, high)
    return min_mean, max_mean
Example #2
0
def op(name,
       data,
       display_name=None,
       description=None,
       collections=None):
  """Create a scalar summary op.

  Arguments:
    name: A unique name for the generated summary node.
    data: A real numeric rank-0 `Tensor`. Must have `dtype` castable
      to `float32`.
    display_name: Optional name for this summary in TensorBoard, as a
      constant `str`. Defaults to `name`.
    description: Optional long-form description for this summary, as a
      constant `str`. Markdown is supported. Defaults to empty.
    collections: Optional list of graph collections keys. The new
      summary op is added to these collections. Defaults to
      `[Graph Keys.SUMMARIES]`.

  Returns:
    A TensorFlow summary op.
  """
  if display_name is None:
    display_name = name
  summary_metadata = metadata.create_summary_metadata(
      display_name=display_name, description=description)
  with tf.name_scope(name):
    with tf.control_dependencies([tf.assert_scalar(data)]):
      return tf.summary.tensor_summary(name='scalar_summary',
                                       tensor=tf.cast(data, tf.float32),
                                       collections=collections,
                                       summary_metadata=summary_metadata)
Example #3
0
def gumbel_softmax(inputs: tf.Tensor,
                   temperature: float = 1.0,
                   symmetric: bool = False,
                   axis: int = -1,
                   scope: Optional[str] = None) -> tf.Tensor:
    if inputs.shape[axis].value <= 2:
        raise ValueError(
            'logits must have at least size 3 on axis={}'.format(axis))

    temperature = tf.convert_to_tensor(temperature, dtype=inputs.dtype)
    with tf.variable_scope(scope, 'gumbel_softmax', [inputs]):
        temperature = tf.assert_scalar(temperature)
        assert_op = tf.assert_greater(temperature, 0.0)

        with tf.control_dependencies([assert_op]):
            gumbel = -tf.log(
                -tf.log(tf.random_uniform(inputs.shape, dtype=inputs.dtype)))
            if symmetric:
                gumbel = (gumbel + tf.matrix_transpose(gumbel)) / 2.0
            gumbel_logits = gumbel + inputs
            gumbel_softmax = tf.exp(
                tf.nn.log_softmax(tf.div(gumbel_logits, temperature),
                                  axis=axis))

    return gumbel_softmax
Example #4
0
def op(name, data, display_name=None, description=None, collections=None):
    """Create a legacy scalar summary op.

  Arguments:
    name: A unique name for the generated summary node.
    data: A real numeric rank-0 `Tensor`. Must have `dtype` castable
      to `float32`.
    display_name: Optional name for this summary in TensorBoard, as a
      constant `str`. Defaults to `name`.
    description: Optional long-form description for this summary, as a
      constant `str`. Markdown is supported. Defaults to empty.
    collections: Optional list of graph collections keys. The new
      summary op is added to these collections. Defaults to
      `[Graph Keys.SUMMARIES]`.

  Returns:
    A TensorFlow summary op.
  """
    if display_name is None:
        display_name = name
    summary_metadata = metadata.create_summary_metadata(
        display_name=display_name, description=description)
    with tf.name_scope(name):
        with tf.control_dependencies([tf.assert_scalar(data)]):
            return tf.summary.tensor_summary(name='scalar_summary',
                                             tensor=tf.cast(data, tf.float32),
                                             collections=collections,
                                             summary_metadata=summary_metadata)
Example #5
0
def scalar(name, tensor, tag=None, description=None, step=None):
    """Create a scalar summary op.

  Arguments:
    name: A name for the generated summary node.
    tensor: A real numeric rank-0 `Tensor`. Must have `dtype` castable
      to `float32`.
    tag: Optional rank-0 string `Tensor` to identify this summary in
      TensorBoard.  Defaults to the generated name of this op.
    description: Optional long-form description for this summary, as a
      constant `str`. Markdown is supported. Defaults to empty.
    step: Optional `int64` monotonic step variable, which defaults
      to `tf.train.get_global_step`.

  Returns:
    A TensorFlow summary op.
  """
    # TODO(nickfelt): make tag param work
    summary_metadata = metadata.create_summary_metadata(
        display_name=None, description=description)
    with tf.name_scope(name, values=[tensor, tag, step]) as scope:
        with tf.control_dependencies([tf.assert_scalar(tensor)]):
            return tf.contrib.summary.generic(name=scope,
                                              tensor=tf.cast(
                                                  tensor, tf.float32),
                                              metadata=summary_metadata,
                                              step=step)
Example #6
0
    def _build_loss(self):
        policy = self.local_or_global_policy
        self._actions_ph = tf.placeholder(tf.int32, [None], name="actions")
        self._rewards_ph = tf.placeholder(tf.float32, [None], name="rewards")
        self._resets_ph = tf.placeholder(tf.float32, [None], name="resets")

        with tf.variable_scope("loss"):
            with tf.variable_scope("predictions"):
                self._predictions = slice_with_actions(policy.output_tensor,
                                                       self._actions_ph)

            with tf.variable_scope("targets"):
                self._next_actions = tf.cast(
                    tf.argmax(policy.target.values, axis=-1), tf.int32)
                all_next_step_predictions = slice_with_actions(
                    policy.target.output_tensor, self._next_actions)
                next_step_multiplier = (1 - self._resets_ph)[..., None]
                self._next_step_predictions = (next_step_multiplier *
                                               self._gamma *
                                               all_next_step_predictions)
                self._targets = self._rewards_ph[
                    ..., None] + self._next_step_predictions

            with tf.variable_scope("quantile_loss"):
                nbins = policy.output_tensor.shape[-1].value
                cdf = np.arange(0, nbins + 1) / nbins
                midpoints = (cdf[:-1] + cdf[1:]) / 2
                overestimation = tf.to_float(
                    self._targets[..., None] < self._predictions[:, None])

                if self._kind == "qr-dqn-0":
                    loss = tf.reduce_sum(tf.reduce_mean(
                        (self._targets[..., None] - self._predictions[:, None])
                        * (midpoints[None, None] - overestimation),
                        axis=[0, 1]),
                                         axis=0)
                else:
                    assert self._kind == "qr-dqn-1", self._kind
                    loss = tf.reduce_sum(tf.reduce_mean(
                        huber_loss(self._targets[..., None] -
                                   self._predictions[:, None]) *
                        tf.abs(midpoints[None, None] - overestimation),
                        axis=[0, 1]),
                                         axis=0)
                tf.assert_scalar(loss)
                return loss
Example #7
0
def gradient_penalty(model: MolGANModel,
                     real_adj: tf.Tensor,
                     real_features: tf.Tensor,
                     gen_adj: tf.Tensor,
                     gen_features: tf.Tensor,
                     discriminator_scope: str,
                     gradient_penalty_weight: float = 10.0,
                     target: float = 1.0,
                     add_summaries: bool = False) -> tf.Tensor:
    scope = '{}GradientPenalty'.format(discriminator_scope.replace('/', ''))
    with tf.name_scope(scope,
                       values=[real_adj, real_features, gen_adj,
                               gen_features]):
        batch_size = gen_adj.shape[0].value
        eps = tf.random_uniform(shape=[batch_size
                                       ])  # batch_size times random numbers

        intp_inputs = {}

        eps_adj = eps
        for _ in range(real_adj.shape.ndims - 1):
            eps_adj = tf.expand_dims(eps_adj, axis=-1)

        intp_inputs['adjacency_in'] = eps_adj * real_adj + (1.0 -
                                                            eps_adj) * gen_adj

        eps_features = eps
        for _ in range(real_features.shape.ndims - 1):
            eps_features = tf.expand_dims(eps_features, axis=-1)

        intp_inputs['features'] = eps_features * real_features + (
            1.0 - eps_features) * gen_features

        with tf.name_scope(
                None):  # Clear scope so update ops are added properly.
            with tf.variable_scope(discriminator_scope, reuse=True):
                disc_interpolates = model.discriminator_fn(
                    intp_inputs, mode=tf.estimator.ModeKeys.TRAIN)

        grads = tf.gradients(
            disc_interpolates,
            (intp_inputs['adjacency_in'], intp_inputs['features']))

        penalty = tf.reduce_sum([
            _penalty_from_gradient(g, batch_size, target=target, scope=sc)
            for g, sc in zip(grads, ['adj_grad_pen', 'feat_grad_pen'])
        ])
        gp_weight = tf.convert_to_tensor(gradient_penalty_weight,
                                         dtype=penalty.dtype)
        gp_weight = tf.assert_scalar(gp_weight)
        penalty *= gp_weight

        tf.losses.add_loss(penalty)
        if add_summaries:
            tf.summary.scalar('gradient_penalty_loss', penalty)

    return penalty
Example #8
0
def _buckets(data, bucket_count=None):
  """Create a TensorFlow op to group data into histogram buckets.

  Arguments:
    data: A `Tensor` of any shape. Must be castable to `float64`.
    bucket_count: Optional positive `int` or scalar `int32` `Tensor`.
  Returns:
    A `Tensor` of shape `[k, 3]` and type `float64`. The `i`th row is
    a triple `[left_edge, right_edge, count]` for a single bucket.
    The value of `k` is either `bucket_count` or `1` or `0`.
  """
  if bucket_count is None:
    bucket_count = DEFAULT_BUCKET_COUNT
  with tf.name_scope('buckets', values=[data, bucket_count]), \
       tf.control_dependencies([tf.assert_scalar(bucket_count),
                                tf.assert_type(bucket_count, tf.int32)]):
    data = tf.reshape(data, shape=[-1])  # flatten
    data = tf.cast(data, tf.float64)
    is_empty = tf.equal(tf.size(data), 0)

    def when_empty():
      return tf.constant([], shape=(0, 3), dtype=tf.float64)

    def when_nonempty():
      min_ = tf.reduce_min(data)
      max_ = tf.reduce_max(data)
      range_ = max_ - min_
      is_singular = tf.equal(range_, 0)

      def when_nonsingular():
        bucket_width = range_ / tf.cast(bucket_count, tf.float64)
        offsets = data - min_
        bucket_indices = tf.cast(tf.floor(offsets / bucket_width),
                                 dtype=tf.int32)
        clamped_indices = tf.minimum(bucket_indices, bucket_count - 1)
        one_hots = tf.one_hot(clamped_indices, depth=bucket_count)
        bucket_counts = tf.cast(tf.reduce_sum(one_hots, axis=0),
                                dtype=tf.float64)
        edges = tf.lin_space(min_, max_, bucket_count + 1)
        left_edges = edges[:-1]
        right_edges = edges[1:]
        return tf.transpose(tf.stack(
            [left_edges, right_edges, bucket_counts]))

      def when_singular():
        center = min_
        bucket_starts = tf.stack([center - 0.5])
        bucket_ends = tf.stack([center + 0.5])
        bucket_counts = tf.stack([tf.cast(tf.size(data), tf.float64)])
        return tf.transpose(
            tf.stack([bucket_starts, bucket_ends, bucket_counts]))

      return tf.cond(is_singular, when_singular, when_nonsingular)

    return tf.cond(is_empty, when_empty, when_nonempty)
Example #9
0
def _buckets(data, bucket_count=None):
    """Create a TensorFlow op to group data into histogram buckets.

  Arguments:
    data: A `Tensor` of any shape. Must be castable to `float64`.
    bucket_count: Optional positive `int` or scalar `int32` `Tensor`.
  Returns:
    A `Tensor` of shape `[k, 3]` and type `float64`. The `i`th row is
    a triple `[left_edge, right_edge, count]` for a single bucket.
    The value of `k` is either `bucket_count` or `1` or `0`.
  """
    if bucket_count is None:
        bucket_count = DEFAULT_BUCKET_COUNT
    with tf.name_scope('buckets', values=[data, bucket_count]), \
         tf.control_dependencies([tf.assert_scalar(bucket_count),
                                  tf.assert_type(bucket_count, tf.int32)]):
        data = tf.reshape(data, shape=[-1])  # flatten
        data = tf.cast(data, tf.float64)
        is_empty = tf.equal(tf.size(data), 0)

        def when_empty():
            return tf.constant([], shape=(0, 3), dtype=tf.float64)

        def when_nonempty():
            min_ = tf.reduce_min(data)
            max_ = tf.reduce_max(data)
            range_ = max_ - min_
            is_singular = tf.equal(range_, 0)

            def when_nonsingular():
                bucket_width = range_ / tf.cast(bucket_count, tf.float64)
                offsets = data - min_
                bucket_indices = tf.cast(tf.floor(offsets / bucket_width),
                                         dtype=tf.int32)
                clamped_indices = tf.minimum(bucket_indices, bucket_count - 1)
                one_hots = tf.one_hot(clamped_indices, depth=bucket_count)
                bucket_counts = tf.cast(tf.reduce_sum(one_hots, axis=0),
                                        dtype=tf.float64)
                edges = tf.lin_space(min_, max_, bucket_count + 1)
                left_edges = edges[:-1]
                right_edges = edges[1:]
                return tf.transpose(
                    tf.stack([left_edges, right_edges, bucket_counts]))

            def when_singular():
                center = min_
                bucket_starts = tf.stack([center - 0.5])
                bucket_ends = tf.stack([center + 0.5])
                bucket_counts = tf.stack([tf.cast(tf.size(data), tf.float64)])
                return tf.transpose(
                    tf.stack([bucket_starts, bucket_ends, bucket_counts]))

            return tf.cond(is_singular, when_singular, when_nonsingular)

        return tf.cond(is_empty, when_empty, when_nonempty)
Example #10
0
    def _build_loss(self):
        policy = self.local_or_global_policy
        self._actions_ph = tf.placeholder(tf.int32, [None], name="actions")
        self._rewards_ph = tf.placeholder(tf.float32, [None], name="rewards")
        self._resets_ph = tf.placeholder(tf.float32, [None], name="resets")

        with tf.variable_scope("loss"):
            with tf.variable_scope("predictions"):
                self._predictions = slice_with_actions(policy.values,
                                                       self._actions_ph)

            with tf.variable_scope("targets"):
                next_step_predictions = tf.reduce_max(policy.target.values,
                                                      axis=-1)
                self._next_step_predictions = ((1 - self._resets_ph) *
                                               self._gamma *
                                               next_step_predictions)
                self._targets = self._rewards_ph + self._next_step_predictions

                loss = tf.reduce_mean(
                    huber_loss(self._targets - self._predictions))
                tf.assert_scalar(loss)
                return loss
Example #11
0
def reward_loss(model: MolGANModel,
                reward_real: tf.Tensor,
                reward_generated: tf.Tensor,
                gan_loss: tfgan.GANLoss,
                lam: float,
                add_summaries: bool = False,
                scope: Optional[str] = None) -> MolGANLoss:
    with tf.name_scope(scope, 'ValueLoss'):
        loss_on_real = tf.losses.mean_squared_error(reward_real,
                                                    model.valuenet_real_probs)
        loss_on_generated = tf.losses.mean_squared_error(
            reward_generated, model.valuenet_gen_probs)
        loss_V = 0.5 * (loss_on_real + loss_on_generated)
        tf.losses.add_loss(loss_V)

        # maximize reward on generated
        gen_reward = tf.reduce_mean(model.valuenet_gen_probs)
        gen_value_loss = -gen_reward
        gen_loss = gan_loss.generator_loss

        alpha = tf.abs(tf.stop_gradient(gen_loss / gen_value_loss))
        lam = tf.assert_scalar(lam)

        generator_loss = lam * gen_loss + (1.0 - lam) * alpha * gen_value_loss

        if add_summaries:
            tf.summary.scalar('lambda', lam)
            tf.summary.scalar('alpha', alpha)
            tf.summary.scalar('reward_on_generated', gen_reward)
            tf.summary.scalar('valuenet_gen_mse_loss', loss_on_generated)
            tf.summary.scalar('valuenet_real_mse_loss', loss_on_real)
            tf.summary.scalar('valuenet_mse_loss', loss_V)

    return MolGANLoss(generator_loss=generator_loss,
                      discriminator_loss=gan_loss.discriminator_loss,
                      valuenet_loss=loss_V)
Example #12
0
 def test_loss_shape(self):
     tf.assert_scalar(self.model.loss_tensor)
Example #13
0
 def test_generator_loss_shape(self):
     tf.assert_scalar(self.model.g_loss)