{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### This notebook demonstrates the use of adversarial debiasing algorithm to learn a fair classifier.\n",
    "Adversarial debiasing [1] is an in-processing technique that learns a classifier to maximize prediction accuracy and simultaneously reduce an adversary's ability to determine the protected attribute from the predictions. This approach leads to a fair classifier as the predictions cannot carry any group discrimination information that the adversary can exploit. We will see how to use this algorithm for learning models with and without fairness constraints and apply them on the Adult dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:root:No module named 'tempeh': LawSchoolGPADataset will be unavailable. To install, run:\n",
      "pip install 'aif360[LawSchoolGPA]'\n",
      "WARNING:root:No module named 'fairlearn': ExponentiatedGradientReduction will be unavailable. To install, run:\n",
      "pip install 'aif360[Reductions]'\n",
      "WARNING:root:No module named 'fairlearn': GridSearchReduction will be unavailable. To install, run:\n",
      "pip install 'aif360[Reductions]'\n",
      "WARNING:root:No module named 'fairlearn': GridSearchReduction will be unavailable. To install, run:\n",
      "pip install 'aif360[Reductions]'\n"
     ]
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "# Load all necessary packages\n",
    "import sys\n",
    "sys.path.append(\"../\")\n",
    "from aif360.datasets import BinaryLabelDataset\n",
    "from aif360.datasets import AdultDataset, GermanDataset, CompasDataset\n",
    "from aif360.metrics import BinaryLabelDatasetMetric\n",
    "from aif360.metrics import ClassificationMetric\n",
    "from aif360.metrics.utils import compute_boolean_conditioning_vector\n",
    "\n",
    "from aif360.algorithms.preprocessing.optim_preproc_helpers.data_preproc_functions import load_preproc_data_adult, load_preproc_data_compas, load_preproc_data_german\n",
    "\n",
    "from aif360.algorithms.inprocessing.adversarial_debiasing import AdversarialDebiasing\n",
    "\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.preprocessing import StandardScaler, MaxAbsScaler\n",
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "from IPython.display import Markdown, display\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "import tensorflow.compat.v1 as tf\n",
    "tf.disable_eager_execution()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Load dataset and set options"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Get the dataset and split into train and test\n",
    "dataset_orig = load_preproc_data_adult()\n",
    "\n",
    "privileged_groups = [{'sex': 1}]\n",
    "unprivileged_groups = [{'sex': 0}]\n",
    "\n",
    "dataset_orig_train, dataset_orig_test = dataset_orig.split([0.7], shuffle=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "dataset_orig = GermanDataset()\n",
    "privileged_groups = [{'sex': 1}]\n",
    "unprivileged_groups = [{'sex': 0}]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "dataset_orig_train, dataset_orig_test = dataset_orig.split([0.7], shuffle=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Metric for original training data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Learn plan classifier without debiasing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load post-processing algorithm that equalizes the odds\n",
    "# Learn parameters with debias set to False\n",
    "sess = tf.Session()\n",
    "plain_model = AdversarialDebiasing(privileged_groups = privileged_groups,\n",
    "                          unprivileged_groups = unprivileged_groups,\n",
    "                          scope_name='plain_classifier',\n",
    "                          debias=False,\n",
    "                          sess=sess)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<aif360.algorithms.inprocessing.adversarial_debiasing.AdversarialDebiasing at 0x2980327c608>"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "plain_model.fit(dataset_orig_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Apply the plain model to test data\n",
    "dataset_nodebiasing_train = plain_model.predict(dataset_orig_train)\n",
    "dataset_nodebiasing_test = plain_model.predict(dataset_orig_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "#### Plain model - without debiasing - dataset metrics"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train set: Difference in mean outcomes between unprivileged and privileged groups = -0.206838\n",
      "Test set: Difference in mean outcomes between unprivileged and privileged groups = -0.205994\n"
     ]
    },
    {
     "data": {
      "text/markdown": [
       "#### Plain model - without debiasing - classification metrics"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set: Classification accuracy = 0.804886\n",
      "Test set: Balanced classification accuracy = 0.659419\n",
      "Test set: Disparate impact = 0.000000\n",
      "Test set: Equal opportunity difference = -0.447686\n",
      "Test set: Average odds difference = -0.273806\n",
      "Test set: Theil_index = 0.179642\n"
     ]
    }
   ],
   "source": [
    "# Metrics for the dataset from plain model (without debiasing)\n",
    "display(Markdown(\"#### Plain model - without debiasing - dataset metrics\"))\n",
    "metric_dataset_nodebiasing_train = BinaryLabelDatasetMetric(dataset_nodebiasing_train, \n",
    "                                             unprivileged_groups=unprivileged_groups,\n",
    "                                             privileged_groups=privileged_groups)\n",
    "\n",
    "print(\"Train set: Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_dataset_nodebiasing_train.mean_difference())\n",
    "\n",
    "metric_dataset_nodebiasing_test = BinaryLabelDatasetMetric(dataset_nodebiasing_test, \n",
    "                                             unprivileged_groups=unprivileged_groups,\n",
    "                                             privileged_groups=privileged_groups)\n",
    "\n",
    "print(\"Test set: Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_dataset_nodebiasing_test.mean_difference())\n",
    "\n",
    "display(Markdown(\"#### Plain model - without debiasing - classification metrics\"))\n",
    "classified_metric_nodebiasing_test = ClassificationMetric(dataset_orig_test, \n",
    "                                                 dataset_nodebiasing_test,\n",
    "                                                 unprivileged_groups=unprivileged_groups,\n",
    "                                                 privileged_groups=privileged_groups)\n",
    "print(\"Test set: Classification accuracy = %f\" % classified_metric_nodebiasing_test.accuracy())\n",
    "TPR = classified_metric_nodebiasing_test.true_positive_rate()\n",
    "TNR = classified_metric_nodebiasing_test.true_negative_rate()\n",
    "bal_acc_nodebiasing_test = 0.5*(TPR+TNR)\n",
    "print(\"Test set: Balanced classification accuracy = %f\" % bal_acc_nodebiasing_test)\n",
    "print(\"Test set: Disparate impact = %f\" % classified_metric_nodebiasing_test.disparate_impact())\n",
    "print(\"Test set: Equal opportunity difference = %f\" % classified_metric_nodebiasing_test.equal_opportunity_difference())\n",
    "print(\"Test set: Average odds difference = %f\" % classified_metric_nodebiasing_test.average_odds_difference())\n",
    "print(\"Test set: Theil_index = %f\" % classified_metric_nodebiasing_test.theil_index())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Apply in-processing algorithm based on adversarial learning"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "sess.close()\n",
    "tf.reset_default_graph()\n",
    "sess = tf.Session()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Learn parameters with debias set to True\n",
    "debiased_model = AdversarialDebiasing(privileged_groups = privileged_groups,\n",
    "                          unprivileged_groups = unprivileged_groups,\n",
    "                          scope_name='debiased_classifier',\n",
    "                          debias=True,\n",
    "                          sess=sess)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 0; iter: 0; batch classifier loss: 0.630446; batch adversarial loss: 0.700471\n",
      "epoch 1; iter: 0; batch classifier loss: 0.586666; batch adversarial loss: 0.663528\n",
      "epoch 2; iter: 0; batch classifier loss: 0.535873; batch adversarial loss: 0.680876\n",
      "epoch 3; iter: 0; batch classifier loss: 0.629068; batch adversarial loss: 0.690611\n",
      "epoch 4; iter: 0; batch classifier loss: 0.604589; batch adversarial loss: 0.641804\n",
      "epoch 5; iter: 0; batch classifier loss: 0.546016; batch adversarial loss: 0.682053\n",
      "epoch 6; iter: 0; batch classifier loss: 0.551893; batch adversarial loss: 0.669567\n",
      "epoch 7; iter: 0; batch classifier loss: 0.515059; batch adversarial loss: 0.647458\n",
      "epoch 8; iter: 0; batch classifier loss: 0.466134; batch adversarial loss: 0.730296\n",
      "epoch 9; iter: 0; batch classifier loss: 0.483293; batch adversarial loss: 0.670743\n",
      "epoch 10; iter: 0; batch classifier loss: 0.487542; batch adversarial loss: 0.709081\n",
      "epoch 11; iter: 0; batch classifier loss: 0.525901; batch adversarial loss: 0.714729\n",
      "epoch 12; iter: 0; batch classifier loss: 0.442926; batch adversarial loss: 0.705642\n",
      "epoch 13; iter: 0; batch classifier loss: 0.407617; batch adversarial loss: 0.652541\n",
      "epoch 14; iter: 0; batch classifier loss: 0.447342; batch adversarial loss: 0.647065\n",
      "epoch 15; iter: 0; batch classifier loss: 0.407173; batch adversarial loss: 0.646382\n",
      "epoch 16; iter: 0; batch classifier loss: 0.436664; batch adversarial loss: 0.675747\n",
      "epoch 17; iter: 0; batch classifier loss: 0.509779; batch adversarial loss: 0.702110\n",
      "epoch 18; iter: 0; batch classifier loss: 0.390341; batch adversarial loss: 0.674433\n",
      "epoch 19; iter: 0; batch classifier loss: 0.472428; batch adversarial loss: 0.686929\n",
      "epoch 20; iter: 0; batch classifier loss: 0.483605; batch adversarial loss: 0.680061\n",
      "epoch 21; iter: 0; batch classifier loss: 0.402752; batch adversarial loss: 0.662552\n",
      "epoch 22; iter: 0; batch classifier loss: 0.360346; batch adversarial loss: 0.655891\n",
      "epoch 23; iter: 0; batch classifier loss: 0.470331; batch adversarial loss: 0.648024\n",
      "epoch 24; iter: 0; batch classifier loss: 0.413358; batch adversarial loss: 0.651251\n",
      "epoch 25; iter: 0; batch classifier loss: 0.434989; batch adversarial loss: 0.649641\n",
      "epoch 26; iter: 0; batch classifier loss: 0.401547; batch adversarial loss: 0.706715\n",
      "epoch 27; iter: 0; batch classifier loss: 0.368419; batch adversarial loss: 0.634777\n",
      "epoch 28; iter: 0; batch classifier loss: 0.411040; batch adversarial loss: 0.679842\n",
      "epoch 29; iter: 0; batch classifier loss: 0.423878; batch adversarial loss: 0.676335\n",
      "epoch 30; iter: 0; batch classifier loss: 0.445241; batch adversarial loss: 0.687283\n",
      "epoch 31; iter: 0; batch classifier loss: 0.407777; batch adversarial loss: 0.647523\n",
      "epoch 32; iter: 0; batch classifier loss: 0.417895; batch adversarial loss: 0.658208\n",
      "epoch 33; iter: 0; batch classifier loss: 0.419258; batch adversarial loss: 0.669278\n",
      "epoch 34; iter: 0; batch classifier loss: 0.349670; batch adversarial loss: 0.626954\n",
      "epoch 35; iter: 0; batch classifier loss: 0.417532; batch adversarial loss: 0.664921\n",
      "epoch 36; iter: 0; batch classifier loss: 0.436573; batch adversarial loss: 0.668980\n",
      "epoch 37; iter: 0; batch classifier loss: 0.417203; batch adversarial loss: 0.675834\n",
      "epoch 38; iter: 0; batch classifier loss: 0.424453; batch adversarial loss: 0.708492\n",
      "epoch 39; iter: 0; batch classifier loss: 0.380485; batch adversarial loss: 0.641966\n",
      "epoch 40; iter: 0; batch classifier loss: 0.338319; batch adversarial loss: 0.665219\n",
      "epoch 41; iter: 0; batch classifier loss: 0.415096; batch adversarial loss: 0.700641\n",
      "epoch 42; iter: 0; batch classifier loss: 0.375992; batch adversarial loss: 0.668136\n",
      "epoch 43; iter: 0; batch classifier loss: 0.392031; batch adversarial loss: 0.659302\n",
      "epoch 44; iter: 0; batch classifier loss: 0.322770; batch adversarial loss: 0.637700\n",
      "epoch 45; iter: 0; batch classifier loss: 0.370554; batch adversarial loss: 0.640240\n",
      "epoch 46; iter: 0; batch classifier loss: 0.371171; batch adversarial loss: 0.651408\n",
      "epoch 47; iter: 0; batch classifier loss: 0.398021; batch adversarial loss: 0.674123\n",
      "epoch 48; iter: 0; batch classifier loss: 0.368332; batch adversarial loss: 0.627480\n",
      "epoch 49; iter: 0; batch classifier loss: 0.390744; batch adversarial loss: 0.632890\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<aif360.algorithms.inprocessing.adversarial_debiasing.AdversarialDebiasing at 0x17f4393bbc8>"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "debiased_model.fit(dataset_orig_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Apply the plain model to test data\n",
    "dataset_debiasing_train = debiased_model.predict(dataset_orig_train)\n",
    "dataset_debiasing_test = debiased_model.predict(dataset_orig_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "#### Plain model - without debiasing - dataset metrics"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train set: Difference in mean outcomes between unprivileged and privileged groups = -0.206838\n",
      "Test set: Difference in mean outcomes between unprivileged and privileged groups = -0.205994\n"
     ]
    },
    {
     "data": {
      "text/markdown": [
       "#### Model - with debiasing - dataset metrics"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train set: Difference in mean outcomes between unprivileged and privileged groups = -0.357143\n",
      "Test set: Difference in mean outcomes between unprivileged and privileged groups = -0.417006\n"
     ]
    },
    {
     "data": {
      "text/markdown": [
       "#### Plain model - without debiasing - classification metrics"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set: Classification accuracy = 0.804886\n",
      "Test set: Balanced classification accuracy = 0.659419\n",
      "Test set: Disparate impact = 0.000000\n",
      "Test set: Equal opportunity difference = -0.447686\n",
      "Test set: Average odds difference = -0.273806\n",
      "Test set: Theil_index = 0.179642\n"
     ]
    },
    {
     "data": {
      "text/markdown": [
       "#### Model - with debiasing - classification metrics"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set: Classification accuracy = 0.785000\n",
      "Test set: Balanced classification accuracy = 0.665517\n",
      "Test set: Disparate impact = 0.573444\n",
      "Test set: Equal opportunity difference = -0.209897\n",
      "Test set: Average odds difference = -0.471615\n",
      "Test set: Theil_index = 0.096292\n"
     ]
    }
   ],
   "source": [
    "# Metrics for the dataset from plain model (without debiasing)\n",
    "display(Markdown(\"#### Plain model - without debiasing - dataset metrics\"))\n",
    "print(\"Train set: Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_dataset_nodebiasing_train.mean_difference())\n",
    "print(\"Test set: Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_dataset_nodebiasing_test.mean_difference())\n",
    "\n",
    "# Metrics for the dataset from model with debiasing\n",
    "display(Markdown(\"#### Model - with debiasing - dataset metrics\"))\n",
    "metric_dataset_debiasing_train = BinaryLabelDatasetMetric(dataset_debiasing_train, \n",
    "                                             unprivileged_groups=unprivileged_groups,\n",
    "                                             privileged_groups=privileged_groups)\n",
    "\n",
    "print(\"Train set: Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_dataset_debiasing_train.mean_difference())\n",
    "\n",
    "metric_dataset_debiasing_test = BinaryLabelDatasetMetric(dataset_debiasing_test, \n",
    "                                             unprivileged_groups=unprivileged_groups,\n",
    "                                             privileged_groups=privileged_groups)\n",
    "\n",
    "print(\"Test set: Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_dataset_debiasing_test.mean_difference())\n",
    "\n",
    "\n",
    "\n",
    "display(Markdown(\"#### Plain model - without debiasing - classification metrics\"))\n",
    "print(\"Test set: Classification accuracy = %f\" % classified_metric_nodebiasing_test.accuracy())\n",
    "TPR = classified_metric_nodebiasing_test.true_positive_rate()\n",
    "TNR = classified_metric_nodebiasing_test.true_negative_rate()\n",
    "bal_acc_nodebiasing_test = 0.5*(TPR+TNR)\n",
    "print(\"Test set: Balanced classification accuracy = %f\" % bal_acc_nodebiasing_test)\n",
    "print(\"Test set: Disparate impact = %f\" % classified_metric_nodebiasing_test.disparate_impact())\n",
    "print(\"Test set: Equal opportunity difference = %f\" % classified_metric_nodebiasing_test.equal_opportunity_difference())\n",
    "print(\"Test set: Average odds difference = %f\" % classified_metric_nodebiasing_test.average_odds_difference())\n",
    "print(\"Test set: Theil_index = %f\" % classified_metric_nodebiasing_test.theil_index())\n",
    "\n",
    "\n",
    "\n",
    "display(Markdown(\"#### Model - with debiasing - classification metrics\"))\n",
    "classified_metric_debiasing_test = ClassificationMetric(dataset_orig_test, \n",
    "                                                 dataset_debiasing_test,\n",
    "                                                 unprivileged_groups=unprivileged_groups,\n",
    "                                                 privileged_groups=privileged_groups)\n",
    "print(\"Test set: Classification accuracy = %f\" % classified_metric_debiasing_test.accuracy())\n",
    "TPR = classified_metric_debiasing_test.true_positive_rate()\n",
    "TNR = classified_metric_debiasing_test.true_negative_rate()\n",
    "bal_acc_debiasing_test = 0.5*(TPR+TNR)\n",
    "print(\"Test set: Balanced classification accuracy = %f\" % bal_acc_debiasing_test)\n",
    "print(\"Test set: Disparate impact = %f\" % classified_metric_debiasing_test.disparate_impact())\n",
    "print(\"Test set: Equal opportunity difference = %f\" % classified_metric_debiasing_test.equal_opportunity_difference())\n",
    "print(\"Test set: Average odds difference = %f\" % classified_metric_debiasing_test.average_odds_difference())\n",
    "print(\"Test set: Theil_index = %f\" % classified_metric_debiasing_test.theil_index())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tqdm import tqdm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "    References:\n",
    "    [1] B. H. Zhang, B. Lemoine, and M. Mitchell, \"Mitigating UnwantedBiases with Adversarial Learning,\" \n",
    "    AAAI/ACM Conference on Artificial Intelligence, Ethics, and Society, 2018."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 100/100 [01:31<00:00,  1.09it/s]\n"
     ]
    }
   ],
   "source": [
    "DEOO_fin = []\n",
    "DPE_fin = []\n",
    "mis_fin = []\n",
    "sigma = 1\n",
    "for step in tqdm(range(100)):\n",
    "    mu_00 = 3 * np.random.rand(1)\n",
    "    mu_01 = np.random.rand(1)\n",
    "    mu_10 = np.random.rand(1)\n",
    "    mu_11 = np.random.rand(1)\n",
    "    for i in range(1000):\n",
    "        if(dataset_orig.labels[i] == 2 and dataset_orig.features[:,7][i] == 0):\n",
    "            #z = np.random.normal(mu_00, sigma, 57)\n",
    "            #z = np.random.chisquare(2,57)\n",
    "            z = np.random.standard_t(3, 57)\n",
    "            for j in range(7):\n",
    "                dataset_orig.features[i][j] = z[j]\n",
    "            for j in range(8, 58):\n",
    "                dataset_orig.features[i][j] = z[j - 1]\n",
    "        elif(dataset_orig.labels[i] == 2 and dataset_orig.features[:,7][i] == 1):\n",
    "            #z = np.random.normal(mu_01, sigma, 57)\n",
    "            #z = np.random.standard_t(4, 57)\n",
    "            z = np.random.chisquare(1,57)\n",
    "            for j in range(7):\n",
    "                dataset_orig.features[i][j] = z[j]\n",
    "            for j in range(8, 58):\n",
    "                dataset_orig.features[i][j] = z[j - 1]\n",
    "        elif(dataset_orig.labels[i] == 1 and dataset_orig.features[:,7][i] == 0):\n",
    "            #z = np.random.normal(mu_10, sigma, 57)\\\n",
    "            z = np.random.chisquare(3,57)\n",
    "            for j in range(7):\n",
    "                dataset_orig.features[i][j] = z[j]\n",
    "            for j in range(8, 58):\n",
    "                dataset_orig.features[i][j] = z[j - 1]\n",
    "        else:\n",
    "            z = np.random.normal(mu_11, sigma, 57)\n",
    "            #z = np.random.chisquare(1,57)\n",
    "            #z = np.random.laplace(mu_11, sigma, 57)\n",
    "            for j in range(7):\n",
    "                dataset_orig.features[i][j] = z[j]\n",
    "            for j in range(8, 58):\n",
    "                dataset_orig.features[i][j] = z[j - 1]\n",
    "    randseed = np.random.randint(10000)\n",
    "    dataset_orig_train, dataset_orig_vt = dataset_orig.split([0.6], shuffle=True, seed = np.random.randint(0, 10000))\n",
    "    dataset_orig_valid, dataset_orig_test = dataset_orig_vt.split([0.5], shuffle=True, seed = np.random.randint(0, 10000))\n",
    "    # Placeholder for predicted and transformed datasets\n",
    "    dataset_orig_train_pred = dataset_orig_train.copy(deepcopy=True)\n",
    "    dataset_orig_valid_pred = dataset_orig_valid.copy(deepcopy=True)\n",
    "    dataset_orig_test_pred = dataset_orig_test.copy(deepcopy=True)\n",
    "\n",
    "    dataset_new_valid_pred = dataset_orig_valid.copy(deepcopy=True)\n",
    "    dataset_new_test_pred = dataset_orig_test.copy(deepcopy=True)\n",
    "\n",
    "    y_test = dataset_orig_test.labels.ravel()\n",
    "\n",
    "    sess.close()\n",
    "    tf.reset_default_graph()\n",
    "    sess = tf.Session()\n",
    "    # Learn parameters with debias set to True\n",
    "    debiased_model = AdversarialDebiasing(privileged_groups = privileged_groups,\n",
    "                          unprivileged_groups = unprivileged_groups,\n",
    "                          scope_name='debiased_classifier',\n",
    "                          debias=True,\n",
    "                          sess=sess)\n",
    "    debiased_model.fit(dataset_orig_train)\n",
    "    dataset_debiasing_train = debiased_model.predict(dataset_orig_train)\n",
    "    dataset_debiasing_test = debiased_model.predict(dataset_orig_test)\n",
    "\n",
    "    eq = 0\n",
    "    for i in range(len(y_test)):\n",
    "        if(dataset_debiasing_test.labels.ravel()[i] == y_test[i]):\n",
    "            eq += 1\n",
    "    mis_fin.append(eq / len(y_test))\n",
    "    n_10 = 0\n",
    "    n_11 = 0\n",
    "    c_10 = 0\n",
    "    c_11 = 0\n",
    "    for i in range(len(y_test)):\n",
    "        if(y_test[i] == 1 and dataset_debiasing_test.protected_attributes[:,1][i] == 0):\n",
    "            n_10 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_10 += 1\n",
    "        elif(y_test[i] == 1 and dataset_debiasing_test.protected_attributes[:,1][i] == 1):\n",
    "            n_11 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_11 += 1\n",
    "    DEOO_fin.append(c_10 / n_10 - c_11 / n_11)\n",
    "    n_00 = 0\n",
    "    n_01 = 0\n",
    "    c_00 = 0\n",
    "    c_01 = 0\n",
    "    for i in range(len(y_test)):\n",
    "        if(y_test[i] == 2 and dataset_debiasing_test.protected_attributes[:,1][i] == 0):\n",
    "            n_00 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_00 += 1\n",
    "        elif(y_test[i] == 2 and dataset_debiasing_test.protected_attributes[:,1][i] == 1):\n",
    "            n_01 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_01 += 1\n",
    "    DPE_fin.append(c_00 / n_00 - c_01 / n_01)\n",
    "DEOO_fin = np.array(DEOO_fin)\n",
    "DPE_fin = np.array(DPE_fin)\n",
    "mis_fin = np.array(mis_fin)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 50/50 [19:55<00:00, 23.91s/it]\n"
     ]
    }
   ],
   "source": [
    "DEOO_fin = []\n",
    "DPE_fin = []\n",
    "mis_fin = []\n",
    "sigma = 1\n",
    "for step in tqdm(range(50)):\n",
    "    randseed = np.random.randint(10000)\n",
    "    dataset_orig_train, dataset_orig_vt = dataset_orig.split([0.6], shuffle=True, seed = np.random.randint(0, 10000))\n",
    "    dataset_orig_valid, dataset_orig_test = dataset_orig_vt.split([0.5], shuffle=True, seed = np.random.randint(0, 10000))\n",
    "    # Placeholder for predicted and transformed datasets\n",
    "    dataset_orig_train_pred = dataset_orig_train.copy(deepcopy=True)\n",
    "    dataset_orig_valid_pred = dataset_orig_valid.copy(deepcopy=True)\n",
    "    dataset_orig_test_pred = dataset_orig_test.copy(deepcopy=True)\n",
    "\n",
    "    dataset_new_valid_pred = dataset_orig_valid.copy(deepcopy=True)\n",
    "    dataset_new_test_pred = dataset_orig_test.copy(deepcopy=True)\n",
    "\n",
    "    y_test = dataset_orig_test.labels.ravel()\n",
    "\n",
    "    sess.close()\n",
    "    tf.reset_default_graph()\n",
    "    sess = tf.Session()\n",
    "    # Learn parameters with debias set to True\n",
    "    debiased_model = AdversarialDebiasing(privileged_groups = privileged_groups,\n",
    "                          unprivileged_groups = unprivileged_groups,\n",
    "                          scope_name='debiased_classifier',\n",
    "                          debias=True,\n",
    "                          sess=sess)\n",
    "    debiased_model.fit(dataset_orig_train)\n",
    "    dataset_debiasing_train = debiased_model.predict(dataset_orig_train)\n",
    "    dataset_debiasing_test = debiased_model.predict(dataset_orig_test)\n",
    "\n",
    "    eq = 0\n",
    "    for i in range(len(y_test)):\n",
    "        if(dataset_debiasing_test.labels.ravel()[i] == y_test[i]):\n",
    "            eq += 1\n",
    "    mis_fin.append(eq / len(y_test))\n",
    "    n_10 = 0\n",
    "    n_11 = 0\n",
    "    c_10 = 0\n",
    "    c_11 = 0\n",
    "    for i in range(len(y_test)):\n",
    "        if(y_test[i] == 1 and dataset_debiasing_test.protected_attributes[:,1][i] == 0):\n",
    "            n_10 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_10 += 1\n",
    "        elif(y_test[i] == 1 and dataset_debiasing_test.protected_attributes[:,1][i] == 1):\n",
    "            n_11 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_11 += 1\n",
    "    DEOO_fin.append(c_10 / n_10 - c_11 / n_11)\n",
    "    n_00 = 0\n",
    "    n_01 = 0\n",
    "    c_00 = 0\n",
    "    c_01 = 0\n",
    "    for i in range(len(y_test)):\n",
    "        if(y_test[i] == 0 and dataset_debiasing_test.protected_attributes[:,1][i] == 0):\n",
    "            n_00 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_00 += 1\n",
    "        elif(y_test[i] == 0 and dataset_debiasing_test.protected_attributes[:,1][i] == 1):\n",
    "            n_01 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_01 += 1\n",
    "    DPE_fin.append(c_00 / n_00 - c_01 / n_01)\n",
    "DEOO_fin = np.array(DEOO_fin)\n",
    "DPE_fin = np.array(DPE_fin)\n",
    "mis_fin = np.array(mis_fin)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.19856798163069647\n",
      "0.07359700484280035\n",
      "0.7908649810625447\n",
      "0.7970774900194493\n",
      "0.2475582826018601\n",
      "0.09365073689999337\n"
     ]
    }
   ],
   "source": [
    "print(np.mean(abs(DEOO_fin)))\n",
    "print(np.mean(abs(DPE_fin)))\n",
    "print(np.mean(mis_fin))\n",
    "print(np.percentile(mis_fin, 95))\n",
    "print(np.percentile(abs(DEOO_fin), 95))\n",
    "print(np.percentile(abs(DPE_fin), 95))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.7.13 ('aif360')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.13"
  },
  "vscode": {
   "interpreter": {
    "hash": "d27cd899c2aad711dbfe864d87d8e4a3aa2aa47421b84ce5060d18007824eabc"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
