diff --git a/examples/sklearn/demo_exponentiated_gradient_reduction_sklearn.ipynb b/examples/sklearn/demo_exponentiated_gradient_reduction_sklearn.ipynb
index a3aa01c7..15d39401 100644
--- a/examples/sklearn/demo_exponentiated_gradient_reduction_sklearn.ipynb
+++ b/examples/sklearn/demo_exponentiated_gradient_reduction_sklearn.ipynb
@@ -1,997 +1,1753 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Sklearn compatible Exponentiated Gradient Reduction\n",
- "\n",
- "Exponentiated gradient reduction is an in-processing technique that reduces fair classification to a sequence of cost-sensitive classification problems, returning a randomized classifier with the lowest empirical error subject to \n",
- "fair classification constraints. The code for exponentiated gradient reduction wraps the source class \n",
- "`fairlearn.reductions.ExponentiatedGradient` available in the https://github.com/fairlearn/fairlearn library,\n",
- "licensed under the MIT Licencse, Copyright Microsoft Corporation."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [],
- "source": [
- "import warnings\n",
- "warnings.filterwarnings(\"ignore\", category=FutureWarning)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "\n",
- "from sklearn.compose import make_column_transformer\n",
- "from sklearn.linear_model import LogisticRegression\n",
- "from sklearn.metrics import accuracy_score\n",
- "from sklearn.model_selection import train_test_split\n",
- "from sklearn.preprocessing import OneHotEncoder\n",
- "\n",
- "from aif360.sklearn.inprocessing import ExponentiatedGradientReduction\n",
- "\n",
- "from aif360.sklearn.datasets import fetch_adult\n",
- "from aif360.sklearn.metrics import average_odds_error"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Loading data"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Datasets are formatted as separate `X` (# samples x # features) and `y` (# samples x # labels) DataFrames. The index of each DataFrame contains protected attribute values per sample. Datasets may also load a `sample_weight` object to be used with certain algorithms/metrics. All of this makes it so that aif360 is compatible with scikit-learn objects.\n",
- "\n",
- "For example, we can easily load the Adult dataset from UCI with the following line:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " | \n",
- " age | \n",
- " workclass | \n",
- " education | \n",
- " education-num | \n",
- " marital-status | \n",
- " occupation | \n",
- " relationship | \n",
- " race | \n",
- " sex | \n",
- " capital-gain | \n",
- " capital-loss | \n",
- " hours-per-week | \n",
- " native-country | \n",
- "
\n",
- " \n",
- " | race | \n",
- " sex | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " | Non-white | \n",
- " Male | \n",
- " 25.0 | \n",
- " Private | \n",
- " 11th | \n",
- " 7.0 | \n",
- " Never-married | \n",
- " Machine-op-inspct | \n",
- " Own-child | \n",
- " Black | \n",
- " Male | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 40.0 | \n",
- " United-States | \n",
- "
\n",
- " \n",
- " | White | \n",
- " Male | \n",
- " 38.0 | \n",
- " Private | \n",
- " HS-grad | \n",
- " 9.0 | \n",
- " Married-civ-spouse | \n",
- " Farming-fishing | \n",
- " Husband | \n",
- " White | \n",
- " Male | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 50.0 | \n",
- " United-States | \n",
- "
\n",
- " \n",
- " | Male | \n",
- " 28.0 | \n",
- " Local-gov | \n",
- " Assoc-acdm | \n",
- " 12.0 | \n",
- " Married-civ-spouse | \n",
- " Protective-serv | \n",
- " Husband | \n",
- " White | \n",
- " Male | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 40.0 | \n",
- " United-States | \n",
- "
\n",
- " \n",
- " | Non-white | \n",
- " Male | \n",
- " 44.0 | \n",
- " Private | \n",
- " Some-college | \n",
- " 10.0 | \n",
- " Married-civ-spouse | \n",
- " Machine-op-inspct | \n",
- " Husband | \n",
- " Black | \n",
- " Male | \n",
- " 7688.0 | \n",
- " 0.0 | \n",
- " 40.0 | \n",
- " United-States | \n",
- "
\n",
- " \n",
- " | White | \n",
- " Male | \n",
- " 34.0 | \n",
- " Private | \n",
- " 10th | \n",
- " 6.0 | \n",
- " Never-married | \n",
- " Other-service | \n",
- " Not-in-family | \n",
- " White | \n",
- " Male | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 30.0 | \n",
- " United-States | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "9qpCIiFt_Skq"
+ },
+ "source": [
+ "# Sklearn compatible Exponentiated Gradient Reduction\n",
+ "\n",
+ "Exponentiated gradient reduction is an in-processing technique that reduces fair classification to a sequence of cost-sensitive classification problems, returning a randomized classifier with the lowest empirical error subject to\n",
+ "fair classification constraints. The code for exponentiated gradient reduction wraps the source class\n",
+ "`fairlearn.reductions.ExponentiatedGradient` available in the https://github.com/fairlearn/fairlearn library,\n",
+ "licensed under the MIT Licencse, Copyright Microsoft Corporation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {
+ "id": "0fYDXGmE_Sks"
+ },
+ "outputs": [],
+ "source": [
+ "import warnings\n",
+ "warnings.filterwarnings(\"ignore\", category=FutureWarning)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "!pip install aif360[all]"
],
- "text/plain": [
- " age workclass education education-num \\\n",
- "race sex \n",
- "Non-white Male 25.0 Private 11th 7.0 \n",
- "White Male 38.0 Private HS-grad 9.0 \n",
- " Male 28.0 Local-gov Assoc-acdm 12.0 \n",
- "Non-white Male 44.0 Private Some-college 10.0 \n",
- "White Male 34.0 Private 10th 6.0 \n",
- "\n",
- " marital-status occupation relationship race \\\n",
- "race sex \n",
- "Non-white Male Never-married Machine-op-inspct Own-child Black \n",
- "White Male Married-civ-spouse Farming-fishing Husband White \n",
- " Male Married-civ-spouse Protective-serv Husband White \n",
- "Non-white Male Married-civ-spouse Machine-op-inspct Husband Black \n",
- "White Male Never-married Other-service Not-in-family White \n",
- "\n",
- " sex capital-gain capital-loss hours-per-week \\\n",
- "race sex \n",
- "Non-white Male Male 0.0 0.0 40.0 \n",
- "White Male Male 0.0 0.0 50.0 \n",
- " Male Male 0.0 0.0 40.0 \n",
- "Non-white Male Male 7688.0 0.0 40.0 \n",
- "White Male Male 0.0 0.0 30.0 \n",
- "\n",
- " native-country \n",
- "race sex \n",
- "Non-white Male United-States \n",
- "White Male United-States \n",
- " Male United-States \n",
- "Non-white Male United-States \n",
- "White Male United-States "
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "X, y, sample_weight = fetch_adult()\n",
- "X.head()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To match the old version, we also remap the \"race\" feature to \"White\"/\"Non-white\","
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [],
- "source": [
- "X.race = X.race.cat.set_categories(['Non-white', 'White'], ordered=True).fillna('Non-white')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can then map the protected attributes to integers,"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [],
- "source": [
- "X.index = pd.MultiIndex.from_arrays(X.index.codes, names=X.index.names)\n",
- "y.index = pd.MultiIndex.from_arrays(y.index.codes, names=y.index.names)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "and the target classes to 0/1,"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [],
- "source": [
- "y = pd.Series(y.factorize(sort=True)[0], index=y.index)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "split the dataset,"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [],
- "source": [
- "(X_train, X_test,\n",
- " y_train, y_test) = train_test_split(X, y, train_size=0.7, random_state=1234567)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We use sklearn for one-hot encoding for easy reference to columns associated with protected attributes, information necessary for Exponentiated Gradient Reduction"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " | \n",
- " workclass_Federal-gov | \n",
- " workclass_Local-gov | \n",
- " workclass_Private | \n",
- " workclass_Self-emp-inc | \n",
- " workclass_Self-emp-not-inc | \n",
- " workclass_State-gov | \n",
- " workclass_Without-pay | \n",
- " education_10th | \n",
- " education_11th | \n",
- " education_12th | \n",
- " ... | \n",
- " native-country_Thailand | \n",
- " native-country_Trinadad&Tobago | \n",
- " native-country_United-States | \n",
- " native-country_Vietnam | \n",
- " native-country_Yugoslavia | \n",
- " age | \n",
- " education-num | \n",
- " capital-gain | \n",
- " capital-loss | \n",
- " hours-per-week | \n",
- "
\n",
- " \n",
- " | race | \n",
- " sex | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " | 1 | \n",
- " 1 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 1.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " ... | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 1.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 58.0 | \n",
- " 11.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 42.0 | \n",
- "
\n",
- " \n",
- " | 0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 1.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " ... | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 51.0 | \n",
- " 12.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 30.0 | \n",
- "
\n",
- " \n",
- " | 1 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 1.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " ... | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 1.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 26.0 | \n",
- " 14.0 | \n",
- " 0.0 | \n",
- " 1887.0 | \n",
- " 40.0 | \n",
- "
\n",
- " \n",
- " | 1 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 1.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " ... | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 44.0 | \n",
- " 3.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 40.0 | \n",
- "
\n",
- " \n",
- " | 1 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 1.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 1.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " ... | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 1.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 33.0 | \n",
- " 6.0 | \n",
- " 0.0 | \n",
- " 0.0 | \n",
- " 40.0 | \n",
- "
\n",
- " \n",
- "
\n",
- "
5 rows × 100 columns
\n",
- "
"
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "2dEm6DiT_Vd5",
+ "outputId": "65d6cdc5-a3e5-4ef8-9e29-d1ead6cadff6"
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Requirement already satisfied: aif360[all] in /usr/local/lib/python3.10/dist-packages (0.5.0)\n",
+ "Requirement already satisfied: numpy>=1.16 in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (1.23.5)\n",
+ "Requirement already satisfied: scipy>=1.2.0 in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (1.11.2)\n",
+ "Requirement already satisfied: pandas>=0.24.0 in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (1.5.3)\n",
+ "Requirement already satisfied: scikit-learn>=1.0 in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (1.1.3)\n",
+ "Requirement already satisfied: matplotlib in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (3.7.1)\n",
+ "Requirement already satisfied: seaborn in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (0.12.2)\n",
+ "Requirement already satisfied: jinja2<3.1.0 in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (3.0.3)\n",
+ "Requirement already satisfied: ipympl in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (0.9.3)\n",
+ "Requirement already satisfied: adversarial-robustness-toolbox>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (1.16.0)\n",
+ "Requirement already satisfied: pytest>=3.5 in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (7.4.1)\n",
+ "Requirement already satisfied: torch in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (2.0.1+cu118)\n",
+ "Requirement already satisfied: BlackBoxAuditing in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (0.1.54)\n",
+ "Requirement already satisfied: tensorflow>=1.13.1 in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (2.13.0)\n",
+ "Requirement already satisfied: sphinx<2 in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (1.8.6)\n",
+ "Requirement already satisfied: tempeh in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (0.1.12)\n",
+ "Requirement already satisfied: cvxpy>=1.0 in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (1.3.2)\n",
+ "Requirement already satisfied: jupyter in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (1.0.0)\n",
+ "Requirement already satisfied: tqdm in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (4.66.1)\n",
+ "Requirement already satisfied: igraph[plotting] in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (0.10.8)\n",
+ "Requirement already satisfied: fairlearn~=0.7 in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (0.9.0)\n",
+ "Requirement already satisfied: rpy2 in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (3.4.2)\n",
+ "Requirement already satisfied: lime in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (0.2.0.1)\n",
+ "Requirement already satisfied: lightgbm in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (4.0.0)\n",
+ "Requirement already satisfied: sphinx-rtd-theme in /usr/local/lib/python3.10/dist-packages (from aif360[all]) (1.3.0)\n",
+ "Requirement already satisfied: six in /usr/local/lib/python3.10/dist-packages (from adversarial-robustness-toolbox>=1.0.0->aif360[all]) (1.16.0)\n",
+ "Requirement already satisfied: setuptools in /usr/local/lib/python3.10/dist-packages (from adversarial-robustness-toolbox>=1.0.0->aif360[all]) (67.7.2)\n",
+ "Requirement already satisfied: osqp>=0.4.1 in /usr/local/lib/python3.10/dist-packages (from cvxpy>=1.0->aif360[all]) (0.6.2.post8)\n",
+ "Requirement already satisfied: ecos>=2 in /usr/local/lib/python3.10/dist-packages (from cvxpy>=1.0->aif360[all]) (2.0.12)\n",
+ "Requirement already satisfied: scs>=1.1.6 in /usr/local/lib/python3.10/dist-packages (from cvxpy>=1.0->aif360[all]) (3.2.3)\n",
+ "Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from jinja2<3.1.0->aif360[all]) (2.1.3)\n",
+ "Requirement already satisfied: python-dateutil>=2.8.1 in /usr/local/lib/python3.10/dist-packages (from pandas>=0.24.0->aif360[all]) (2.8.2)\n",
+ "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas>=0.24.0->aif360[all]) (2023.3.post1)\n",
+ "Requirement already satisfied: iniconfig in /usr/local/lib/python3.10/dist-packages (from pytest>=3.5->aif360[all]) (2.0.0)\n",
+ "Requirement already satisfied: packaging in /usr/local/lib/python3.10/dist-packages (from pytest>=3.5->aif360[all]) (23.1)\n",
+ "Requirement already satisfied: pluggy<2.0,>=0.12 in /usr/local/lib/python3.10/dist-packages (from pytest>=3.5->aif360[all]) (1.3.0)\n",
+ "Requirement already satisfied: exceptiongroup>=1.0.0rc8 in /usr/local/lib/python3.10/dist-packages (from pytest>=3.5->aif360[all]) (1.1.3)\n",
+ "Requirement already satisfied: tomli>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from pytest>=3.5->aif360[all]) (2.0.1)\n",
+ "Requirement already satisfied: joblib>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from scikit-learn>=1.0->aif360[all]) (1.3.2)\n",
+ "Requirement already satisfied: threadpoolctl>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from scikit-learn>=1.0->aif360[all]) (3.2.0)\n",
+ "Requirement already satisfied: Pygments>=2.0 in /usr/local/lib/python3.10/dist-packages (from sphinx<2->aif360[all]) (2.16.1)\n",
+ "Requirement already satisfied: docutils<0.18,>=0.11 in /usr/local/lib/python3.10/dist-packages (from sphinx<2->aif360[all]) (0.17.1)\n",
+ "Requirement already satisfied: snowballstemmer>=1.1 in /usr/local/lib/python3.10/dist-packages (from sphinx<2->aif360[all]) (2.2.0)\n",
+ "Requirement already satisfied: babel!=2.0,>=1.3 in /usr/local/lib/python3.10/dist-packages (from sphinx<2->aif360[all]) (2.12.1)\n",
+ "Requirement already satisfied: alabaster<0.8,>=0.7 in /usr/local/lib/python3.10/dist-packages (from sphinx<2->aif360[all]) (0.7.13)\n",
+ "Requirement already satisfied: imagesize in /usr/local/lib/python3.10/dist-packages (from sphinx<2->aif360[all]) (1.4.1)\n",
+ "Requirement already satisfied: requests>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from sphinx<2->aif360[all]) (2.31.0)\n",
+ "Requirement already satisfied: sphinxcontrib-websupport in /usr/local/lib/python3.10/dist-packages (from sphinx<2->aif360[all]) (1.2.4)\n",
+ "Requirement already satisfied: absl-py>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (1.4.0)\n",
+ "Requirement already satisfied: astunparse>=1.6.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (1.6.3)\n",
+ "Requirement already satisfied: flatbuffers>=23.1.21 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (23.5.26)\n",
+ "Requirement already satisfied: gast<=0.4.0,>=0.2.1 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (0.4.0)\n",
+ "Requirement already satisfied: google-pasta>=0.1.1 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (0.2.0)\n",
+ "Requirement already satisfied: grpcio<2.0,>=1.24.3 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (1.57.0)\n",
+ "Requirement already satisfied: h5py>=2.9.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (3.9.0)\n",
+ "Requirement already satisfied: keras<2.14,>=2.13.1 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (2.13.1)\n",
+ "Requirement already satisfied: libclang>=13.0.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (16.0.6)\n",
+ "Requirement already satisfied: opt-einsum>=2.3.2 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (3.3.0)\n",
+ "Requirement already satisfied: protobuf!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev,>=3.20.3 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (3.20.3)\n",
+ "Requirement already satisfied: tensorboard<2.14,>=2.13 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (2.13.0)\n",
+ "Requirement already satisfied: tensorflow-estimator<2.14,>=2.13.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (2.13.0)\n",
+ "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (2.3.0)\n",
+ "Requirement already satisfied: typing-extensions<4.6.0,>=3.6.6 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (4.5.0)\n",
+ "Requirement already satisfied: wrapt>=1.11.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (1.15.0)\n",
+ "Requirement already satisfied: tensorflow-io-gcs-filesystem>=0.23.1 in /usr/local/lib/python3.10/dist-packages (from tensorflow>=1.13.1->aif360[all]) (0.33.0)\n",
+ "Requirement already satisfied: networkx in /usr/local/lib/python3.10/dist-packages (from BlackBoxAuditing->aif360[all]) (3.1)\n",
+ "Requirement already satisfied: texttable>=1.6.2 in /usr/local/lib/python3.10/dist-packages (from igraph[plotting]->aif360[all]) (1.6.7)\n",
+ "Requirement already satisfied: cairocffi>=1.2.0 in /usr/local/lib/python3.10/dist-packages (from igraph[plotting]->aif360[all]) (1.6.1)\n",
+ "Requirement already satisfied: ipython<9 in /usr/local/lib/python3.10/dist-packages (from ipympl->aif360[all]) (7.34.0)\n",
+ "Requirement already satisfied: ipython-genutils in /usr/local/lib/python3.10/dist-packages (from ipympl->aif360[all]) (0.2.0)\n",
+ "Requirement already satisfied: pillow in /usr/local/lib/python3.10/dist-packages (from ipympl->aif360[all]) (9.4.0)\n",
+ "Requirement already satisfied: traitlets<6 in /usr/local/lib/python3.10/dist-packages (from ipympl->aif360[all]) (5.7.1)\n",
+ "Requirement already satisfied: ipywidgets<9,>=7.6.0 in /usr/local/lib/python3.10/dist-packages (from ipympl->aif360[all]) (7.7.1)\n",
+ "Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib->aif360[all]) (1.1.0)\n",
+ "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib->aif360[all]) (0.11.0)\n",
+ "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib->aif360[all]) (4.42.1)\n",
+ "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib->aif360[all]) (1.4.5)\n",
+ "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib->aif360[all]) (3.1.1)\n",
+ "Requirement already satisfied: notebook in /usr/local/lib/python3.10/dist-packages (from jupyter->aif360[all]) (6.5.5)\n",
+ "Requirement already satisfied: qtconsole in /usr/local/lib/python3.10/dist-packages (from jupyter->aif360[all]) (5.4.4)\n",
+ "Requirement already satisfied: jupyter-console in /usr/local/lib/python3.10/dist-packages (from jupyter->aif360[all]) (6.1.0)\n",
+ "Requirement already satisfied: nbconvert in /usr/local/lib/python3.10/dist-packages (from jupyter->aif360[all]) (6.5.4)\n",
+ "Requirement already satisfied: ipykernel in /usr/local/lib/python3.10/dist-packages (from jupyter->aif360[all]) (5.5.6)\n",
+ "Requirement already satisfied: scikit-image>=0.12 in /usr/local/lib/python3.10/dist-packages (from lime->aif360[all]) (0.19.3)\n",
+ "Requirement already satisfied: cffi>=1.10.0 in /usr/local/lib/python3.10/dist-packages (from rpy2->aif360[all]) (1.15.1)\n",
+ "Requirement already satisfied: tzlocal in /usr/local/lib/python3.10/dist-packages (from rpy2->aif360[all]) (5.0.1)\n",
+ "Requirement already satisfied: sphinxcontrib-jquery<5,>=4 in /usr/local/lib/python3.10/dist-packages (from sphinx-rtd-theme->aif360[all]) (4.1)\n",
+ "Requirement already satisfied: memory-profiler in /usr/local/lib/python3.10/dist-packages (from tempeh->aif360[all]) (0.61.0)\n",
+ "Requirement already satisfied: shap in /usr/local/lib/python3.10/dist-packages (from tempeh->aif360[all]) (0.42.1)\n",
+ "Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from torch->aif360[all]) (3.12.2)\n",
+ "Requirement already satisfied: sympy in /usr/local/lib/python3.10/dist-packages (from torch->aif360[all]) (1.12)\n",
+ "Requirement already satisfied: triton==2.0.0 in /usr/local/lib/python3.10/dist-packages (from torch->aif360[all]) (2.0.0)\n",
+ "Requirement already satisfied: cmake in /usr/local/lib/python3.10/dist-packages (from triton==2.0.0->torch->aif360[all]) (3.27.4.1)\n",
+ "Requirement already satisfied: lit in /usr/local/lib/python3.10/dist-packages (from triton==2.0.0->torch->aif360[all]) (16.0.6)\n",
+ "Requirement already satisfied: wheel<1.0,>=0.23.0 in /usr/local/lib/python3.10/dist-packages (from astunparse>=1.6.0->tensorflow>=1.13.1->aif360[all]) (0.41.2)\n",
+ "Requirement already satisfied: pycparser in /usr/local/lib/python3.10/dist-packages (from cffi>=1.10.0->rpy2->aif360[all]) (2.21)\n",
+ "Requirement already satisfied: jedi>=0.16 in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl->aif360[all]) (0.19.0)\n",
+ "Requirement already satisfied: decorator in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl->aif360[all]) (4.4.2)\n",
+ "Requirement already satisfied: pickleshare in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl->aif360[all]) (0.7.5)\n",
+ "Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl->aif360[all]) (3.0.39)\n",
+ "Requirement already satisfied: backcall in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl->aif360[all]) (0.2.0)\n",
+ "Requirement already satisfied: matplotlib-inline in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl->aif360[all]) (0.1.6)\n",
+ "Requirement already satisfied: pexpect>4.3 in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl->aif360[all]) (4.8.0)\n",
+ "Requirement already satisfied: widgetsnbextension~=3.6.0 in /usr/local/lib/python3.10/dist-packages (from ipywidgets<9,>=7.6.0->ipympl->aif360[all]) (3.6.5)\n",
+ "Requirement already satisfied: jupyterlab-widgets>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from ipywidgets<9,>=7.6.0->ipympl->aif360[all]) (3.0.8)\n",
+ "Requirement already satisfied: jupyter-client in /usr/local/lib/python3.10/dist-packages (from ipykernel->jupyter->aif360[all]) (6.1.12)\n",
+ "Requirement already satisfied: tornado>=4.2 in /usr/local/lib/python3.10/dist-packages (from ipykernel->jupyter->aif360[all]) (6.3.2)\n",
+ "Requirement already satisfied: qdldl in /usr/local/lib/python3.10/dist-packages (from osqp>=0.4.1->cvxpy>=1.0->aif360[all]) (0.1.7.post0)\n",
+ "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests>=2.0.0->sphinx<2->aif360[all]) (3.2.0)\n",
+ "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests>=2.0.0->sphinx<2->aif360[all]) (3.4)\n",
+ "Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests>=2.0.0->sphinx<2->aif360[all]) (2.0.4)\n",
+ "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests>=2.0.0->sphinx<2->aif360[all]) (2023.7.22)\n",
+ "Requirement already satisfied: imageio>=2.4.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image>=0.12->lime->aif360[all]) (2.31.3)\n",
+ "Requirement already satisfied: tifffile>=2019.7.26 in /usr/local/lib/python3.10/dist-packages (from scikit-image>=0.12->lime->aif360[all]) (2023.8.30)\n",
+ "Requirement already satisfied: PyWavelets>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image>=0.12->lime->aif360[all]) (1.4.1)\n",
+ "Requirement already satisfied: google-auth<3,>=1.6.3 in /usr/local/lib/python3.10/dist-packages (from tensorboard<2.14,>=2.13->tensorflow>=1.13.1->aif360[all]) (2.17.3)\n",
+ "Requirement already satisfied: google-auth-oauthlib<1.1,>=0.5 in /usr/local/lib/python3.10/dist-packages (from tensorboard<2.14,>=2.13->tensorflow>=1.13.1->aif360[all]) (1.0.0)\n",
+ "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.10/dist-packages (from tensorboard<2.14,>=2.13->tensorflow>=1.13.1->aif360[all]) (3.4.4)\n",
+ "Requirement already satisfied: tensorboard-data-server<0.8.0,>=0.7.0 in /usr/local/lib/python3.10/dist-packages (from tensorboard<2.14,>=2.13->tensorflow>=1.13.1->aif360[all]) (0.7.1)\n",
+ "Requirement already satisfied: werkzeug>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from tensorboard<2.14,>=2.13->tensorflow>=1.13.1->aif360[all]) (2.3.7)\n",
+ "Requirement already satisfied: psutil in /usr/local/lib/python3.10/dist-packages (from memory-profiler->tempeh->aif360[all]) (5.9.5)\n",
+ "Requirement already satisfied: lxml in /usr/local/lib/python3.10/dist-packages (from nbconvert->jupyter->aif360[all]) (4.9.3)\n",
+ "Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.10/dist-packages (from nbconvert->jupyter->aif360[all]) (4.11.2)\n",
+ "Requirement already satisfied: bleach in /usr/local/lib/python3.10/dist-packages (from nbconvert->jupyter->aif360[all]) (6.0.0)\n",
+ "Requirement already satisfied: defusedxml in /usr/local/lib/python3.10/dist-packages (from nbconvert->jupyter->aif360[all]) (0.7.1)\n",
+ "Requirement already satisfied: entrypoints>=0.2.2 in /usr/local/lib/python3.10/dist-packages (from nbconvert->jupyter->aif360[all]) (0.4)\n",
+ "Requirement already satisfied: jupyter-core>=4.7 in /usr/local/lib/python3.10/dist-packages (from nbconvert->jupyter->aif360[all]) (5.3.1)\n",
+ "Requirement already satisfied: jupyterlab-pygments in /usr/local/lib/python3.10/dist-packages (from nbconvert->jupyter->aif360[all]) (0.2.2)\n",
+ "Requirement already satisfied: mistune<2,>=0.8.1 in /usr/local/lib/python3.10/dist-packages (from nbconvert->jupyter->aif360[all]) (0.8.4)\n",
+ "Requirement already satisfied: nbclient>=0.5.0 in /usr/local/lib/python3.10/dist-packages (from nbconvert->jupyter->aif360[all]) (0.8.0)\n",
+ "Requirement already satisfied: nbformat>=5.1 in /usr/local/lib/python3.10/dist-packages (from nbconvert->jupyter->aif360[all]) (5.9.2)\n",
+ "Requirement already satisfied: pandocfilters>=1.4.1 in /usr/local/lib/python3.10/dist-packages (from nbconvert->jupyter->aif360[all]) (1.5.0)\n",
+ "Requirement already satisfied: tinycss2 in /usr/local/lib/python3.10/dist-packages (from nbconvert->jupyter->aif360[all]) (1.2.1)\n",
+ "Requirement already satisfied: pyzmq<25,>=17 in /usr/local/lib/python3.10/dist-packages (from notebook->jupyter->aif360[all]) (23.2.1)\n",
+ "Requirement already satisfied: argon2-cffi in /usr/local/lib/python3.10/dist-packages (from notebook->jupyter->aif360[all]) (23.1.0)\n",
+ "Requirement already satisfied: nest-asyncio>=1.5 in /usr/local/lib/python3.10/dist-packages (from notebook->jupyter->aif360[all]) (1.5.7)\n",
+ "Requirement already satisfied: Send2Trash>=1.8.0 in /usr/local/lib/python3.10/dist-packages (from notebook->jupyter->aif360[all]) (1.8.2)\n",
+ "Requirement already satisfied: terminado>=0.8.3 in /usr/local/lib/python3.10/dist-packages (from notebook->jupyter->aif360[all]) (0.17.1)\n",
+ "Requirement already satisfied: prometheus-client in /usr/local/lib/python3.10/dist-packages (from notebook->jupyter->aif360[all]) (0.17.1)\n",
+ "Requirement already satisfied: nbclassic>=0.4.7 in /usr/local/lib/python3.10/dist-packages (from notebook->jupyter->aif360[all]) (1.0.0)\n",
+ "Requirement already satisfied: qtpy>=2.4.0 in /usr/local/lib/python3.10/dist-packages (from qtconsole->jupyter->aif360[all]) (2.4.0)\n",
+ "Requirement already satisfied: slicer==0.0.7 in /usr/local/lib/python3.10/dist-packages (from shap->tempeh->aif360[all]) (0.0.7)\n",
+ "Requirement already satisfied: numba in /usr/local/lib/python3.10/dist-packages (from shap->tempeh->aif360[all]) (0.56.4)\n",
+ "Requirement already satisfied: cloudpickle in /usr/local/lib/python3.10/dist-packages (from shap->tempeh->aif360[all]) (2.2.1)\n",
+ "Requirement already satisfied: sphinxcontrib-serializinghtml in /usr/local/lib/python3.10/dist-packages (from sphinxcontrib-websupport->sphinx<2->aif360[all]) (1.1.5)\n",
+ "Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy->torch->aif360[all]) (1.3.0)\n",
+ "Requirement already satisfied: cachetools<6.0,>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from google-auth<3,>=1.6.3->tensorboard<2.14,>=2.13->tensorflow>=1.13.1->aif360[all]) (5.3.1)\n",
+ "Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/lib/python3.10/dist-packages (from google-auth<3,>=1.6.3->tensorboard<2.14,>=2.13->tensorflow>=1.13.1->aif360[all]) (0.3.0)\n",
+ "Requirement already satisfied: rsa<5,>=3.1.4 in /usr/local/lib/python3.10/dist-packages (from google-auth<3,>=1.6.3->tensorboard<2.14,>=2.13->tensorflow>=1.13.1->aif360[all]) (4.9)\n",
+ "Requirement already satisfied: requests-oauthlib>=0.7.0 in /usr/local/lib/python3.10/dist-packages (from google-auth-oauthlib<1.1,>=0.5->tensorboard<2.14,>=2.13->tensorflow>=1.13.1->aif360[all]) (1.3.1)\n",
+ "Requirement already satisfied: parso<0.9.0,>=0.8.3 in /usr/local/lib/python3.10/dist-packages (from jedi>=0.16->ipython<9->ipympl->aif360[all]) (0.8.3)\n",
+ "Requirement already satisfied: platformdirs>=2.5 in /usr/local/lib/python3.10/dist-packages (from jupyter-core>=4.7->nbconvert->jupyter->aif360[all]) (3.10.0)\n",
+ "Requirement already satisfied: jupyter-server>=1.8 in /usr/local/lib/python3.10/dist-packages (from nbclassic>=0.4.7->notebook->jupyter->aif360[all]) (1.24.0)\n",
+ "Requirement already satisfied: notebook-shim>=0.2.3 in /usr/local/lib/python3.10/dist-packages (from nbclassic>=0.4.7->notebook->jupyter->aif360[all]) (0.2.3)\n",
+ "Requirement already satisfied: fastjsonschema in /usr/local/lib/python3.10/dist-packages (from nbformat>=5.1->nbconvert->jupyter->aif360[all]) (2.18.0)\n",
+ "Requirement already satisfied: jsonschema>=2.6 in /usr/local/lib/python3.10/dist-packages (from nbformat>=5.1->nbconvert->jupyter->aif360[all]) (4.19.0)\n",
+ "Requirement already satisfied: ptyprocess>=0.5 in /usr/local/lib/python3.10/dist-packages (from pexpect>4.3->ipython<9->ipympl->aif360[all]) (0.7.0)\n",
+ "Requirement already satisfied: wcwidth in /usr/local/lib/python3.10/dist-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython<9->ipympl->aif360[all]) (0.2.6)\n",
+ "Requirement already satisfied: argon2-cffi-bindings in /usr/local/lib/python3.10/dist-packages (from argon2-cffi->notebook->jupyter->aif360[all]) (21.2.0)\n",
+ "Requirement already satisfied: soupsieve>1.2 in /usr/local/lib/python3.10/dist-packages (from beautifulsoup4->nbconvert->jupyter->aif360[all]) (2.5)\n",
+ "Requirement already satisfied: webencodings in /usr/local/lib/python3.10/dist-packages (from bleach->nbconvert->jupyter->aif360[all]) (0.5.1)\n",
+ "Requirement already satisfied: llvmlite<0.40,>=0.39.0dev0 in /usr/local/lib/python3.10/dist-packages (from numba->shap->tempeh->aif360[all]) (0.39.1)\n",
+ "Requirement already satisfied: attrs>=22.2.0 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat>=5.1->nbconvert->jupyter->aif360[all]) (23.1.0)\n",
+ "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat>=5.1->nbconvert->jupyter->aif360[all]) (2023.7.1)\n",
+ "Requirement already satisfied: referencing>=0.28.4 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat>=5.1->nbconvert->jupyter->aif360[all]) (0.30.2)\n",
+ "Requirement already satisfied: rpds-py>=0.7.1 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat>=5.1->nbconvert->jupyter->aif360[all]) (0.10.2)\n",
+ "Requirement already satisfied: anyio<4,>=3.1.0 in /usr/local/lib/python3.10/dist-packages (from jupyter-server>=1.8->nbclassic>=0.4.7->notebook->jupyter->aif360[all]) (3.7.1)\n",
+ "Requirement already satisfied: websocket-client in /usr/local/lib/python3.10/dist-packages (from jupyter-server>=1.8->nbclassic>=0.4.7->notebook->jupyter->aif360[all]) (1.6.2)\n",
+ "Requirement already satisfied: pyasn1<0.6.0,>=0.4.6 in /usr/local/lib/python3.10/dist-packages (from pyasn1-modules>=0.2.1->google-auth<3,>=1.6.3->tensorboard<2.14,>=2.13->tensorflow>=1.13.1->aif360[all]) (0.5.0)\n",
+ "Requirement already satisfied: oauthlib>=3.0.0 in /usr/local/lib/python3.10/dist-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<1.1,>=0.5->tensorboard<2.14,>=2.13->tensorflow>=1.13.1->aif360[all]) (3.2.2)\n",
+ "Requirement already satisfied: sniffio>=1.1 in /usr/local/lib/python3.10/dist-packages (from anyio<4,>=3.1.0->jupyter-server>=1.8->nbclassic>=0.4.7->notebook->jupyter->aif360[all]) (1.3.0)\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "id": "mGTPlveh_Sks"
+ },
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "\n",
+ "from sklearn.compose import make_column_transformer\n",
+ "from sklearn.linear_model import LogisticRegression\n",
+ "from sklearn.metrics import accuracy_score\n",
+ "from sklearn.model_selection import train_test_split\n",
+ "from sklearn.preprocessing import OneHotEncoder\n",
+ "\n",
+ "from aif360.sklearn.inprocessing import ExponentiatedGradientReduction\n",
+ "\n",
+ "from aif360.sklearn.datasets import fetch_adult\n",
+ "from aif360.sklearn.metrics import average_odds_error"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "R14XPGRH_Skt"
+ },
+ "source": [
+ "### Loading data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "8BFNKGQH_Skt"
+ },
+ "source": [
+ "Datasets are formatted as separate `X` (# samples x # features) and `y` (# samples x # labels) DataFrames. The index of each DataFrame contains protected attribute values per sample. Datasets may also load a `sample_weight` object to be used with certain algorithms/metrics. All of this makes it so that aif360 is compatible with scikit-learn objects.\n",
+ "\n",
+ "For example, we can easily load the Adult dataset from UCI with the following line:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 379
+ },
+ "id": "rKX-UfbE_Skt",
+ "outputId": "5c8ef89d-6256-44a4-aef0-c88bbbd40d3c"
+ },
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ " age workclass education education-num \\\n",
+ "race sex \n",
+ "Non-white Male 25.0 Private 11th 7.0 \n",
+ "White Male 38.0 Private HS-grad 9.0 \n",
+ " Male 28.0 Local-gov Assoc-acdm 12.0 \n",
+ "Non-white Male 44.0 Private Some-college 10.0 \n",
+ "White Male 34.0 Private 10th 6.0 \n",
+ "\n",
+ " marital-status occupation relationship race \\\n",
+ "race sex \n",
+ "Non-white Male Never-married Machine-op-inspct Own-child Black \n",
+ "White Male Married-civ-spouse Farming-fishing Husband White \n",
+ " Male Married-civ-spouse Protective-serv Husband White \n",
+ "Non-white Male Married-civ-spouse Machine-op-inspct Husband Black \n",
+ "White Male Never-married Other-service Not-in-family White \n",
+ "\n",
+ " sex capital-gain capital-loss hours-per-week \\\n",
+ "race sex \n",
+ "Non-white Male Male 0.0 0.0 40.0 \n",
+ "White Male Male 0.0 0.0 50.0 \n",
+ " Male Male 0.0 0.0 40.0 \n",
+ "Non-white Male Male 7688.0 0.0 40.0 \n",
+ "White Male Male 0.0 0.0 30.0 \n",
+ "\n",
+ " native-country \n",
+ "race sex \n",
+ "Non-white Male United-States \n",
+ "White Male United-States \n",
+ " Male United-States \n",
+ "Non-white Male United-States \n",
+ "White Male United-States "
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " | \n",
+ " age | \n",
+ " workclass | \n",
+ " education | \n",
+ " education-num | \n",
+ " marital-status | \n",
+ " occupation | \n",
+ " relationship | \n",
+ " race | \n",
+ " sex | \n",
+ " capital-gain | \n",
+ " capital-loss | \n",
+ " hours-per-week | \n",
+ " native-country | \n",
+ "
\n",
+ " \n",
+ " | race | \n",
+ " sex | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | Non-white | \n",
+ " Male | \n",
+ " 25.0 | \n",
+ " Private | \n",
+ " 11th | \n",
+ " 7.0 | \n",
+ " Never-married | \n",
+ " Machine-op-inspct | \n",
+ " Own-child | \n",
+ " Black | \n",
+ " Male | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 40.0 | \n",
+ " United-States | \n",
+ "
\n",
+ " \n",
+ " | White | \n",
+ " Male | \n",
+ " 38.0 | \n",
+ " Private | \n",
+ " HS-grad | \n",
+ " 9.0 | \n",
+ " Married-civ-spouse | \n",
+ " Farming-fishing | \n",
+ " Husband | \n",
+ " White | \n",
+ " Male | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 50.0 | \n",
+ " United-States | \n",
+ "
\n",
+ " \n",
+ " | Male | \n",
+ " 28.0 | \n",
+ " Local-gov | \n",
+ " Assoc-acdm | \n",
+ " 12.0 | \n",
+ " Married-civ-spouse | \n",
+ " Protective-serv | \n",
+ " Husband | \n",
+ " White | \n",
+ " Male | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 40.0 | \n",
+ " United-States | \n",
+ "
\n",
+ " \n",
+ " | Non-white | \n",
+ " Male | \n",
+ " 44.0 | \n",
+ " Private | \n",
+ " Some-college | \n",
+ " 10.0 | \n",
+ " Married-civ-spouse | \n",
+ " Machine-op-inspct | \n",
+ " Husband | \n",
+ " Black | \n",
+ " Male | \n",
+ " 7688.0 | \n",
+ " 0.0 | \n",
+ " 40.0 | \n",
+ " United-States | \n",
+ "
\n",
+ " \n",
+ " | White | \n",
+ " Male | \n",
+ " 34.0 | \n",
+ " Private | \n",
+ " 10th | \n",
+ " 6.0 | \n",
+ " Never-married | \n",
+ " Other-service | \n",
+ " Not-in-family | \n",
+ " White | \n",
+ " Male | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 30.0 | \n",
+ " United-States | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n"
+ ]
+ },
+ "metadata": {},
+ "execution_count": 4
+ }
],
- "text/plain": [
- " workclass_Federal-gov workclass_Local-gov workclass_Private \\\n",
- "race sex \n",
- "1 1 0.0 0.0 0.0 \n",
- " 0 0.0 0.0 0.0 \n",
- " 1 0.0 0.0 1.0 \n",
- " 1 0.0 0.0 1.0 \n",
- " 1 0.0 0.0 1.0 \n",
- "\n",
- " workclass_Self-emp-inc workclass_Self-emp-not-inc \\\n",
- "race sex \n",
- "1 1 0.0 1.0 \n",
- " 0 0.0 1.0 \n",
- " 1 0.0 0.0 \n",
- " 1 0.0 0.0 \n",
- " 1 0.0 0.0 \n",
- "\n",
- " workclass_State-gov workclass_Without-pay education_10th \\\n",
- "race sex \n",
- "1 1 0.0 0.0 0.0 \n",
- " 0 0.0 0.0 0.0 \n",
- " 1 0.0 0.0 0.0 \n",
- " 1 0.0 0.0 0.0 \n",
- " 1 0.0 0.0 1.0 \n",
- "\n",
- " education_11th education_12th ... native-country_Thailand \\\n",
- "race sex ... \n",
- "1 1 0.0 0.0 ... 0.0 \n",
- " 0 0.0 0.0 ... 0.0 \n",
- " 1 0.0 0.0 ... 0.0 \n",
- " 1 0.0 0.0 ... 0.0 \n",
- " 1 0.0 0.0 ... 0.0 \n",
- "\n",
- " native-country_Trinadad&Tobago native-country_United-States \\\n",
- "race sex \n",
- "1 1 0.0 1.0 \n",
- " 0 0.0 0.0 \n",
- " 1 0.0 1.0 \n",
- " 1 0.0 0.0 \n",
- " 1 0.0 1.0 \n",
- "\n",
- " native-country_Vietnam native-country_Yugoslavia age \\\n",
- "race sex \n",
- "1 1 0.0 0.0 58.0 \n",
- " 0 0.0 0.0 51.0 \n",
- " 1 0.0 0.0 26.0 \n",
- " 1 0.0 0.0 44.0 \n",
- " 1 0.0 0.0 33.0 \n",
- "\n",
- " education-num capital-gain capital-loss hours-per-week \n",
- "race sex \n",
- "1 1 11.0 0.0 0.0 42.0 \n",
- " 0 12.0 0.0 0.0 30.0 \n",
- " 1 14.0 0.0 1887.0 40.0 \n",
- " 1 3.0 0.0 0.0 40.0 \n",
- " 1 6.0 0.0 0.0 40.0 \n",
- "\n",
- "[5 rows x 100 columns]"
- ]
- },
- "execution_count": 8,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "ohe = make_column_transformer(\n",
- " (OneHotEncoder(sparse=False), X_train.dtypes == 'category'),\n",
- " remainder='passthrough', verbose_feature_names_out=False)\n",
- "X_train = pd.DataFrame(ohe.fit_transform(X_train), columns=ohe.get_feature_names_out(), index=X_train.index)\n",
- "X_test = pd.DataFrame(ohe.transform(X_test), columns=ohe.get_feature_names_out(), index=X_test.index)\n",
- "\n",
- "X_train.head()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The protected attribute information is also replicated in the labels:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "race sex\n",
- "1 1 0\n",
- " 0 1\n",
- " 1 1\n",
- " 1 0\n",
- " 1 0\n",
- "dtype: int64"
- ]
- },
- "execution_count": 9,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "y_train.head()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Running metrics"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "With the data in this format, we can easily train a scikit-learn model and get predictions for the test data:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.8460234392275374"
- ]
- },
- "execution_count": 10,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "y_pred = LogisticRegression(solver='liblinear').fit(X_train, y_train).predict(X_test)\n",
- "lr_acc = accuracy_score(y_test, y_pred)\n",
- "lr_acc"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can assess how close the predictions are to equality of odds.\n",
- "\n",
- "`average_odds_error()` computes the (unweighted) average of the absolute values of the true positive rate (TPR) difference and false positive rate (FPR) difference, i.e.:\n",
- "\n",
- "$$ \\tfrac{1}{2}\\left(|FPR_{D = \\text{unprivileged}} - FPR_{D = \\text{privileged}}| + |TPR_{D = \\text{unprivileged}} - TPR_{D = \\text{privileged}}|\\right) $$"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.09335303807799161"
- ]
- },
- "execution_count": 11,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "lr_aoe_sex = average_odds_error(y_test, y_pred, prot_attr='sex')\n",
- "lr_aoe_sex"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.06751597777565721"
- ]
- },
- "execution_count": 12,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "lr_aoe_race = average_odds_error(y_test, y_pred, prot_attr='race')\n",
- "lr_aoe_race"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exponentiated Gradient Reduction"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Choose a base model for the randomized classifier"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [],
- "source": [
- "estimator = LogisticRegression(solver='liblinear')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Determine the columns associated with the protected attribute(s)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [],
- "source": [
- "prot_attr_cols = [colname for colname in X_train if \"sex\" in colname or \"race\" in colname]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Train the randomized classifier and observe test accuracy. Other options for `constraints` include \"DemographicParity\", \"TruePositiveRateParity\", \"FalsePositiveRateParity\", and \"ErrorRateParity\"."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0.834303825458834\n"
- ]
- }
- ],
- "source": [
- "np.random.seed(0) #for reproducibility\n",
- "exp_grad_red = ExponentiatedGradientReduction(prot_attr=prot_attr_cols, \n",
- " estimator=estimator, \n",
- " constraints=\"EqualizedOdds\",\n",
- " drop_prot_attr=False)\n",
- "exp_grad_red.fit(X_train, y_train)\n",
- "egr_acc = exp_grad_red.score(X_test, y_test)\n",
- "print(egr_acc)\n",
- "\n",
- "# Check for that accuracy is comparable\n",
- "assert abs(lr_acc-egr_acc)<=0.03"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0.02361168550972803\n"
- ]
- }
- ],
- "source": [
- "egr_aoe_sex = average_odds_error(y_test, exp_grad_red.predict(X_test), prot_attr='sex')\n",
- "print(egr_aoe_sex)\n",
- "\n",
- "# Check for improvement in average odds error for sex\n",
- "assert egr_aoe_sex\n",
+ " \n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " | \n",
+ " workclass_Federal-gov | \n",
+ " workclass_Local-gov | \n",
+ " workclass_Private | \n",
+ " workclass_Self-emp-inc | \n",
+ " workclass_Self-emp-not-inc | \n",
+ " workclass_State-gov | \n",
+ " workclass_Without-pay | \n",
+ " education_10th | \n",
+ " education_11th | \n",
+ " education_12th | \n",
+ " ... | \n",
+ " native-country_Thailand | \n",
+ " native-country_Trinadad&Tobago | \n",
+ " native-country_United-States | \n",
+ " native-country_Vietnam | \n",
+ " native-country_Yugoslavia | \n",
+ " age | \n",
+ " education-num | \n",
+ " capital-gain | \n",
+ " capital-loss | \n",
+ " hours-per-week | \n",
+ "
\n",
+ " \n",
+ " | race | \n",
+ " sex | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " ... | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 58.0 | \n",
+ " 11.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 42.0 | \n",
+ "
\n",
+ " \n",
+ " | 0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " ... | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 51.0 | \n",
+ " 12.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 30.0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " ... | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 26.0 | \n",
+ " 14.0 | \n",
+ " 0.0 | \n",
+ " 1887.0 | \n",
+ " 40.0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " ... | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 44.0 | \n",
+ " 3.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 40.0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " ... | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 33.0 | \n",
+ " 6.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 40.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
5 rows × 100 columns
\n",
+ "
\n",
+ " \n",
+ " \n"
+ ]
+ },
+ "metadata": {},
+ "execution_count": 9
+ }
+ ],
+ "source": [
+ "ohe = make_column_transformer(\n",
+ " (OneHotEncoder(sparse=False), X_train.dtypes == 'category'),\n",
+ " remainder='passthrough', verbose_feature_names_out=False)\n",
+ "X_train = pd.DataFrame(ohe.fit_transform(X_train), columns=ohe.get_feature_names_out(), index=X_train.index)\n",
+ "X_test = pd.DataFrame(ohe.transform(X_test), columns=ohe.get_feature_names_out(), index=X_test.index)\n",
+ "\n",
+ "X_train.head()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "iDl0-rpN_Skv"
+ },
+ "source": [
+ "The protected attribute information is also replicated in the labels:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "ceed2vSk_Skv",
+ "outputId": "f78ed972-3708-4719-ced4-a71d90ce4d82"
+ },
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ "race sex\n",
+ "1 1 0\n",
+ " 0 1\n",
+ " 1 1\n",
+ " 1 0\n",
+ " 1 0\n",
+ "dtype: int64"
+ ]
+ },
+ "metadata": {},
+ "execution_count": 10
+ }
+ ],
+ "source": [
+ "y_train.head()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "2JlMQ_ps_Skw"
+ },
+ "source": [
+ "### Running metrics"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "rd7IevXR_Skw"
+ },
+ "source": [
+ "With the data in this format, we can easily train a scikit-learn model and get predictions for the test data:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "T32eJkuA_Skw",
+ "outputId": "9f017a8f-a197-498c-926e-0a558776f5d0"
+ },
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ "0.8463919805410186"
+ ]
+ },
+ "metadata": {},
+ "execution_count": 11
+ }
+ ],
+ "source": [
+ "y_pred = LogisticRegression(solver='liblinear').fit(X_train, y_train).predict(X_test)\n",
+ "lr_acc = accuracy_score(y_test, y_pred)\n",
+ "lr_acc"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "2npvOfdY_Skw"
+ },
+ "source": [
+ "We can assess how close the predictions are to equality of odds.\n",
+ "\n",
+ "`average_odds_error()` computes the (unweighted) average of the absolute values of the true positive rate (TPR) difference and false positive rate (FPR) difference, i.e.:\n",
+ "\n",
+ "$$ \\tfrac{1}{2}\\left(|FPR_{D = \\text{unprivileged}} - FPR_{D = \\text{privileged}}| + |TPR_{D = \\text{unprivileged}} - TPR_{D = \\text{privileged}}|\\right) $$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "I4nQ0LpF_Skw",
+ "outputId": "d995618d-123a-4c87-bd9a-e9efbfede696"
+ },
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ "0.09072468611163034"
+ ]
+ },
+ "metadata": {},
+ "execution_count": 12
+ }
+ ],
+ "source": [
+ "lr_aoe_sex = average_odds_error(y_test, y_pred, prot_attr='sex')\n",
+ "lr_aoe_sex"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "ep82WxJX_Skw",
+ "outputId": "a8e54eca-ea30-4cb1-b83c-0dab87ee6fa6"
+ },
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ "0.06302158185948953"
+ ]
+ },
+ "metadata": {},
+ "execution_count": 13
+ }
+ ],
+ "source": [
+ "lr_aoe_race = average_odds_error(y_test, y_pred, prot_attr='race')\n",
+ "lr_aoe_race"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "TpcF_2PM_Skx"
+ },
+ "source": [
+ "### Exponentiated Gradient Reduction"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "NHEevMCI_Skx"
+ },
+ "source": [
+ "Choose a base model for the randomized classifier"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {
+ "id": "S7eh3VEH_Skx"
+ },
+ "outputs": [],
+ "source": [
+ "estimator = LogisticRegression(solver='liblinear')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "fyR6n3Qd_Skx"
+ },
+ "source": [
+ "Determine the columns associated with the protected attribute(s)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {
+ "id": "HDSm1ujB_Skx"
+ },
+ "outputs": [],
+ "source": [
+ "prot_attr_cols = [colname for colname in X_train if \"sex\" in colname or \"race\" in colname]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "z2OhxVgK_Skx"
+ },
+ "source": [
+ "Train the randomized classifier and observe test accuracy. Other options for `constraints` include \"DemographicParity\", \"TruePositiveRateParity\", \"FalsePositiveRateParity\", and \"ErrorRateParity\"."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "-jRJaCIG_Skx",
+ "outputId": "f17fa52b-1ba4-42f7-c05c-3bd92a9a1521"
+ },
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "0.8340827006707452\n"
+ ]
+ }
+ ],
+ "source": [
+ "np.random.seed(0) #for reproducibility\n",
+ "exp_grad_red = ExponentiatedGradientReduction(prot_attr=prot_attr_cols,\n",
+ " estimator=estimator,\n",
+ " constraints=\"EqualizedOdds\",\n",
+ " drop_prot_attr=False)\n",
+ "exp_grad_red.fit(X_train, y_train)\n",
+ "egr_acc = exp_grad_red.score(X_test, y_test)\n",
+ "print(egr_acc)\n",
+ "\n",
+ "# Check for that accuracy is comparable\n",
+ "assert abs(lr_acc-egr_acc)<=0.03"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "2Tcuj5dE_Skx",
+ "outputId": "421d090d-6eb7-4857-b227-856a25f22ddb"
+ },
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "0.025270988735088984\n"
+ ]
+ }
+ ],
+ "source": [
+ "egr_aoe_sex = average_odds_error(y_test, exp_grad_red.predict(X_test), prot_attr='sex')\n",
+ "print(egr_aoe_sex)\n",
+ "\n",
+ "# Check for improvement in average odds error for sex\n",
+ "assert egr_aoe_sex