Spaces:
Runtime error
Runtime error
| # The code for Meta-Classification-Algorithm is based on, the paper https://arxiv.org/abs/1806.06055 | |
| # See: https://github.com/vijaykeswani/FairClassification | |
| import numpy as np | |
| from aif360.algorithms import Transformer | |
| from aif360.algorithms.inprocessing.celisMeta import FalseDiscovery | |
| from aif360.algorithms.inprocessing.celisMeta import StatisticalRate | |
| class MetaFairClassifier(Transformer): | |
| """The meta algorithm here takes the fairness metric as part of the input | |
| and returns a classifier optimized w.r.t. that fairness metric [11]_. | |
| References: | |
| .. [11] L. E. Celis, L. Huang, V. Keswani, and N. K. Vishnoi. | |
| "Classification with Fairness Constraints: A Meta-Algorithm with | |
| Provable Guarantees," 2018. | |
| """ | |
| def __init__(self, tau=0.8, sensitive_attr="", type="fdr", seed=None): | |
| """ | |
| Args: | |
| tau (double, optional): Fairness penalty parameter. | |
| sensitive_attr (str, optional): Name of protected attribute. | |
| type (str, optional): The type of fairness metric to be used. | |
| Currently "fdr" (false discovery rate ratio) and "sr" | |
| (statistical rate/disparate impact) are supported. To use | |
| another type, the corresponding optimization class has to be | |
| implemented. | |
| seed (int, optional): Random seed. | |
| """ | |
| super(MetaFairClassifier, self).__init__(tau=tau, | |
| sensitive_attr=sensitive_attr, type=type, seed=seed) | |
| self.tau = tau | |
| self.sensitive_attr = sensitive_attr | |
| if type == "fdr": | |
| self.obj = FalseDiscovery() | |
| elif type == "sr": | |
| self.obj = StatisticalRate() | |
| else: | |
| raise NotImplementedError("Only 'fdr' and 'sr' are supported yet.") | |
| self.seed = seed | |
| def fit(self, dataset): | |
| """Learns the fair classifier. | |
| Args: | |
| dataset (BinaryLabelDataset): Dataset containing true labels. | |
| Returns: | |
| MetaFairClassifier: Returns self. | |
| """ | |
| if not self.sensitive_attr: | |
| self.sensitive_attr = dataset.protected_attribute_names[0] | |
| sens_idx = dataset.protected_attribute_names.index(self.sensitive_attr) | |
| x_train = dataset.features | |
| y_train = np.where(dataset.labels.flatten() == dataset.favorable_label, | |
| 1, -1) | |
| x_control_train = np.where( | |
| np.isin(dataset.protected_attributes[:, sens_idx], | |
| dataset.privileged_protected_attributes[sens_idx]), | |
| 1, 0) | |
| self.model = self.obj.getModel(self.tau, x_train, y_train, | |
| x_control_train, self.seed) | |
| return self | |
| def predict(self, dataset): | |
| """Obtain the predictions for the provided dataset using the learned | |
| classifier model. | |
| Args: | |
| dataset (BinaryLabelDataset): Dataset containing labels that needs | |
| to be transformed. | |
| Returns: | |
| BinaryLabelDataset: Transformed dataset. | |
| """ | |
| t = self.model(dataset.features) | |
| pred_dataset = dataset.copy() | |
| pred_dataset.labels = (t > 0).astype(int).reshape((-1, 1)) | |
| pred_dataset.scores = ((t + 1) / 2).reshape((-1, 1)) | |
| return pred_dataset | |