diff --git a/examples/bankDefault.ipynb b/examples/bankDefault.ipynb new file mode 100644 index 00000000..2097cc59 --- /dev/null +++ b/examples/bankDefault.ipynb @@ -0,0 +1,542 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Tutorial of using AIF 360 to predict default of credit cards with adjusted bias on sex\n", + "\n", + "Author: Yi Wang\n", + "\n", + "GitHub: https://github.com/yahowang\n", + "\n", + "Data source: https://archive.ics.uci.edu/ml/datasets/default+of+credit+card+clients\n", + "\n", + "Idea Inspiration: https://nbviewer.jupyter.org/github/IBM/AIF360/blob/master/examples/tutorial_credit_scoring.ipynb\n", + "\n", + "Public Paper: Yeh, I. C., & Lien, C. H. (2009). The comparisons of data mining techniques for the predictive accuracy of probability of default of credit card clients. Expert Systems with Applications, 36(2), 2473-2480.\n", + "\n", + "License: MIT License" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Intro\n", + "Because of the advance of financial crediting system, customers are able to make an expense with their creditability and pay off in the future. Yet, it is challenging yet vital for banks to determine whether their customers would have the ability to pay off their credits to minimize the risk of capital loss. Therefore, one of the ways of doing so is to track historical transactions and payments to target potential customers who will not meet payoff requirements. These customers will be classified and will have a greater change of fedault in the future. \n", + "\n", + "In this task, the dataset was obtained from banks in Taiwan and was meant to target the case of customers default payments. This is a binary classification problem and the target valuable is whether acustomer will default or not based on different features and payment histories. \n", + "\n", + "This dataset contains more females than males and the males have more instances being credit card default. With the use of AI Fairness 360 (AIF 360), we can adjust the bias on sex and compare the performance of a simple model on the original and transformed dataset.\n", + "\n", + "## Feature Description\n", + "Since UCI Machine Learning Repository has some wrong information about feature decriptions, I will list the features in detail as below.\n", + "\n", + "$X_1$: Amount of the given credit (NT dollar): it includes both the individual consumer credit and his/her family (supplementary) credit.\n", + "\n", + "$X_2$: Sex (1 = male; 2 = female).\n", + "\n", + "$X_3$: Education (1 = graduate school; 2 = university; 3 = high school; 0,4,5,6 = others).\n", + "\n", + "$X_4$: Marriage (1 = married; 2 = single; 3 = divorce; 0 = others).\n", + "\n", + "$X_5$: Age (year).\n", + "\n", + "$X_6$ - $X_{11}$: History of past payment (with 10 categories for each feature).\n", + "- The measurement scale for the repayment status is: \n", + " - -2 = No consumption\n", + " - -1 = payment in full\n", + " - 0 = minimum amount of payment\n", + " - 1 = payment delay for one month\n", + " - 2 = payment delay for two months\n", + " - 3 = payment delay for three months\n", + " - 4 = payment delay for four months\n", + " - 5 = payment delay for five months\n", + " - 6 = payment delay for six months\n", + " - 7 = payment delay for seven months\n", + " - 8 = payment delay for eight months\n", + " - 9 = payment delay for nine months and above\n", + "- $X_6$ = the repayment status in September, 2005 \n", + "- $X_7$ = the repayment status in August, 2005\n", + "- $X_8$ = the repayment status in July, 2005\n", + "- $X_9$ = the repayment status in June, 2005\n", + "- $X_{10}$ = the repayment status in May, 2005\n", + "- $X_{11}$ = the repayment status in April, 2005\n", + "\n", + "$X_{12}$-$X_{17}$: Amount of bill statement (NT dollar)\n", + "- $X_{12}$ = amount of bill statement in September, 2005\n", + "- $X_{13}$ = amount of bill statement in August, 2005\n", + "- $X_{14}$ = amount of bill statement in July, 2005\n", + "- $X_{15}$ = amount of bill statement in June, 2005\n", + "- $X_{16}$ = amount of bill statement in May, 2005\n", + "- $X_{17}$ = amount of bill statement in April, 2005\n", + "\n", + "$X_{18}$-$X_{23}$: Amount of previous payment (NT dollar).\n", + "- $X_{18}$ = amount paid in September, 2005\n", + "- $X_{19}$ = amount paid in August, 2005\n", + "- $X_{20}$ = amount paid in July, 2005\n", + "- $X_{21}$ = amount paid in June, 2005\n", + "- $X_{22}$ = amount paid in May, 2005\n", + "- $X_{23}$ = amount paid in April, 2005.\n", + "\n", + "$X_{24}$: Whether the customer will default in the next session (1 = Yes; 0 = No)" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Loading Raw Data and Preprocessing" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "First we need to load the data and wrap it in a standard AIF360 dataset such that many metrics can be used later." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from matplotlib import pylab as plt\n", + "import matplotlib\n", + "from sklearn.preprocessing import OrdinalEncoder\n", + "from sklearn.preprocessing import MinMaxScaler\n", + "from sklearn.preprocessing import OneHotEncoder\n", + "from sklearn.preprocessing import StandardScaler\n", + "from sklearn.preprocessing import LabelEncoder\n", + "from aif360.datasets import StandardDataset\n", + "from aif360.metrics import BinaryLabelDatasetMetric\n", + "from aif360.algorithms.preprocessing import Reweighing\n", + "from IPython.display import Markdown, display\n", + "from sklearn.ensemble import RandomForestClassifier\n", + "from sklearn.metrics import accuracy_score, roc_curve, auc" + ], + "outputs": [], + "execution_count": 16, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "The customeized preprocessing function for this dataset" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "def preprocess(df):\n", + " \"\"\"\n", + " Customized preprocessing method for the dataset.\n", + " Input: original df\n", + " Output: preprocessed df\n", + " \"\"\"\n", + " # Standard Scaler\n", + " scaler = StandardScaler()\n", + " continuous =['LIMIT_BAL','BILL_AMT1','BILL_AMT2','BILL_AMT3','BILL_AMT4','BILL_AMT5','BILL_AMT6','PAY_AMT1','PAY_AMT2','PAY_AMT3','PAY_AMT4','PAY_AMT5','PAY_AMT6']\n", + " df[continuous] = scaler.fit_transform(df[continuous])\n", + "\n", + " # Payment status contains a mixture of qualitative and quantitative values\n", + " # Thus, it needs a special preprocessing to decouple the mixture\n", + " mixed_features = [\"PAY_0\", \"PAY_2\", \"PAY_3\", \"PAY_4\", \"PAY_5\", \"PAY_6\"]\n", + " for mixed_feature in mixed_features:\n", + " for i in range(-2,1):\n", + " df[mixed_feature + \"_\" + str(i)] = [1 if t else 0 for t in df[mixed_feature] == i]\n", + " df[mixed_feature] = [0 if t == i else t for t in df[mixed_feature]]\n", + "\n", + " # One Hot\n", + " ohe = OneHotEncoder(sparse=False, handle_unknown = \"ignore\")\n", + " features = [\"EDUCATION\", \"MARRIAGE\"]\n", + " temp = ohe.fit_transform(df[features])\n", + "\n", + " for i in range(len(ohe.get_feature_names())):\n", + " feature_name = ohe.get_feature_names()[i].split(\"_\")\n", + " feature_name = features[int(feature_name[0][1])] + \"_\" + feature_name[1] \n", + " temp_i = pd.DataFrame(temp[:, i], columns = [feature_name])\n", + " df = pd.concat([df, temp_i], axis = 1)\n", + "\n", + " for feature in features:\n", + " df = df.drop(feature, axis = 1)\n", + "\n", + " # Minmax\n", + " continuous = [\"AGE\"] + mixed_features\n", + " minmax = MinMaxScaler()\n", + " df[continuous] = minmax.fit_transform(df[continuous])\n", + "\n", + " return df" + ], + "outputs": [], + "execution_count": 2, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "#### Dataset Wrapper" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Here we convert the raw data to a standard dataset. We need to protect the feature that has bias. Here we should pretect 'SEX' in our data. We also need to specify the privileged group and unprivileged group in the feature. Here, the privileged group is male and unprivileged group is the female." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "file_path = \"https://archive.ics.uci.edu/ml/machine-learning-databases/00350/default%20of%20credit%20card%20clients.xls\"\n", + "df = pd.read_excel(file_path, skiprows = 1)\n", + "df['SEX'] = df['SEX']-1 # make male to 0 and female to 1\n", + "\n", + "privileged_groups = [{'SEX': 0}] # male\n", + "unprivileged_groups = [{'SEX': 1}] # female\n", + "label_name = \"default payment next month\"\n", + "favorable_classes = [1] # 1 means default of credit being true\n", + "protected_attribute_names = ['SEX']\n", + "privileged_classes = [[0]] # male\n", + "\n", + "metadata={'label_maps': [{1: 'Default', 0: 'Not Default'}]}\n", + "\n", + "orig_data = StandardDataset(df, \n", + " label_name, \n", + " favorable_classes, \n", + " protected_attribute_names, \n", + " privileged_classes,\n", + " custom_preprocessing=preprocess)\n", + "\n", + "np.random.seed(2080)\n", + "dataset_orig_train, dataset_orig_vt = orig_data.split([0.7], shuffle=True)\n", + "dataset_orig_valid, dataset_orig_test = dataset_orig_vt.split([0.5], shuffle=True)" + ], + "outputs": [], + "execution_count": 3, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Metric for the original dataset" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Now that we have identified the protected attribute 'SEX' and defined privileged and unprivileged values, we can use aif360 to detect bias in the dataset. One simple test is to compare the percentage of favorable results for the privileged and unprivileged groups, subtracting the former percentage from the latter. A negative value indicates that females are less likely having credit card default in the future. This is implemented in the method called mean_difference on the BinaryLabelDatasetMetric class. The code below performs this check and displays the output, showing that the difference is -0.034253." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "# Metric for the original dataset\n", + "metric_orig_train = BinaryLabelDatasetMetric(dataset_orig_train, \n", + " unprivileged_groups=unprivileged_groups,\n", + " privileged_groups=privileged_groups)\n", + "display(Markdown(\"#### Original training dataset\"))\n", + "print(\"Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_orig_train.mean_difference())" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/markdown": [ + "#### Original training dataset" + ], + "text/plain": [ + "" + ] + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Difference in mean outcomes between unprivileged and privileged groups = -0.034253\n" + ] + } + ], + "execution_count": 58, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Transform the training data\n", + "\n", + "We do see some bias between females and males. Now we need to adjust for this bias in our training. Reweighing is a preprocessing technique that reweighs each (group, label) combination differently to ensure fairness before classificatio" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "RW = Reweighing(unprivileged_groups=unprivileged_groups,\n", + " privileged_groups=privileged_groups)\n", + "RW.fit(dataset_orig_train)\n", + "dataset_transf_train = RW.transform(dataset_orig_train)" + ], + "outputs": [], + "execution_count": 4, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Check the mean difference between two groups again with the mean difference." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "metric_transf_train = BinaryLabelDatasetMetric(dataset_transf_train, \n", + " unprivileged_groups=unprivileged_groups,\n", + " privileged_groups=privileged_groups)\n", + "display(Markdown(\"#### Transformed training dataset\"))\n", + "print(\"Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_transf_train.mean_difference())" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/markdown": [ + "#### Transformed training dataset" + ], + "text/plain": [ + "" + ] + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Difference in mean outcomes between unprivileged and privileged groups = -0.000000\n" + ] + } + ], + "execution_count": 5, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Model comparison with fittings on different datasets\n", + "\n", + "We would like to see if the preprocssing of data would hurt the performance of the model. So we trained a simple Random Forest classifier on both original and transformed training data, then compare the Area Under ROC, namely AUC, on testing data." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "### Fit a Random Forest classifier with the original data" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "X_train = dataset_orig_train.features\n", + "y_train = dataset_orig_train.labels.ravel()\n", + "X_valid = dataset_orig_valid.features\n", + "y_valid = dataset_orig_valid.labels.ravel()\n", + "X_test = dataset_orig_test.features\n", + "y_test = dataset_orig_test.labels.ravel()\n", + "\n", + "random_state = 2080\n", + "max_depth = range(1,10) # max depths that the model can split further\n", + "minimum_splits = range(2,10) # minimum splits that the model can split further\n", + "accuracies = [] # validation accuracies\n", + "models = []\n", + "\n", + "# finding the best metrics\n", + "for d in max_depth:\n", + " for s in minimum_splits:\n", + " rfc = RandomForestClassifier(n_estimators=50, min_samples_split=s, max_depth=d, random_state=random_state)\n", + " rfc.fit(X_train,y_train, sample_weight=dataset_orig_train.instance_weights)\n", + " accuracies.append(accuracy_score(y_valid, rfc.predict(X_valid)))\n", + " models.append(rfc)\n", + "\n", + "# find the best model based on the validation accuracies\n", + "model = models[np.argmax(accuracies)]\n", + "\n", + "# calculate the false positive rate and true positive rate of our best model\n", + "fpr, tpr, threshold = roc_curve(y_test, model.predict_proba(X_test)[:,1])" + ], + "outputs": [], + "execution_count": 17, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "#### Visualize the ROC for model fitted on the original data" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "plt.plot(fpr, tpr, 'b', label = 'AUC = %0.2f' % auc(fpr, tpr))\n", + "plt.title('Receiver Operating Characteristic RF (Original Data)')\n", + "plt.legend(loc = 'lower right')\n", + "plt.plot([0, 1], [0, 1],'r--')\n", + "plt.xlim([0, 1])\n", + "plt.ylim([0, 1])\n", + "plt.ylabel('True Positive Rate')\n", + "plt.xlabel('False Positive Rate')\n", + "plt.show()" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": [ + "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\n" + ], + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + } + } + ], + "execution_count": 18, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "### Fit a Random Forest classifier with the transformed data" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "X_train = dataset_transf_train.features\n", + "y_train = dataset_transf_train.labels.ravel()\n", + "\n", + "random_state = 2080\n", + "max_depth = range(1,10)\n", + "minimum_splits = range(2,10)\n", + "accuracies = []\n", + "models = []\n", + "\n", + "# finding the best metrics\n", + "for d in max_depth:\n", + " for s in minimum_splits:\n", + " rfc = RandomForestClassifier(n_estimators=50, min_samples_split=s, max_depth=d, random_state=random_state)\n", + " rfc.fit(X_train,y_train, sample_weight=dataset_transf_train.instance_weights)\n", + " accuracies.append(accuracy_score(y_valid, rfc.predict(X_valid)))\n", + " models.append(rfc)\n", + "\n", + "# find the best model according to the accuracy score\n", + "model = models[np.argmax(accuracies)]\n", + "\n", + "# calculate the false positive rate and true positive rate of our best model\n", + "fpr, tpr, threshold = roc_curve(y_test, model.predict_proba(X_test)[:,1])" + ], + "outputs": [], + "execution_count": 19, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "#### Visualize the ROC for model fitted on the transformed data" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "plt.plot(fpr, tpr, 'b', label = 'AUC = %0.2f' % auc(fpr, tpr))\n", + "plt.title('Receiver Operating Characteristic RF (Transformed Data)')\n", + "plt.legend(loc = 'lower right')\n", + "plt.plot([0, 1], [0, 1],'r--')\n", + "plt.xlim([0, 1])\n", + "plt.ylim([0, 1])\n", + "plt.ylabel('True Positive Rate')\n", + "plt.xlabel('False Positive Rate')\n", + "plt.show()" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": [ + "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hQD23DNFtJfjOE7ZkLaK4uOPbXrggSGcXBVee82C+H36qQ2i8yB+juNkKGnbR/Hzzzbt2DGEk192Gbz4ommp/v1ht91CEMJxUp9NmzaRlZXF+vXrwxal3FC1alUaNWrEVmU4biBtFcUPP8COOyYxdEd0EL8zz4S2beHSS6FC2jbKHCfhZGVlUatWLZo0aYKkRZyd9EZVWbp0KVlZWTRt2rTMjpu2b7kaNaw7IClMm2ZpSG+7zZY7d7ZIr64kHKdI1q9fT926dV1JJAkRoW7dumXegkvLN11uLixdCo0aJfhEmzZZIu727WH69CRqJsfJHFxJJJdE1Hdamp4WLLBpdnYCTzJlCpx1lrm6nn46PPssNGiQwBM6juOkJmnZoti0yaYHHZTAk1SqBCtXwocfwnvvuZJwnDRm8ODBiAjTp0//b913333Hcccdl6/ceeedx6BBgwDriL/lllto0aIFbdq0Yd999+Xzzz/fYlkeeughmjdvzm677caXX34Zs0y3bt1o37497du3p0mTJrRv3x6At99++7/17du3p0KFCkyYMGGLZSqOtGxRbNxo0zIPBjhqlOWsfuwx82SaOdPjMzlOBjBgwAAOPPBABg4cyD333BPXPnfeeScLFy5k8uTJVKlShUWLFjFixIgtkmPq1KkMHDiQKVOmsGDBAg4//HBmzpxJxQJJy959993/5m+44Qa23nprAHr06EGPHj0AmDRpEieeeOJ/SiSRpOVbMNKiKDNFsWqV5VR9/nlo2tTm69VzJeE4Zci115oltyxp3x6eeqroMqtXr+aHH37g22+/5YQTTohLUaxdu5aXXnqJOXPmUKVKFQAaNGhA165dt0jejz76iO7du1OlShWaNm1K8+bNGTt2LPvtt1/M8qrKe++9x/DhwzfbNmDAAM4444wtkide0tL0FFG2ZeJ09Pnn0Lo19O1rd/KkSR7Ez3EyiCFDhnD00Uez6667su222/LLL78Uu8+sWbNo3LgxtWvXLrbsddddl88cFPn17t17s7J//fUXO+2003/LjRo14q+//ir02KNGjaJBgwa0iBEm+913302aokjLT+aIgjj88C080KpVcM45sN12FhOkU6ctls1xnNgU9+WfKAYMGMC1114LQPfu3RkwYAB77bVXod5BJfUaevLJJ+Muq6olOl9hrYYxY8ZQvXp12iQphlFaKorR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\n" + ], + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + } + } + ], + "execution_count": 20, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Conclusion" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "We do see that mitigating the gender effect on the model can reduce the mean difference between males and female in terms of their proportion of being default. The model fitted on the transformed data can also perform more fairly than the original dataset in terms of ethics. The ROC curves are a bit different but the AUC is not impacted largely, which is a good thing we would like to observe. This means that the model fitted on unbiased 'SEX' groups can evaluate people more fairly without paying too much attention on their sex." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [], + "outputs": [], + "execution_count": null, + "metadata": {} + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.7.6", + "mimetype": "text/x-python", + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "pygments_lexer": "ipython3", + "nbconvert_exporter": "python", + "file_extension": ".py" + }, + "nteract": { + "version": "0.22.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} \ No newline at end of file