Source code for holisticai.bias.mitigation.postprocessing.wasserstein_barycenters.transformer

import numpy as np
from holisticai.bias.mitigation.postprocessing.wasserstein_barycenters.algorithm import WassersteinBarycenterAlgorithm
from holisticai.utils.transformers.bias import BMPostprocessing as BMPost


[docs] class WassersteinBarycenter(BMPost): """ Fair Regression with Wasserstein Barycenters learning a real-valued function that\ satisfies the Demographic Parity constraint [1]_ . The strategy founds the optimal fair\ predictor computing the Wasserstein barycenter of the distributions induced by the\ standard regression function on the sensitive groups. Examples -------- >>> from holisticai.bias.mitigation import WassersteinBarycenter >>> mitigator = WassersteinBarycenter() >>> mitigator.fit_transform(y_pred, group_a, group_b) >>> test_data_transformed = mitigator.transform(y_pred, group_a, group_b) References ---------- .. [1] Chzhen, Evgenii, et al. "Fair regression with wasserstein barycenters."\ Advances in Neural Information Processing Systems 33 (2020): 7321-7331. """ def __init__(self): self.algorithm = WassersteinBarycenterAlgorithm()
[docs] def fit(self, y_pred: np.ndarray, group_a: np.ndarray, group_b: np.ndarray): """ Compute parameters for calibrated equalized odds. Description ---------- Compute parameters for calibrated equalized odds algorithm. Parameters ---------- y_pred : array-like Predicted vector (num_examples,). group_a : array-like Group membership vector (binary) group_b : array-like Group membership vector (binary) Returns ------- Self """ params = self._load_data(y_pred=y_pred, group_a=group_a, group_b=group_b) group_a = params["group_a"] == 1 group_b = params["group_b"] == 1 y_pred = params["y_pred"] sensitive_features = np.stack([group_a, group_b], axis=1) self.algorithm.fit(y_pred, sensitive_features) return self
[docs] def transform( self, y_pred: np.ndarray, group_a: np.ndarray, group_b: np.ndarray, ): """ Apply transform function to predictions and likelihoods Description ---------- Use a fitted probability to change the output label and invert the likelihood Parameters ---------- y_pred : array-like Predicted vector (nb_examples,) group_a : array-like Group membership vector (binary) group_b : array-like Group membership vector (binary) threshold : float float value to discriminate between 0 and 1 Returns ------- dict A dictionary with new predictions """ params = self._load_data(y_pred=y_pred, group_a=group_a, group_b=group_b) group_a = params["group_a"] == 1 group_b = params["group_b"] == 1 y_pred = params["y_pred"] sensitive_features = np.stack([group_a, group_b], axis=1) new_y_pred = self.algorithm.transform(y_pred, sensitive_features) return {"y_pred": new_y_pred}
[docs] def fit_transform(self, y_pred: np.ndarray, group_a: np.ndarray, group_b: np.ndarray): """ Fit and transform Description ---------- Fit and transform Parameters ---------- y_pred : array-like Predicted vector (num_examples,). group_a : array-like Group membership vector (binary) group_b : array-like Group membership vector (binary) Returns ------- dict A dictionary with new predictions """ return self.fit( y_pred, group_a, group_b, ).transform(y_pred, group_a, group_b)