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", - " \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", - " \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", - " \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", - " \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", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
ageworkclasseducationeducation-nummarital-statusoccupationrelationshipracesexcapital-gaincapital-losshours-per-weeknative-country
racesex
Non-whiteMale25.0Private11th7.0Never-marriedMachine-op-inspctOwn-childBlackMale0.00.040.0United-States
WhiteMale38.0PrivateHS-grad9.0Married-civ-spouseFarming-fishingHusbandWhiteMale0.00.050.0United-States
Male28.0Local-govAssoc-acdm12.0Married-civ-spouseProtective-servHusbandWhiteMale0.00.040.0United-States
Non-whiteMale44.0PrivateSome-college10.0Married-civ-spouseMachine-op-inspctHusbandBlackMale7688.00.040.0United-States
WhiteMale34.0Private10th6.0Never-marriedOther-serviceNot-in-familyWhiteMale0.00.030.0United-States
\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", - " \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", - " \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", - " \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", - " \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", - " \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", - " \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", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
workclass_Federal-govworkclass_Local-govworkclass_Privateworkclass_Self-emp-incworkclass_Self-emp-not-incworkclass_State-govworkclass_Without-payeducation_10theducation_11theducation_12th...native-country_Thailandnative-country_Trinadad&Tobagonative-country_United-Statesnative-country_Vietnamnative-country_Yugoslaviaageeducation-numcapital-gaincapital-losshours-per-week
racesex
110.00.00.00.01.00.00.00.00.00.0...0.00.01.00.00.058.011.00.00.042.0
00.00.00.00.01.00.00.00.00.00.0...0.00.00.00.00.051.012.00.00.030.0
10.00.01.00.00.00.00.00.00.00.0...0.00.01.00.00.026.014.00.01887.040.0
10.00.01.00.00.00.00.00.00.00.0...0.00.00.00.00.044.03.00.00.040.0
10.00.01.00.00.00.00.01.00.00.0...0.00.01.00.00.033.06.00.00.040.0
\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", + " \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", + " \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", + " \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", + " \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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ageworkclasseducationeducation-nummarital-statusoccupationrelationshipracesexcapital-gaincapital-losshours-per-weeknative-country
racesex
Non-whiteMale25.0Private11th7.0Never-marriedMachine-op-inspctOwn-childBlackMale0.00.040.0United-States
WhiteMale38.0PrivateHS-grad9.0Married-civ-spouseFarming-fishingHusbandWhiteMale0.00.050.0United-States
Male28.0Local-govAssoc-acdm12.0Married-civ-spouseProtective-servHusbandWhiteMale0.00.040.0United-States
Non-whiteMale44.0PrivateSome-college10.0Married-civ-spouseMachine-op-inspctHusbandBlackMale7688.00.040.0United-States
WhiteMale34.0Private10th6.0Never-marriedOther-serviceNot-in-familyWhiteMale0.00.030.0United-States
\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
\n", + "\n", + "\n", + "
\n", + " \n", + "\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", + " \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", + " \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", + " \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", + " \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", + " \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", + " \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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
workclass_Federal-govworkclass_Local-govworkclass_Privateworkclass_Self-emp-incworkclass_Self-emp-not-incworkclass_State-govworkclass_Without-payeducation_10theducation_11theducation_12th...native-country_Thailandnative-country_Trinadad&Tobagonative-country_United-Statesnative-country_Vietnamnative-country_Yugoslaviaageeducation-numcapital-gaincapital-losshours-per-week
racesex
110.00.00.00.01.00.00.00.00.00.0...0.00.01.00.00.058.011.00.00.042.0
00.00.00.00.01.00.00.00.00.00.0...0.00.00.00.00.051.012.00.00.030.0
10.00.01.00.00.00.00.00.00.00.0...0.00.01.00.00.026.014.00.01887.040.0
10.00.01.00.00.00.00.00.00.00.0...0.00.00.00.00.044.03.00.00.040.0
10.00.01.00.00.00.00.01.00.00.0...0.00.01.00.00.033.06.00.00.040.0
\n", + "

5 rows × 100 columns

\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
\n", + "\n", + "\n", + "
\n", + " \n", + "\n", + "\n", + "\n", + " \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