Exemple #1
0
 def build_train_op_tfco(self,
                         learning_rate=0.1):
     ctx = tfco.multiclass_rate_context(self.num_classes,
                                        self.predictions_tensor,
                                        self.labels_placeholder)
     # positive_slice = ctx.subset(self.labels_placeholder > 0)
     # overall_tpr = tfco.positive_prediction_rate(positive_slice)
     constraints = []
     for c in range(self.num_classes):
         pos_rate = tfco.positive_prediction_rate(ctx, c)
         constraints.append(pos_rate <= (1.05 / self.num_classes))
     mp = tfco.RateMinimizationProblem(tfco.error_rate(ctx), constraints)
     self.opt = tfco.ProxyLagrangianOptimizerV1(tf.train.AdamOptimizer(learning_rate))
     self.train_op = self.opt.minimize(mp)
     return self.train_op
Exemple #2
0
    def build_train_op_ctx(self, learning_rate=.001):
        # We initialize the constrained problem using the rate helpers.
        ctx = tfco.rate_context(self.predictions_tensor,
                                self.labels_placeholder)
        positive_slice = ctx.subset(self.labels_placeholder > 0)
        overall_tpr = tfco.positive_prediction_rate(positive_slice)
        constraints = []
        for placeholder in self.protected_placeholders:
            slice_tpr = tfco.positive_prediction_rate(
                ctx.subset((placeholder > 0) & (self.labels_placeholder > 0)))
            tmp = 2 * (overall_tpr - slice_tpr)
            constraints.append(tmp)

        constraint = sum(constraints) <= 0.2 * self.didi_tr
        mp = tfco.RateMinimizationProblem(tfco.error_rate(ctx), [constraint])
        opt = tfco.ProxyLagrangianOptimizerV1(
            tf.train.AdamOptimizer(learning_rate))
        self.train_op = opt.minimize(mp)
        return self.train_op
Exemple #3
0
    def lagrangian_optimizer(train_set,
                             epsilon=epsilon,
                             learning_rate=0.01,
                             learning_rate_constraint=0.01,
                             loops=2000):
        tf.reset_default_graph()

        x_train, y_train, z_train = train_set
        num_examples = x_train.shape[0]
        dimension = x_train.shape[-1]

        # Data tensors.
        features_tensor = tf.constant(x_train.astype("float32"),
                                      name="features")
        labels_tensor = tf.constant(y_train.astype("float32"), name="labels")

        # Linear model.
        weights = tf.Variable(tf.zeros(dimension, dtype=tf.float32),
                              name="weights")
        threshold = tf.Variable(0, name="threshold", dtype=tf.float32)
        predictions_tensor = (
            tf.tensordot(features_tensor, weights, axes=(1, 0)) + threshold)

        predictions_group0 = tf.boolean_mask(predictions_tensor,
                                             mask=(z_train < 1))
        num0 = np.sum(z_train < 1)
        predictions_group1 = tf.boolean_mask(predictions_tensor,
                                             mask=(z_train > 0))
        num1 = np.sum(z_train > 0)

        # Set up rates.
        context = tfco.rate_context(predictions_tensor, labels_tensor)
        true_positive_rate = tfco.true_positive_rate(context)
        true_negative_rate = tfco.true_negative_rate(context)

        context0 = context.subset(z_train < 1)
        true_positive_rate0 = tfco.true_positive_rate(context0)

        context1 = context.subset(z_train > 0)
        true_positive_rate1 = tfco.true_positive_rate(context1)

        # Set up slack variables.
        slack_tpr = tf.Variable(0.5, dtype=tf.float32)
        slack_tnr = tf.Variable(0.5, dtype=tf.float32)

        # Projection ops for slacks.
        projection_ops = []
        projection_ops.append(
            tf.assign(slack_tpr, tf.clip_by_value(slack_tpr, 0.001, 0.999)))
        projection_ops.append(
            tf.assign(slack_tnr, tf.clip_by_value(slack_tnr, 0.001, 0.999)))

        # Set up 1 - G-mean objective.
        objective = tfco.wrap_rate(1.0 - tf.sqrt(slack_tpr * slack_tnr))

        # Set up slack constraints.
        constraints = []
        constraints.append(tfco.wrap_rate(slack_tpr) <= true_positive_rate)
        constraints.append(tfco.wrap_rate(slack_tnr) <= true_negative_rate)

        # Set up fairness equal-opportunity constraints.
        constraints.append(
            true_positive_rate0 <= true_positive_rate1 + epsilon)
        constraints.append(
            true_positive_rate1 <= true_positive_rate0 + epsilon)

        # Set up constraint optimization problem.
        problem = tfco.RateMinimizationProblem(objective, constraints)

        # Set up solver.
        optimizer = tf.train.AdamOptimizer(learning_rate)
        constraint_optimizer = tf.train.AdamOptimizer(learning_rate_constraint)
        lagrangian_optimizer = tfco.ProxyLagrangianOptimizerV1(
            optimizer=optimizer, constraint_optimizer=constraint_optimizer)
        train_op = lagrangian_optimizer.minimize(problem)

        # Start TF session and initialize variables.
        session = tf.Session()
        tf.set_random_seed(654321)  # Set random seed for reproducibility.
        session.run(tf.global_variables_initializer())

        # We maintain a list of objectives and model weights during training.
        objectives = []
        violations = []
        models = []

        # Perform  full gradient updates.
        for ii in xrange(loops):
            # Gradient update.
            session.run(train_op)
            # Projection.
            session.run(projection_ops)

            # Checkpoint once in 100 iterations.
            if ii % 100 == 0:
                # Model weights.
                model = [session.run(weights), session.run(threshold)]
                models.append(model)

                # Snapshot performace
                error, tpr0, tpr1 = evaluate_expected_results(
                    train_set, [model], [1.0])
                objectives.append(error)
                violations.append(
                    [tpr0 - tpr1 - epsilon, tpr1 - tpr0 - epsilon])

        # Use the recorded objectives and constraints to find the best iterate.
        # Best model
        best_iterate = tfco.find_best_candidate_index(np.array(objectives),
                                                      np.array(violations))
        best_model = models[best_iterate]

        # Stochastic model over a subset of classifiers.
        probabilities = tfco.find_best_candidate_distribution(
            np.array(objectives), np.array(violations))
        models_pruned = [
            models[i] for i in range(len(models)) if probabilities[i] > 0.0
        ]
        probabilities_pruned = probabilities[probabilities > 0.0]

        # Stochastic model over all classifiers.
        probabilities_all = probabilities * 0.0 + 1.0 / len(probabilities)

        # Return Pruned models, Avg models, Best model
        results = {
            'stochastic': (models, probabilities_all),
            'pruned': (models_pruned, probabilities_pruned),
            'best': best_model,
            'objectives': objectives,
            'violations': violations
        }
        return results