コード例 #1
0
  def test_roc_auc(self):
    """Tests that roc_auc's constraints give correct thresholds."""
    # We don't check roc_auc_upper_bound since most of the code is shared, and
    # the test is too slow already.
    bins = 3
    bisection_epsilon = 1e-6
    structure_memoizer = {
        defaults.DENOMINATOR_LOWER_BOUND_KEY: 0.0,
        defaults.GLOBAL_STEP_KEY: tf.Variable(0, dtype=tf.int32),
        defaults.VARIABLE_FN_KEY: tf.Variable
    }

    expression = binary_rates.roc_auc(self._context, bins)

    # Extract the the constraints and the associated variables.
    constraint_list = []
    variables = deferred_tensor.DeferredVariableList()
    for constraint in expression.extra_constraints:
      constraint_value = constraint.expression.constraint_expression.evaluate(
          structure_memoizer)
      constraint_list.append(constraint_value)
      variables += constraint_value.variables
    variables = variables.list
    self.assertEqual(bins, len(constraint_list))
    constraints = deferred_tensor.DeferredTensor.apply(
        lambda *args: tf.stack(args), *constraint_list)

    # We need to explicitly create all variables included in the expression
    # before we can try to extract the roc_auc_thresholds.
    for variable in variables:
      variable.create(structure_memoizer)

    # The find_zeros_of_functions() helper will perform a bisection search over
    # the roc_auc_thresholds, so we need to extract the Tensor containing them
    # from the graph.
    roc_auc_thresholds = None
    for variable in variables:
      tensor = variable(structure_memoizer)
      if tensor.name.startswith("tfco_roc_auc_thresholds"):
        self.assertIsNone(roc_auc_thresholds)
        roc_auc_thresholds = tensor
    self.assertIsNotNone(roc_auc_thresholds)

    def update_ops_fn():
      update_ops = []
      for variable in variables:
        update_ops += variable.update_ops(structure_memoizer)
      return update_ops

    with self.wrapped_session() as session:
      session.run_ops(update_ops_fn)

      def evaluate_fn(values):
        """Assigns the variables and evaluates the constraints."""
        session.run_ops(lambda: roc_auc_thresholds.assign(values))
        return session.run(constraints(structure_memoizer))

      actual_thresholds = test_helpers.find_zeros_of_functions(
          bins, evaluate_fn, epsilon=bisection_epsilon)

    expected_thresholds = self._find_roc_auc_thresholds(bins)
    self.assertAllClose(
        expected_thresholds, actual_thresholds, rtol=0, atol=bisection_epsilon)
    def test_precision(self):
        """Checks `precision`."""
        bisection_epsilon = 1e-6
        structure_memoizer = {
            defaults.DENOMINATOR_LOWER_BOUND_KEY: 0.0,
            defaults.GLOBAL_STEP_KEY: tf.Variable(0, dtype=tf.int32),
            defaults.VARIABLE_FN_KEY: tf.Variable
        }

        expression = general_rates.precision(self._context)

        # Extract the the constraints and the associated variables.
        constraint_list = []
        variables = deferred_tensor.DeferredVariableList()
        for constraint in expression.extra_constraints:
            constraint_value = constraint.expression.constraint_expression.evaluate(
                structure_memoizer)
            constraint_list.append(constraint_value)
            variables += constraint_value.variables
        variables = variables.list
        self.assertEqual(2, len(constraint_list))
        constraints = deferred_tensor.DeferredTensor.apply(
            lambda *args: tf.stack(args), *constraint_list)

        # We need to explicitly create all variables included in the expression
        # before we can try to extract the ratio_bounds.
        for variable in variables:
            variable.create(structure_memoizer)

        # The find_zeros_of_functions() helper will perform a bisection search over
        # the ratio_bounds, so we need to extract the Tensor containing them from
        # the graph.
        ratio_bounds = None
        for variable in variables:
            tensor = variable(structure_memoizer)
            if tensor.name.startswith("tfco_ratio_bounds"):
                self.assertIsNone(ratio_bounds)
                ratio_bounds = tensor
        self.assertIsNotNone(ratio_bounds)

        def update_ops_fn():
            update_ops = []
            for variable in variables:
                update_ops += variable.update_ops(structure_memoizer)
            return update_ops

        with self.wrapped_session() as session:
            session.run_ops(update_ops_fn)

            def evaluate_fn(values):
                """Assigns the variables and evaluates the constraints."""
                session.run_ops(lambda: ratio_bounds.assign(values))
                return session.run(constraints(structure_memoizer))

            actual_ratio_bounds = test_helpers.find_zeros_of_functions(
                2, evaluate_fn, epsilon=bisection_epsilon)
            actual_numerator = actual_ratio_bounds[0]
            actual_denominator = actual_ratio_bounds[1]

        expected_numerator = (np.sum(
            (0.5 * (1.0 + np.sign(self._predictions))) *
            (self._labels > 0.0) * self._weights) / np.sum(self._weights))

        expected_denominator = (np.sum(
            (0.5 * (1.0 + np.sign(self._predictions))) * self._weights) /
                                np.sum(self._weights))

        self.assertAllClose(expected_numerator,
                            actual_numerator,
                            rtol=0,
                            atol=bisection_epsilon)
        self.assertAllClose(expected_denominator,
                            actual_denominator,
                            rtol=0,
                            atol=bisection_epsilon)
    def test_f_score(self):
        """Checks `f_score`."""
        beta = 1.6
        bisection_epsilon = 1e-6
        structure_memoizer = {
            defaults.DENOMINATOR_LOWER_BOUND_KEY: 0.0,
            defaults.GLOBAL_STEP_KEY: tf.Variable(0, dtype=tf.int32),
            defaults.VARIABLE_FN_KEY: tf.Variable
        }

        expression = general_rates.f_score(self._context, beta)

        # Extract the the constraints and the associated variables.
        constraint_list = []
        variables = deferred_tensor.DeferredVariableList()
        for constraint in expression.extra_constraints:
            constraint_value = constraint.expression.constraint_expression.evaluate(
                structure_memoizer)
            constraint_list.append(constraint_value)
            variables += constraint_value.variables
        variables = variables.list
        self.assertEqual(1, len(constraint_list))
        constraints = deferred_tensor.DeferredTensor.apply(
            lambda *args: tf.stack(args), *constraint_list)

        # We need to explicitly create all variables included in the expression
        # before we can try to extract the denominator_bound.
        for variable in variables:
            variable.create(structure_memoizer)

        # The find_zeros_of_functions() helper will perform a bisection search over
        # the denominator_bound, so we need to extract the Tensor containing them
        # from the graph.
        denominator_bound = None
        for variable in variables:
            tensor = variable(structure_memoizer)
            if tensor.name.startswith("tfco_denominator_bound"):
                self.assertIsNone(denominator_bound)
                denominator_bound = tensor
        self.assertIsNotNone(denominator_bound)

        def update_ops_fn():
            update_ops = []
            for variable in variables:
                update_ops += variable.update_ops(structure_memoizer)
            return update_ops

        with self.wrapped_session() as session:
            session.run_ops(update_ops_fn)

            def evaluate_fn(values):
                """Assigns the variables and evaluates the constraints."""
                # We need to extract the first element from the one-element "values"
                # Tensor, since the denominator_bound has shape (), not (1,).
                session.run_ops(lambda: denominator_bound.assign(values[0]))
                return session.run(constraints(structure_memoizer))

            # We need to extract the first element here, for the same reason as above.
            actual_denominator_bound = test_helpers.find_zeros_of_functions(
                1, evaluate_fn, epsilon=bisection_epsilon)[0]

        expected_denominator = (((1.0 + beta * beta) * np.sum(
            (0.5 * (1.0 + np.sign(self._predictions))) *
            (self._labels > 0.0) * self._weights) + (beta * beta) * np.sum(
                (0.5 * (1.0 - np.sign(self._predictions))) *
                (self._labels > 0.0) * self._weights) + np.sum(
                    (0.5 * (1.0 + np.sign(self._predictions))) *
                    (self._labels <= 0.0) * self._weights)) /
                                np.sum(self._weights))

        self.assertAllClose(expected_denominator,
                            actual_denominator_bound,
                            rtol=0,
                            atol=bisection_epsilon)