diff --git a/.circleci/config.yml b/.circleci/config.yml index 04cab68..47f10df 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,6 +13,11 @@ jobs: pip3 install -r requirements.txt python3 -m tests.unit.TestBiasDetector + - run: + name: Unit Tests for Risk Calculator + command: | + python3 -m tests.unit.TestRiskCalculator + workflows: version: 2 test_and_run: diff --git a/README.md b/README.md index e1412f3..c160786 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,13 @@ The method `compare_root_variable_conditioned_groups` performs the same calculat For both methods the output is a tuple similar to the ones described for the FreqsVsRef method, but with an additional element given by the standard deviation of the distances, provided only when the root variable is a multi-class feature. +## Focus on the Risk Analysis +With the latest version (1.2) we introduce a Risk measurement, based on the results of the Bias Detector. Currently it's only accessible via the python API, but we plan to add a frontend option for it. It is implemented in the `brio/risk` sub-module. + +The methodology behind the risk computation will be soon published with a scientific paper. If you want to experiment with it already, you can use the method `compute_hazard_from_freqvsfreq_or_freqvsref` of the class `HazardFromBiasDetectionCalculator` upon each results from FreqVsFreq and FreqVsRef. The computed hazards need to be passed to `compute_risk` from `RiskCalculator`: this function will provide an overall measure of risk. + ## What's next -Currently (September 2023) we plan to implement functionalities for the Opacity section, which is now empty. Furthermore, we want to introduce a risk measurement analysis, which will provide an overall risk assessment of a model using a series of bias and opacity checks. +Currently (June 2024) we plan to implement functionalities for the Opacity section, which is now empty, and a more refined and accessible Risk section. ## Call to action! We hope to raise interest in the data science community and ask for support! Anyone interested in expanding and improving our tool is more than welcome! You can do that opening a pull request for a functionality you wish to include. Also bugs warnings are very important and welcome. diff --git a/VERSION.txt b/VERSION.txt index 3eefcb9..26aaba0 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -1.0.0 +1.2.0 diff --git a/brio/bias/FreqVsFreqBiasDetector.py b/brio/bias/FreqVsFreqBiasDetector.py index 2c55db4..d8098ff 100644 --- a/brio/bias/FreqVsFreqBiasDetector.py +++ b/brio/bias/FreqVsFreqBiasDetector.py @@ -1,7 +1,7 @@ from .BiasDetector import BiasDetector from .threshold_calculator import threshold_calculator from sklearn.utils.extmath import cartesian -from itertools import combinations +from itertools import combinations, compress from scipy.spatial.distance import jensenshannon import numpy as np @@ -45,16 +45,22 @@ def compute_distance_between_frequencies(self, for pair in combinations(observed_distribution, 2): # Squaring JS given that the scipy implementation has square root distance = jensenshannon(p=pair[0], q=pair[1], base=2)**2 - distances.append(distance) + # If no observation are present for one class, the JS distance will be a nan. + # Changing into None to keep the functionalities of Risk Measurement. + if np.isnan(distance): + distances.append(None) + else: + distances.append(distance) else: raise Exception("Only TVD or JS are supported as distances for freq_vs_freq analysis") - overall_distance = self.aggregating_function(distances) - - if len(distances) > 1: + #Keeping all the not None distances (relevant for multi-classe root variable scenarios) + distances_not_none = list(compress(distances, [d is not None for d in distances])) + overall_distance = self.aggregating_function(distances_not_none) if len(distances_not_none) > 0 else None + if len(distances_not_none) > 1: ## Computing the standard deviation of the distances in case of # multi-class root_variable - return overall_distance, np.std(distances) + return overall_distance, np.std(distances_not_none) else: return overall_distance, None @@ -158,13 +164,11 @@ def compare_root_variable_conditioned_groups(self, # Second parameter for threshold calculator A2 = len(root_variable_labels) - - conditioned_frequencies = {} - conditioning_variables_subsets = list(self.powerset(conditioning_variables)) # All the possible subsets of conditioning variables are inspected. The first one # is excluded being the empty set. + conditioned_frequencies = {} for conditioning_variables_subset in conditioning_variables_subsets[1:]: combinations = cartesian([dataframe[v].unique() for v in conditioning_variables_subset]) @@ -177,48 +181,52 @@ def compare_root_variable_conditioned_groups(self, dataframe_subset = dataframe.query(condition) num_of_obs = dataframe_subset.shape[0] - if num_of_obs >= min_obs_per_group: - if self.target_variable_type == 'class': - conditioned_frequencies[condition] = ( - num_of_obs, - self.get_frequencies_list( - dataframe_subset, - target_variable, - target_variable_labels, - root_variable, - root_variable_labels)[0] #taking the relative freqs, the absolute freqs are not needed here - ) - elif self.target_variable_type == 'probability': - conditioned_frequencies[condition] = ( - num_of_obs, - self.get_frequencies_list_from_probs( - dataframe_subset, - target_variable, - root_variable, - root_variable_labels, - n_bins)[0] #taking the relative freqs, the absolute freqs are not needed here - ) - - else: - conditioned_frequencies[condition] = (num_of_obs, None) + if self.target_variable_type == 'class': + conditioned_frequencies[condition] = ( + num_of_obs, + self.get_frequencies_list( + dataframe_subset, + target_variable, + target_variable_labels, + root_variable, + root_variable_labels)[0] #taking the relative freqs, the absolute freqs are not needed here + ) + elif self.target_variable_type == 'probability': + conditioned_frequencies[condition] = ( + num_of_obs, + self.get_frequencies_list_from_probs( + dataframe_subset, + target_variable, + root_variable, + root_variable_labels, + n_bins)[0] #taking the relative freqs, the absolute freqs are not needed here + ) distances = { # group: (number_of_observations, (overall_distance, standard_deviations) ) group: ( (obs_and_freqs[0], self.compute_distance_between_frequencies(obs_and_freqs[1]) # (distance, standard_deviations) - ) if obs_and_freqs[1] is not None else (obs_and_freqs[0], None) + ) ) for group, obs_and_freqs in conditioned_frequencies.items() } - - results = {group: ( - ( + + results = {} + for group, obs_and_dist in distances.items(): + # Too small groups + if obs_and_dist[0] < min_obs_per_group: + result = (obs_and_dist[0], None, 'Not enough observations') + # Groups for which distance is not defined (only one class available, JS computed) + elif obs_and_dist[1][0] is None: + result = (obs_and_dist[0], None, 'Distance non defined') + else: + result = ( obs_and_dist[0], #This will also be the A3 for threshold_calculator, being it the number of obs of the group obs_and_dist[1][0], #distance obs_and_dist[1][0]<=threshold_calculator(A1=self.A1, A2=A2, A3=obs_and_dist[0], default_threshold=threshold), threshold_calculator(A1=self.A1, A2=A2, A3=obs_and_dist[0], default_threshold=threshold), obs_and_dist[1][1] #standard deviation - ) if obs_and_dist[1] is not None else (obs_and_dist[0], obs_and_dist[1], 'Not enough observations') - ) for group, obs_and_dist in distances.items()} + ) + results[group] = result return results \ No newline at end of file diff --git a/brio/bias/FreqVsRefBiasDetector.py b/brio/bias/FreqVsRefBiasDetector.py index 533fb95..4ba6601 100644 --- a/brio/bias/FreqVsRefBiasDetector.py +++ b/brio/bias/FreqVsRefBiasDetector.py @@ -93,8 +93,13 @@ def compute_distance_from_reference(self, kl = kl_elementwise.sum() else: raise Exception("Only 'no','zero' and 'laplace' are supported as divergence adjustment methods.") + divergence = self.normalization_function(kl) - divergences.append(divergence) + + if np.isnan(divergence): + divergences.append(None) + else: + divergences.append(divergence) return divergences @@ -230,34 +235,30 @@ def compare_root_variable_conditioned_groups(self, dataframe_subset = dataframe.query(condition) num_of_obs = dataframe_subset.shape[0] - if num_of_obs >= min_obs_per_group: - if self.target_variable_type == 'class': - freqs, abs_freqs = self.get_frequencies_list( - dataframe_subset, - target_variable, - target_variable_labels, - root_variable, - root_variable_labels) - conditioned_frequencies[condition] = ( - num_of_obs, - freqs, - [sum(x) for x in abs_freqs] - ) - elif self.target_variable_type == 'probability': - freqs, abs_freqs = self.get_frequencies_list_from_probs( - dataframe_subset, - target_variable, - root_variable, - root_variable_labels, - n_bins) - conditioned_frequencies[condition] = ( - num_of_obs, - freqs, - [sum(x) for x in abs_freqs] - ) - - else: - conditioned_frequencies[condition] = (num_of_obs, None) + if self.target_variable_type == 'class': + freqs, abs_freqs = self.get_frequencies_list( + dataframe_subset, + target_variable, + target_variable_labels, + root_variable, + root_variable_labels) + conditioned_frequencies[condition] = ( + num_of_obs, + freqs, + [sum(x) for x in abs_freqs] + ) + elif self.target_variable_type == 'probability': + freqs, abs_freqs = self.get_frequencies_list_from_probs( + dataframe_subset, + target_variable, + root_variable, + root_variable_labels, + n_bins) + conditioned_frequencies[condition] = ( + num_of_obs, + freqs, + [sum(x) for x in abs_freqs] + ) distances = { group: ( @@ -266,17 +267,28 @@ def compare_root_variable_conditioned_groups(self, self.compute_distance_from_reference(observed_distribution=obs_and_freqs[1], reference_distribution=reference_distribution, n_obs=obs_and_freqs[2]) - ) if obs_and_freqs[1] is not None else (obs_and_freqs[0], None) + ) ) for group, obs_and_freqs in conditioned_frequencies.items() } - - results = {group: ( - ( - obs_and_dist[0], - obs_and_dist[1], - [d<=threshold_calculator(A1=self.A1, A2=A2, A3=obs_and_dist[0], default_threshold=threshold) for d in obs_and_dist[1]], + + results = {} + for group, obs_and_dist in distances.items(): + # Too small groups + if obs_and_dist[0] < min_obs_per_group: + result = (obs_and_dist[0], [None for d in obs_and_dist[1]], 'Not enough observations') + else: + result = ( + obs_and_dist[0], #obs + obs_and_dist[1], #distance + [d<=threshold_calculator( + A1=self.A1, + A2=A2, + A3=obs_and_dist[0], + default_threshold=threshold + ) if d is not None else 'Distance not defined' for d in obs_and_dist[1]], threshold_calculator(A1=self.A1, A2=A2, A3=obs_and_dist[0], default_threshold=threshold) - ) if obs_and_dist[1] is not None else (obs_and_dist[0], obs_and_dist[1], 'Not enough observations') - ) for group, obs_and_dist in distances.items()} + ) + + results[group] = result return results \ No newline at end of file diff --git a/brio/risk/HazardFromBiasDetectionCalculator.py b/brio/risk/HazardFromBiasDetectionCalculator.py new file mode 100644 index 0000000..8997f1e --- /dev/null +++ b/brio/risk/HazardFromBiasDetectionCalculator.py @@ -0,0 +1,96 @@ +import numpy as np + +class HazardFromBiasDetectionCalculator: + + ''' + This class manages the calculation of hazards for the + tests within the Bias module + ''' + + def as_list(self, x): + if type(x) is list: + return x + else: + return [x] + + def compute_hazard_from_freqvsfreq_or_freqvsref( + self, + overall_result, + conditioned_results, + tot_observations, + conditioning_variables, + weight_logic="group"): + + ''' + Computes the hazard for a FreqVsFreq or a FreqVsRef analysis. + + Args: + overall_result: dict with non-conditioned results from FreqVs* analysis + conditioned_result: dict with conditioned results from FreqVs* analysis #TODO handle when only overall result is available + tot_observation: num, total number of data points analyzed + conditioning_variables: list, conditioning variables used in FreqVs* analysis + weight_logic: str, it can be either "group" or "individual", it determines how much each single test will weight on the hazard result + ''' + + #tot number features=conditioning + root (+1) + n_features_total = len(conditioning_variables) + 1 + + hazard_overall = 0 + # Iterating over each reference distribution, if available (FreqVsRef) + # In case of FreqVsFreq, there will be a single iteration + num_iterations = len(self.as_list(overall_result[0])) + for k in np.arange(0, num_iterations): + + # test result, threshold, num_samples, boolean, num_used_features + #TODO use dict instead, and use explicit keys for readibility + test_results = [] + test_results.append(( + self.as_list(overall_result[0])[k], + overall_result[2], + tot_observations, + self.as_list(overall_result[1])[k], + 1 #for the overall test, only 1 feature used, the root variable + )) + + for group_name, group in conditioned_results.items(): + if (self.as_list(group[1])[k] is not None): + test_results.append( + ( + self.as_list(group[1])[k], #test result + group[3], #threshold + group[0], #num_samples + self.as_list(group[2])[k], #boolean + len(group_name.split("&"))+1 #num_used_features, cond.+root + ) + ) + + if weight_logic=="group": + #T_i in Risk Function document + weight_denominator = 0 + for line in test_results: + weight_denominator += n_features_total - line[4] + 1 + elif weight_logic=="individual": + #S_i in Risk Function document + weight_denominator = np.sum([x[4] for x in test_results]) + else: + raise Exception('Only "group" or "individual" are allowed for parameter weight_logic') + + + hazard = 0 + for line in test_results: + if weight_logic=="group": + c_info = n_features_total - line[4] + 1 + weight = c_info/weight_denominator + elif weight_logic=="individual": + weight = line[4]/weight_denominator + else: + raise Exception('Only "group" or "individual" are allowed for parameter weight_logic') + + delta = 1 if line[3]==False else 0 + q = line[2]/tot_observations + e = line[0] - line[1] + hazard += delta * weight * q * abs(e)**(1./3.) * line[1]**(1./3.) + + hazard_overall+= hazard + + return hazard_overall \ No newline at end of file diff --git a/brio/risk/RiskCalculator.py b/brio/risk/RiskCalculator.py new file mode 100644 index 0000000..ab4714f --- /dev/null +++ b/brio/risk/RiskCalculator.py @@ -0,0 +1,20 @@ +import numpy as np + +class RiskCalculator: + + def compute_risk(self, test_hazards): + ''' + Computes the overall risk using the hazards coming from the + different Bias and Opacity tests. + + Args: + test_hazards: list of hazards computed for a set of tests + + Returns: + risk: num, the overall measure of risk + ''' + # test_hazards = [list_of_hazards] + + risk = np.sum(test_hazards)/len(test_hazards) + + return risk \ No newline at end of file diff --git a/brio/risks/__init__.py b/brio/risk/__init__.py similarity index 100% rename from brio/risks/__init__.py rename to brio/risk/__init__.py diff --git a/frontend/views/bias_route/FreqvsFreq.py b/frontend/views/bias_route/FreqvsFreq.py index fd0ec0c..0303bca 100644 --- a/frontend/views/bias_route/FreqvsFreq.py +++ b/frontend/views/bias_route/FreqvsFreq.py @@ -62,6 +62,8 @@ def freqvsfreq(): dict_vars['predictions'] = request.form['predictions'] if 'agg_func' in list(request.form.keys()): dict_vars['agg_func'] = request.form['agg_func'] + else: + dict_vars['agg_func'] = max if float(request.form['Slider']) > 0: dict_vars['thr'] = float(request.form['Slider']) else: @@ -83,6 +85,7 @@ def results_fvf(): bd = FreqVsFreqBiasDetector( distance=dict_vars['distance'], + aggregating_function=dict_vars['agg_func'], A1=dict_vars['a1_param'], target_variable_type=dict_vars['target_type'] ) diff --git a/notebooks/RiskMeasure_experiments_2_WIP.ipynb b/notebooks/RiskMeasure_experiments_2_WIP.ipynb new file mode 100644 index 0000000..28737f8 --- /dev/null +++ b/notebooks/RiskMeasure_experiments_2_WIP.ipynb @@ -0,0 +1,2187 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "0b134d6e", + "metadata": {}, + "outputs": [], + "source": [ + "import os, sys\n", + "dir2 = os.path.abspath('')\n", + "dir1 = os.path.dirname(dir2)\n", + "if not dir1 in sys.path: sys.path.append(dir1)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "77c1e269", + "metadata": {}, + "outputs": [], + "source": [ + "from brio.utils.Preprocessing import Preprocessing\n", + "from sklearn.model_selection import train_test_split\n", + "from pickle import dump, load\n", + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "from brio.bias.FreqVsFreqBiasDetector import FreqVsFreqBiasDetector\n", + "from brio.bias.FreqVsRefBiasDetector import FreqVsRefBiasDetector" + ] + }, + { + "cell_type": "markdown", + "id": "68af6499", + "metadata": {}, + "source": [ + "## Importing Data and Trained Classifier" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "66127e6c", + "metadata": {}, + "outputs": [], + "source": [ + "input_data_path = \"../data/raw_data/uci-default-of-credit-card/data/data.csv\"\n", + "local_path_save = '../data/mlflow_artifacts/'" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "bf0e3b01", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/davideposillipo/.pyenv/versions/3.10.9/envs/prova/lib/python3.10/site-packages/sklearn/base.py:329: UserWarning: Trying to unpickle estimator OneHotEncoder from version 1.2.1 when using version 1.0.2. This might lead to breaking code or invalid results. Use at your own risk. For more info please refer to:\n", + "https://scikit-learn.org/stable/modules/model_persistence.html#security-maintainability-limitations\n", + " warnings.warn(\n", + "/Users/davideposillipo/.pyenv/versions/3.10.9/envs/prova/lib/python3.10/site-packages/sklearn/base.py:329: UserWarning: Trying to unpickle estimator StandardScaler from version 1.2.1 when using version 1.0.2. This might lead to breaking code or invalid results. Use at your own risk. For more info please refer to:\n", + "https://scikit-learn.org/stable/modules/model_persistence.html#security-maintainability-limitations\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "fitted_ohe = load(open(local_path_save + '_ohe.pkl', 'rb')) \n", + "fitted_scaler = load(open(local_path_save + '_scaler.pkl', 'rb'))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6646c312", + "metadata": {}, + "outputs": [], + "source": [ + "pp = Preprocessing(input_data_path, \"default\")\n", + "X, Y = pp.read_dataframe()\n", + "\n", + "X_train, X_test, Y_train, Y_test = train_test_split(X,Y, test_size=0.3, random_state=420)\n", + "\n", + "X_test_ohe, _, _ = pp.preprocess_for_classification(df=X_test, \n", + " fit_ohe=True, \n", + " fitted_ohe=fitted_ohe,\n", + " perform_scaling=True,\n", + " fitted_scaler=fitted_scaler)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "ba010d39", + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"./mlruns/1/1e4a0667c7a64cbe8c7b023410e5781c/artifacts/model/model.pkl\", \"rb\") as file:\n", + " classifier = load(file)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "04cacf92", + "metadata": {}, + "outputs": [], + "source": [ + "predicted_prob = classifier.predict_proba(X_test_ohe)\n", + "predicted_values = classifier.predict(X_test_ohe)" + ] + }, + { + "cell_type": "markdown", + "id": "01057c6d", + "metadata": {}, + "source": [ + "#### Definition of conditioning variables" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d7e96a84", + "metadata": {}, + "outputs": [], + "source": [ + "def age_buckets(x):\n", + " if x < 30:\n", + " return 1\n", + " elif x < 40:\n", + " return 2\n", + " else:\n", + " return 3\n", + "\n", + "X_test['age_buckets'] = X.x5_age.apply(age_buckets)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "c24a0c9c", + "metadata": {}, + "outputs": [], + "source": [ + "conditioning_variables = ['x3_education', 'x4_marriage', 'age_buckets']" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "7950602d", + "metadata": {}, + "outputs": [], + "source": [ + "df_with_predictions = pd.concat(\n", + " [X_test.reset_index(drop=True), pd.Series(predicted_values)], axis=1).rename(columns={0:\"predictions\"})" + ] + }, + { + "cell_type": "markdown", + "id": "d6f80bfb", + "metadata": {}, + "source": [ + "## Hazard and risk functions" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "7e6183a2", + "metadata": {}, + "outputs": [], + "source": [ + "def hazard_function(overall_result, conditioned_results, tot_observations):\n", + " \n", + " # test result, threshold, num_samples, boolean\n", + " test_results = []\n", + " test_results.append((overall_result[0], \n", + " overall_result[2], \n", + " tot_observations, \n", + " overall_result[1]))\n", + " \n", + " for group in conditioned_results.values():\n", + " if (group[1] is not None):\n", + " test_results.append((group[1], group[3], group[0], group[2]))\n", + " \n", + " hazard = 0\n", + " for line in test_results:\n", + " weight = 1 #to be implemented\n", + " delta = 1 if line[3]==False else 0\n", + " q = line[2]/tot_observations\n", + " e = line[0] - line[1]\n", + " hazard += delta * weight * q * e\n", + " \n", + " average_threshold = np.mean([x[1] for x in test_results])\n", + " \n", + " return hazard, average_threshold" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "a1bdeff0", + "metadata": {}, + "outputs": [], + "source": [ + "def hazard_function_2(overall_result, conditioned_results, tot_observations):\n", + " \n", + " # test result, threshold, num_samples, boolean\n", + " test_results = []\n", + " test_results.append((overall_result[0], \n", + " overall_result[2], \n", + " tot_observations, \n", + " overall_result[1]))\n", + " \n", + " for group in conditioned_results.values():\n", + " if (group[1] is not None):\n", + " test_results.append((group[1], group[3], group[0], group[2]))\n", + " \n", + " hazard = 0\n", + " for line in test_results:\n", + " weight = 1 #to be implemented\n", + " delta = 1 if line[3]==False else 0\n", + " q = line[2]/tot_observations\n", + " e = line[0] - line[1]\n", + " hazard += delta * weight * q * e * line[1] #aggiunta di threshold del singolo gruppo\n", + " \n", + " average_threshold = np.mean([x[1] for x in test_results])\n", + " \n", + " return hazard, average_threshold" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "9dec052f", + "metadata": {}, + "outputs": [], + "source": [ + "def risk_function(test_hazards, average_thresholds):\n", + " # test_hazards = [list_of_hazards]\n", + " # average_thresholds = [mean(thresholds_of_test1), mean(thresholds_of_a_test2), ...], \n", + " # needed if automatic threshold is used\n", + " risk = 0\n", + " for hazard, threshold in zip(test_hazards, average_thresholds):\n", + " risk += hazard * threshold\n", + " \n", + " risk = risk/len(test_hazards)**2\n", + " \n", + " return risk" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "a61a651d", + "metadata": {}, + "outputs": [], + "source": [ + "def risk_function_2(test_hazards, average_thresholds):\n", + " # test_hazards = [list_of_hazards]\n", + " # average_thresholds = [mean(thresholds_of_test1), mean(thresholds_of_a_test2), ...], \n", + " # needed if automatic threshold is used\n", + " risk = 0\n", + " for hazard, threshold in zip(test_hazards, average_thresholds):\n", + " risk += hazard # tolto threshold\n", + " \n", + " risk = risk/len(test_hazards)**2\n", + " \n", + " return risk" + ] + }, + { + "cell_type": "markdown", + "id": "0e6e5723", + "metadata": {}, + "source": [ + "### Test 1: TVD, A1=high" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "38346302", + "metadata": {}, + "outputs": [], + "source": [ + "bd_1 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"high\")" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "ebde5b3d", + "metadata": {}, + "outputs": [], + "source": [ + "overall_1 = bd_1.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "9dc1af6e", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_1 = bd_1.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "e4ad51ba", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_1, average_threshold_1 = hazard_function(\n", + " overall_1, \n", + " conditioned_1, \n", + " df_with_predictions.shape[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "ec7f74f2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.09976465885178575" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hazard_test_1" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "cbf707be", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_1_2, average_threshold_1_2 = hazard_function_2(\n", + " overall_1, \n", + " conditioned_1, \n", + " df_with_predictions.shape[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "3ecfd390", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.0016526941966088404" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hazard_test_1_2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8e4aa9c2", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "49f2d0fe", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0ae31dc3", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55e07a3c", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "e7914be4", + "metadata": {}, + "source": [ + "### Test 2 (TVD, low)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "e8377772", + "metadata": {}, + "outputs": [], + "source": [ + "bd_2 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"low\")" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "14e80b7e", + "metadata": {}, + "outputs": [], + "source": [ + "overall_2 = bd_2.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "468b603a", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_2 = bd_2.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "4016a74d", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_2, average_threshold_2 = hazard_function(\n", + " overall_2, \n", + " conditioned_2, \n", + " df_with_predictions.shape[0])" + ] + }, + { + "cell_type": "markdown", + "id": "847b9871", + "metadata": {}, + "source": [ + "### Test 3 (JS, high)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "e8ce1a46", + "metadata": {}, + "outputs": [], + "source": [ + "bd_3 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"high\")" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "5817e2d8", + "metadata": {}, + "outputs": [], + "source": [ + "overall_3 = bd_3.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "ff84ad8a", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_3 = bd_3.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "1043e2b1", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_3, average_threshold_3 = hazard_function(\n", + " overall_3, \n", + " conditioned_3, \n", + " df_with_predictions.shape[0])" + ] + }, + { + "cell_type": "markdown", + "id": "e65d63c0", + "metadata": {}, + "source": [ + "### Test 4 (JS, low)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "8bd6ad0f", + "metadata": {}, + "outputs": [], + "source": [ + "bd_4 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"low\")" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "f35b30be", + "metadata": {}, + "outputs": [], + "source": [ + "overall_4 = bd_4.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "3ba5c71c", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_4 = bd_4.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "b11aedbb", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_4, average_threshold_4 = hazard_function(\n", + " overall_4, \n", + " conditioned_4, \n", + " df_with_predictions.shape[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "21c1a238", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(0.0011441803173238346, True, 0.038868585412256317, None)" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "overall_4" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "cf25ff2c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'x3_education==1': (3119,\n", + " 0.000889500656873715,\n", + " True,\n", + " 0.03895143959289674,\n", + " None),\n", + " 'x3_education==3': (1499,\n", + " 0.0015440397130407938,\n", + " True,\n", + " 0.03904057062398841,\n", + " None),\n", + " 'x3_education==2': (4250,\n", + " 0.0014069427700605507,\n", + " True,\n", + " 0.038922567122490655,\n", + " None),\n", + " 'x3_education==4': (40, 0.0, True, 0.04052878118384472, None),\n", + " 'x3_education==5': (75, 0.01773188348797698, True, 0.04004903810567666, None),\n", + " 'x3_education==6': (14, None, 'Not enough observations'),\n", + " 'x3_education==0': (3, None, 'Not enough observations'),\n", + " 'x4_marriage==1': (4065,\n", + " 0.0006622420845844328,\n", + " True,\n", + " 0.03892645023759367,\n", + " None),\n", + " 'x4_marriage==2': (4822,\n", + " 0.0017816477735895428,\n", + " True,\n", + " 0.03891200891721621,\n", + " None),\n", + " 'x4_marriage==3': (95, 0.005139203671928956, True, 0.0399042256460958, None),\n", + " 'x4_marriage==0': (18, None, 'Not enough observations'),\n", + " 'age_buckets==3': (2727,\n", + " 0.0005520467561810636,\n", + " True,\n", + " 0.038965431871108035,\n", + " None),\n", + " 'age_buckets==1': (2895,\n", + " 0.00014080595312827762,\n", + " True,\n", + " 0.03895908758112406,\n", + " None),\n", + " 'age_buckets==2': (3378,\n", + " 0.004642843764858481,\n", + " True,\n", + " 0.03894356315834885,\n", + " None),\n", + " 'x3_education==1 & x4_marriage==1': (1106,\n", + " 0.0013808097053743882,\n", + " True,\n", + " 0.0390882789383699,\n", + " None),\n", + " 'x3_education==1 & x4_marriage==2': (2002,\n", + " 0.0007714976131269403,\n", + " True,\n", + " 0.03900143196290057,\n", + " None),\n", + " 'x3_education==1 & x4_marriage==3': (10, None, 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==0': (1, None, 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==1': (842,\n", + " 0.0013293644451187769,\n", + " True,\n", + " 0.03913770060319752,\n", + " None),\n", + " 'x3_education==3 & x4_marriage==2': (616,\n", + " 0.0026766502047438972,\n", + " True,\n", + " 0.039203275417264274,\n", + " None),\n", + " 'x3_education==3 & x4_marriage==3': (26, None, 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==0': (15, None, 'Not enough observations'),\n", + " 'x3_education==2 & x4_marriage==1': (2047,\n", + " 0.0008843782698063716,\n", + " True,\n", + " 0.038998652941457684,\n", + " None),\n", + " 'x3_education==2 & x4_marriage==2': (2145,\n", + " 0.0020037880399754724,\n", + " True,\n", + " 0.038992906353361736,\n", + " None),\n", + " 'x3_education==2 & x4_marriage==3': (56,\n", + " 0.0034056180121872144,\n", + " True,\n", + " 0.04025334448575739,\n", + " None),\n", + " 'x3_education==2 & x4_marriage==0': (2, None, 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==1': (17, None, 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==2': (21, None, 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==3': (2, None, 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==0': (0, None, 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==1': (45,\n", + " 0.016319772563106846,\n", + " True,\n", + " 0.040427050983124845,\n", + " None),\n", + " 'x3_education==5 & x4_marriage==2': (29, None, 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==3': (1, None, 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==0': (0, None, 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==1': (7, None, 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==2': (7, None, 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==3': (0, None, 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==0': (0, None, 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==1': (1, None, 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==2': (2, None, 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==3': (0, None, 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==0': (0, None, 'Not enough observations'),\n", + " 'x3_education==1 & age_buckets==3': (710,\n", + " 9.289286910588404e-05,\n", + " True,\n", + " 0.039172204976585454,\n", + " None),\n", + " 'x3_education==1 & age_buckets==1': (1070,\n", + " 9.344831622309132e-05,\n", + " True,\n", + " 0.03909392253529011,\n", + " None),\n", + " 'x3_education==1 & age_buckets==2': (1339,\n", + " 0.003380171689433621,\n", + " True,\n", + " 0.03905744131846861,\n", + " None),\n", + " 'x3_education==3 & age_buckets==3': (783,\n", + " 0.002279727387873382,\n", + " True,\n", + " 0.039152042200564174,\n", + " None),\n", + " 'x3_education==3 & age_buckets==1': (281,\n", + " 0.0028387729486277547,\n", + " True,\n", + " 0.039421118734555886,\n", + " None),\n", + " 'x3_education==3 & age_buckets==2': (435,\n", + " 0.007446428652865581,\n", + " True,\n", + " 0.03928939621417106,\n", + " None),\n", + " 'x3_education==2 & age_buckets==3': (1180,\n", + " 0.0004958039568485653,\n", + " True,\n", + " 0.03907750016172852,\n", + " None),\n", + " 'x3_education==2 & age_buckets==1': (1502,\n", + " 0.000498442393993108,\n", + " True,\n", + " 0.0390402802952325,\n", + " None),\n", + " 'x3_education==2 & age_buckets==2': (1568,\n", + " 0.005620102489719185,\n", + " True,\n", + " 0.039034105403155314,\n", + " None),\n", + " 'x3_education==4 & age_buckets==3': (13, None, 'Not enough observations'),\n", + " 'x3_education==4 & age_buckets==1': (15, None, 'Not enough observations'),\n", + " 'x3_education==4 & age_buckets==2': (12, None, 'Not enough observations'),\n", + " 'x3_education==5 & age_buckets==3': (28, None, 'Not enough observations'),\n", + " 'x3_education==5 & age_buckets==1': (26, None, 'Not enough observations'),\n", + " 'x3_education==5 & age_buckets==2': (21, None, 'Not enough observations'),\n", + " 'x3_education==6 & age_buckets==3': (12, None, 'Not enough observations'),\n", + " 'x3_education==6 & age_buckets==1': (1, None, 'Not enough observations'),\n", + " 'x3_education==6 & age_buckets==2': (1, None, 'Not enough observations'),\n", + " 'x3_education==0 & age_buckets==3': (1, None, 'Not enough observations'),\n", + " 'x3_education==0 & age_buckets==1': (0, None, 'Not enough observations'),\n", + " 'x3_education==0 & age_buckets==2': (2, None, 'Not enough observations'),\n", + " 'x4_marriage==1 & age_buckets==3': (1973,\n", + " 0.0005954671163637724,\n", + " True,\n", + " 0.03900327304970935,\n", + " None),\n", + " 'x4_marriage==1 & age_buckets==1': (433,\n", + " 0.0006050564306400878,\n", + " True,\n", + " 0.03929064049774874,\n", + " None),\n", + " 'x4_marriage==1 & age_buckets==2': (1659,\n", + " 0.0025308859076596394,\n", + " True,\n", + " 0.039026203596578886,\n", + " None),\n", + " 'x4_marriage==2 & age_buckets==3': (682,\n", + " 0.000984116705666417,\n", + " True,\n", + " 0.03918078476435046,\n", + " None),\n", + " 'x4_marriage==2 & age_buckets==1': (2450,\n", + " 0.0004679756788383263,\n", + " True,\n", + " 0.038977284322524244,\n", + " None),\n", + " 'x4_marriage==2 & age_buckets==2': (1690,\n", + " 0.008770217406302681,\n", + " True,\n", + " 0.03902365864366842,\n", + " None),\n", + " 'x4_marriage==3 & age_buckets==3': (67,\n", + " 0.006048351225986506,\n", + " True,\n", + " 0.04012440624900843,\n", + " None),\n", + " 'x4_marriage==3 & age_buckets==1': (9, None, 'Not enough observations'),\n", + " 'x4_marriage==3 & age_buckets==2': (19, None, 'Not enough observations'),\n", + " 'x4_marriage==0 & age_buckets==3': (5, None, 'Not enough observations'),\n", + " 'x4_marriage==0 & age_buckets==1': (3, None, 'Not enough observations'),\n", + " 'x4_marriage==0 & age_buckets==2': (10, None, 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==1 & age_buckets==3': (530,\n", + " 0.0016115417796606346,\n", + " True,\n", + " 0.03923866877310845,\n", + " None),\n", + " 'x3_education==1 & x4_marriage==1 & age_buckets==1': (57,\n", + " 0.0006475595413858937,\n", + " True,\n", + " 0.040240098901698176,\n", + " None),\n", + " 'x3_education==1 & x4_marriage==1 & age_buckets==2': (519,\n", + " 0.00026135130212967203,\n", + " True,\n", + " 0.039243820191469415,\n", + " None),\n", + " 'x3_education==1 & x4_marriage==2 & age_buckets==3': (174,\n", + " 0.0032975398163250617,\n", + " True,\n", + " 0.039602860299026266,\n", + " None),\n", + " 'x3_education==1 & x4_marriage==2 & age_buckets==1': (1013,\n", + " 7.255783873653612e-05,\n", + " True,\n", + " 0.039103466125778766,\n", + " None),\n", + " 'x3_education==1 & x4_marriage==2 & age_buckets==2': (815,\n", + " 0.0055297298572293775,\n", + " True,\n", + " 0.039144070312308536,\n", + " None),\n", + " 'x3_education==1 & x4_marriage==3 & age_buckets==3': (6,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==3 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==3 & age_buckets==2': (4,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==0 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==0 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==0 & age_buckets==2': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==1 & age_buckets==3': (540,\n", + " 0.0016661560238569815,\n", + " True,\n", + " 0.039234122918275924,\n", + " None),\n", + " 'x3_education==3 & x4_marriage==1 & age_buckets==1': (66,\n", + " 0.001641687659141143,\n", + " True,\n", + " 0.040134779273517496,\n", + " None),\n", + " 'x3_education==3 & x4_marriage==1 & age_buckets==2': (236,\n", + " 0.0031946627324049887,\n", + " True,\n", + " 0.03948231262426713,\n", + " None),\n", + " 'x3_education==3 & x4_marriage==2 & age_buckets==3': (215,\n", + " 0.006229793987585709,\n", + " True,\n", + " 0.039517243631904286,\n", + " None),\n", + " 'x3_education==3 & x4_marriage==2 & age_buckets==1': (212,\n", + " 0.0018314701557554697,\n", + " True,\n", + " 0.039522653172211375,\n", + " None),\n", + " 'x3_education==3 & x4_marriage==2 & age_buckets==2': (189,\n", + " 0.022452053043175157,\n", + " True,\n", + " 0.03956831708838497,\n", + " None),\n", + " 'x3_education==3 & x4_marriage==3 & age_buckets==3': (23,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==3 & age_buckets==1': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==3 & age_buckets==2': (2,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==0 & age_buckets==3': (5,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==0 & age_buckets==1': (2,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==0 & age_buckets==2': (8,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==2 & x4_marriage==1 & age_buckets==3': (865,\n", + " 0.00035057107813314626,\n", + " True,\n", + " 0.0391325114755164,\n", + " None),\n", + " 'x3_education==2 & x4_marriage==1 & age_buckets==1': (298,\n", + " 0.0002290790469398784,\n", + " True,\n", + " 0.03940169500215893,\n", + " None),\n", + " 'x3_education==2 & x4_marriage==1 & age_buckets==2': (884,\n", + " 0.005110244605296763,\n", + " True,\n", + " 0.039128378446622925,\n", + " None),\n", + " 'x3_education==2 & x4_marriage==2 & age_buckets==3': (278,\n", + " 0.0019505471745487094,\n", + " True,\n", + " 0.039424730161892074,\n", + " None),\n", + " 'x3_education==2 & x4_marriage==2 & age_buckets==1': (1196,\n", + " 0.0009740553778556391,\n", + " True,\n", + " 0.039075302149231016,\n", + " None),\n", + " 'x3_education==2 & x4_marriage==2 & age_buckets==2': (671,\n", + " 0.008619822290895059,\n", + " True,\n", + " 0.039184301433021235,\n", + " None),\n", + " 'x3_education==2 & x4_marriage==3 & age_buckets==3': (37,\n", + " 0.0032043535726546716,\n", + " True,\n", + " 0.04059948860718527,\n", + " None),\n", + " 'x3_education==2 & x4_marriage==3 & age_buckets==1': (7,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==2 & x4_marriage==3 & age_buckets==2': (12,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==2 & x4_marriage==0 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==2 & x4_marriage==0 & age_buckets==1': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==2 & x4_marriage==0 & age_buckets==2': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==1 & age_buckets==3': (9,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==1 & age_buckets==1': (2,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==1 & age_buckets==2': (6,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==2 & age_buckets==3': (3,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==2 & age_buckets==1': (12,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==2 & age_buckets==2': (6,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==3 & age_buckets==3': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==3 & age_buckets==1': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==3 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==0 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==0 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==0 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==1 & age_buckets==3': (22,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==1 & age_buckets==1': (10,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==1 & age_buckets==2': (13,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==2 & age_buckets==3': (6,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==2 & age_buckets==1': (16,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==2 & age_buckets==2': (7,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==3 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==3 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==3 & age_buckets==2': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==0 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==0 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==0 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==1 & age_buckets==3': (6,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==1 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==1 & age_buckets==2': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==2 & age_buckets==3': (6,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==2 & age_buckets==1': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==2 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==3 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==3 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==3 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==0 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==0 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==0 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==1 & age_buckets==3': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==1 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==1 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==2 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==2 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==2 & age_buckets==2': (2,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==3 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==3 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==3 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==0 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==0 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==0 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations')}" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conditioned_4" + ] + }, + { + "cell_type": "markdown", + "id": "6b08c2f2", + "metadata": {}, + "source": [ + "## Risk results" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "0c8805e1", + "metadata": {}, + "outputs": [], + "source": [ + "hazards = [hazard_test_1, hazard_test_2, hazard_test_3, hazard_test_4]\n", + "average_thresholds = [average_threshold_1, average_threshold_2, average_threshold_3, average_threshold_4]" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "df958149", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.00015458111237839916" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "risk_function(hazards, average_thresholds)" + ] + }, + { + "cell_type": "markdown", + "id": "811da932", + "metadata": {}, + "source": [ + "# Experiments with 3 models" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "3022aa0b", + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"./trained_model_for_testing/RF_12_200.pkl\", \"rb\") as file:\n", + " classifier_1 = load(file)\n", + " \n", + "with open(\"./trained_model_for_testing/RF_37_10.pkl\", \"rb\") as file:\n", + " classifier_2 = load(file)\n", + " \n", + "with open(\"./trained_model_for_testing/Tree_depth2.pkl\", \"rb\") as file:\n", + " classifier_3 = load(file)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "b985b114", + "metadata": {}, + "outputs": [], + "source": [ + "predicted_prob_1 = classifier_1.predict_proba(X_test_ohe)\n", + "predicted_values_1 = classifier_1.predict(X_test_ohe)\n", + "df_with_predictions_1 = pd.concat(\n", + " [X_test.reset_index(drop=True), \n", + " pd.Series(predicted_values_1)], axis=1).rename(columns={0:\"predictions\"})\n", + "\n", + "predicted_prob_2 = classifier_2.predict_proba(X_test_ohe)\n", + "predicted_values_2 = classifier_2.predict(X_test_ohe)\n", + "df_with_predictions_2 = pd.concat(\n", + " [X_test.reset_index(drop=True), \n", + " pd.Series(predicted_values_2)], axis=1).rename(columns={0:\"predictions\"})\n", + "\n", + "predicted_prob_3 = classifier_3.predict_proba(X_test_ohe)\n", + "predicted_values_3 = classifier_3.predict(X_test_ohe)\n", + "df_with_predictions_3 = pd.concat(\n", + " [X_test.reset_index(drop=True), \n", + " pd.Series(predicted_values_3)], axis=1).rename(columns={0:\"predictions\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "23ba3a67", + "metadata": {}, + "outputs": [], + "source": [ + "def test_model(data_frame):\n", + " ### Test 1: TVD, A1=high\n", + "\n", + " bd_1 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"high\")\n", + "\n", + " overall_1 = bd_1.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_1 = bd_1.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_1, average_threshold_1 = hazard_function(\n", + " overall_1, \n", + " conditioned_1, \n", + " data_frame.shape[0])\n", + " \n", + " print(\"Test 1 (TVD, A1=high) hazard: \", hazard_test_1)\n", + "\n", + " ### Test 2 (TVD, low)\n", + "\n", + " bd_2 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"low\")\n", + "\n", + " overall_2 = bd_2.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_2 = bd_2.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_2, average_threshold_2 = hazard_function(\n", + " overall_2, \n", + " conditioned_2, \n", + " data_frame.shape[0])\n", + " \n", + " print(\"Test 2 (TVD, A1=low) hazard: \", hazard_test_2)\n", + "\n", + " ### Test 3 (JS, high)\n", + "\n", + " bd_3 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"high\")\n", + "\n", + " overall_3 = bd_3.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_3 = bd_3.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_3, average_threshold_3 = hazard_function(\n", + " overall_3, \n", + " conditioned_3, \n", + " data_frame.shape[0])\n", + " \n", + " print(\"Test 3 (JS, A1=high) hazard: \", hazard_test_3)\n", + "\n", + " ### Test 4 (JS, low)\n", + "\n", + " bd_4 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"low\")\n", + "\n", + " overall_4 = bd_4.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_4 = bd_4.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_4, average_threshold_4 = hazard_function(\n", + " overall_4, \n", + " conditioned_4, \n", + " data_frame.shape[0])\n", + " \n", + " print(\"Test 4 (JS, A1=low) hazard: \", hazard_test_4)\n", + " \n", + " hazards = [hazard_test_1, hazard_test_2, hazard_test_3, hazard_test_4]\n", + " average_thresholds = [average_threshold_1, \n", + " average_threshold_2, average_threshold_3, average_threshold_4]\n", + " \n", + " return risk_function(hazards, average_thresholds)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "7f9c5d36", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test 1 (TVD, A1=high) hazard: 0.09976465885178575\n", + "Test 2 (TVD, A1=low) hazard: 0.02015304845287825\n", + "Test 3 (JS, A1=high) hazard: 0.00011458216656976323\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model RF_12_200: 0.00015458111237839916\n", + "\n", + "\n", + "Test 1 (TVD, A1=high) hazard: 0.09085147869902101\n", + "Test 2 (TVD, A1=low) hazard: 0.014801760181546463\n", + "Test 3 (JS, A1=high) hazard: 1.52371151916934e-06\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model RF_37_10: 0.00013193466737245095\n", + "\n", + "\n", + "Test 1 (TVD, A1=high) hazard: 0.03355105791241006\n", + "Test 2 (TVD, A1=low) hazard: 0.006384298991373367\n", + "Test 3 (JS, A1=high) hazard: 0.00014383137973982362\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model Tree_depth2: 5.113018082906323e-05\n", + "\n", + "\n" + ] + } + ], + "source": [ + "for model, df in zip([\"RF_12_200\", \"RF_37_10\", \"Tree_depth2\"],\n", + " [df_with_predictions_1, df_with_predictions_2, df_with_predictions_3]):\n", + " print(f\"Overall risk measure for model {model}: \", test_model(df))\n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6f6f9ae", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6dad0e13", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc7a0765", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "ab6c0a6a", + "metadata": {}, + "outputs": [], + "source": [ + "def test_model_2(data_frame):\n", + " ### Test 1: TVD, A1=high\n", + "\n", + " bd_1 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"high\")\n", + "\n", + " overall_1 = bd_1.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_1 = bd_1.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_1, average_threshold_1 = hazard_function_2(\n", + " overall_1, \n", + " conditioned_1, \n", + " data_frame.shape[0])\n", + " \n", + " print(\"Test 1 (TVD, A1=high) hazard: \", hazard_test_1)\n", + "\n", + " ### Test 2 (TVD, low)\n", + "\n", + " bd_2 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"low\")\n", + "\n", + " overall_2 = bd_2.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_2 = bd_2.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_2, average_threshold_2 = hazard_function_2(\n", + " overall_2, \n", + " conditioned_2, \n", + " data_frame.shape[0])\n", + " \n", + " print(\"Test 2 (TVD, A1=low) hazard: \", hazard_test_2)\n", + "\n", + " ### Test 3 (JS, high)\n", + "\n", + " bd_3 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"high\")\n", + "\n", + " overall_3 = bd_3.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_3 = bd_3.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_3, average_threshold_3 = hazard_function_2(\n", + " overall_3, \n", + " conditioned_3, \n", + " data_frame.shape[0])\n", + " \n", + " print(\"Test 3 (JS, A1=high) hazard: \", hazard_test_3)\n", + "\n", + " ### Test 4 (JS, low)\n", + "\n", + " bd_4 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"low\")\n", + "\n", + " overall_4 = bd_4.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_4 = bd_4.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_4, average_threshold_4 = hazard_function_2(\n", + " overall_4, \n", + " conditioned_4, \n", + " data_frame.shape[0])\n", + " \n", + " print(\"Test 4 (JS, A1=low) hazard: \", hazard_test_4)\n", + " \n", + " hazards = [hazard_test_1, hazard_test_2, hazard_test_3, hazard_test_4]\n", + " average_thresholds = [average_threshold_1, \n", + " average_threshold_2, average_threshold_3, average_threshold_4]\n", + " \n", + " return risk_function_2(hazards, average_thresholds)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "9626cff1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test 1 (TVD, A1=high) hazard: 0.0016526941966088404\n", + "Test 2 (TVD, A1=low) hazard: 0.0007892524565281126\n", + "Test 3 (JS, A1=high) hazard: 1.956457231838417e-06\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model RF_12_200: 0.00015274394439804945\n", + "\n", + "\n", + "Test 1 (TVD, A1=high) hazard: 0.0015049775936835396\n", + "Test 2 (TVD, A1=low) hazard: 0.0005801440913963854\n", + "Test 3 (JS, A1=high) hazard: 2.6739671511961216e-08\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model RF_37_10: 0.0001303217765469648\n", + "\n", + "\n", + "Test 1 (TVD, A1=high) hazard: 0.0005595555272103964\n", + "Test 2 (TVD, A1=low) hazard: 0.00025096748221272835\n", + "Test 3 (JS, A1=high) hazard: 2.4731412590394615e-06\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model Tree_depth2: 5.081225941763526e-05\n", + "\n", + "\n" + ] + } + ], + "source": [ + "for model, df in zip([\"RF_12_200\", \"RF_37_10\", \"Tree_depth2\"],\n", + " [df_with_predictions_1, df_with_predictions_2, df_with_predictions_3]):\n", + " print(f\"Overall risk measure for model {model}: \", test_model_2(df))\n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "67c01cb1", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test 1 (TVD, A1=high) hazard: 0.09976465885178575\n", + "Test 2 (TVD, A1=low) hazard: 0.02015304845287825\n", + "Test 3 (JS, A1=high) hazard: 0.00011458216656976323\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model RF_12_200: 0.00015458111237839916\n", + "\n", + "\n", + "Test 1 (TVD, A1=high) hazard: 0.09085147869902101\n", + "Test 2 (TVD, A1=low) hazard: 0.014801760181546463\n", + "Test 3 (JS, A1=high) hazard: 1.52371151916934e-06\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model RF_37_10: 0.00013193466737245095\n", + "\n", + "\n", + "Test 1 (TVD, A1=high) hazard: 0.03355105791241006\n", + "Test 2 (TVD, A1=low) hazard: 0.006384298991373367\n", + "Test 3 (JS, A1=high) hazard: 0.00014383137973982362\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model Tree_depth2: 5.113018082906323e-05\n", + "\n", + "\n" + ] + } + ], + "source": [ + "for model, df in zip([\"RF_12_200\", \"RF_37_10\", \"Tree_depth2\"],\n", + " [df_with_predictions_1, df_with_predictions_2, df_with_predictions_3]):\n", + " print(f\"Overall risk measure for model {model}: \", test_model(df))\n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d0a8bc0", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93a740fc", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3d508927", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "23ed8452", + "metadata": {}, + "outputs": [], + "source": [ + "bd_ref = FreqVsRefBiasDetector()" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "bc060445", + "metadata": {}, + "outputs": [], + "source": [ + "male_0_ref = 55/100\n", + "male_1_ref = 45/100\n", + "\n", + "female_0_ref = 50/100\n", + "female_1_ref = 50/100\n", + "\n", + "ref_distribution = [np.array([female_0_ref, female_1_ref]), np.array([male_0_ref, male_1_ref])]" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "4d38d0d6", + "metadata": {}, + "outputs": [], + "source": [ + "overall_ref = bd_ref.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " #threshold=0.1,\n", + " reference_distribution=ref_distribution\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "eb083e91", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "([0.3708341585642676, 0.3668290639264449],\n", + " [False, False],\n", + " 0.016368585412256314)" + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "overall_ref" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "7f8a877e", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_ref = bd_ref.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables,\n", + " #threshold=0.1,\n", + " min_obs_per_group=30,\n", + " reference_distribution=ref_distribution)" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "ca87efbd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'x3_education==1': (3119,\n", + " [0.4620223006815293, 0.456287468022177],\n", + " [False, False],\n", + " 0.016451439592896744),\n", + " 'x3_education==3': (1499,\n", + " [0.30004054728107643, 0.301920000109016],\n", + " [False, False],\n", + " 0.016540570623988414),\n", + " 'x3_education==2': (4250,\n", + " [0.3297513070249223, 0.32991040581610154],\n", + " [False, False],\n", + " 0.016422567122490656),\n", + " 'x3_education==4': (40, [1.0, 1.0], [False, False], 0.01802878118384471),\n", + " 'x3_education==5': (75,\n", + " [0.45277540525442184, 0.6135760511412283],\n", + " [False, False],\n", + " 0.017549038105676658),\n", + " 'x3_education==6': (14, None, 'Not enough observations'),\n", + " 'x3_education==0': (3, None, 'Not enough observations'),\n", + " 'x4_marriage==1': (4065,\n", + " [0.376452060901446, 0.35992113661821357],\n", + " [False, False],\n", + " 0.016426450237593673),\n", + " 'x4_marriage==2': (4822,\n", + " [0.36513728387900557, 0.3741329246698629],\n", + " [False, False],\n", + " 0.01641200891721621),\n", + " 'x4_marriage==3': (95,\n", + " [0.44397106958324817, 0.2777694169405729],\n", + " [False, False],\n", + " 0.017404225646095797),\n", + " 'x4_marriage==0': (18, None, 'Not enough observations'),\n", + " 'age_buckets==3': (2727,\n", + " [0.36859563815725926, 0.3482206719343247],\n", + " [False, False],\n", + " 0.016465431871108036),\n", + " 'age_buckets==1': (2895,\n", + " [0.3630201449190119, 0.3242010905897603],\n", + " [False, False],\n", + " 0.016459087581124063),\n", + " 'age_buckets==2': (3378,\n", + " [0.3782484161589076, 0.42896787633099487],\n", + " [False, False],\n", + " 0.01644356315834885),\n", + " 'x3_education==1 & x4_marriage==1': (1106,\n", + " [0.48192521938779376, 0.4889748520001793],\n", + " [False, False],\n", + " 0.0165882789383699),\n", + " 'x3_education==1 & x4_marriage==2': (2002,\n", + " [0.4492546144758617, 0.4395444808863672],\n", + " [False, False],\n", + " 0.016501431962900565),\n", + " 'x3_education==1 & x4_marriage==3': (10, None, 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==0': (1, None, 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==1': (842,\n", + " [0.2850405151436606, 0.28204816346821415],\n", + " [False, False],\n", + " 0.016637700603197515),\n", + " 'x3_education==3 & x4_marriage==2': (616,\n", + " [0.31017434029145563, 0.3318910910270282],\n", + " [False, False],\n", + " 0.016703275417264275),\n", + " 'x3_education==3 & x4_marriage==3': (26, None, 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==0': (15, None, 'Not enough observations'),\n", + " 'x3_education==2 & x4_marriage==1': (2047,\n", + " [0.3470522934317195, 0.33566342753392664],\n", + " [False, False],\n", + " 0.016498652941457678),\n", + " 'x3_education==2 & x4_marriage==2': (2145,\n", + " [0.3149338370490783, 0.32590111074043315],\n", + " [False, False],\n", + " 0.016492906353361734),\n", + " 'x3_education==2 & x4_marriage==3': (56,\n", + " [0.40117071177669594, 0.2547990572571768],\n", + " [False, False],\n", + " 0.017753344485757386),\n", + " 'x3_education==2 & x4_marriage==0': (2, None, 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==1': (17, None, 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==2': (21, None, 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==3': (2, None, 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==0': (0, None, 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==1': (45,\n", + " [1.0, 0.5580368406063803],\n", + " [False, False],\n", + " 0.017927050983124842),\n", + " 'x3_education==5 & x4_marriage==2': (29, None, 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==3': (1, None, 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==0': (0, None, 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==1': (7, None, 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==2': (7, None, 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==3': (0, None, 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==0': (0, None, 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==1': (1, None, 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==2': (2, None, 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==3': (0, None, 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==0': (0, None, 'Not enough observations'),\n", + " 'x3_education==1 & age_buckets==3': (710,\n", + " [0.44173964106929964, 0.4029550549844849],\n", + " [False, False],\n", + " 0.016672204976585454),\n", + " 'x3_education==1 & age_buckets==1': (1070,\n", + " [0.469201641275132, 0.4320928423736369],\n", + " [False, False],\n", + " 0.016593922535290104),\n", + " 'x3_education==1 & age_buckets==2': (1339,\n", + " [0.47059578748144526, 0.5101121945730993],\n", + " [False, False],\n", + " 0.01655744131846861),\n", + " 'x3_education==3 & age_buckets==3': (783,\n", + " [0.2861974650786553, 0.30070274118258955],\n", + " [False, False],\n", + " 0.016652042200564175),\n", + " 'x3_education==3 & age_buckets==1': (281,\n", + " [0.3694620990998062, 0.2310031282303594],\n", + " [False, False],\n", + " 0.01692111873455588),\n", + " 'x3_education==3 & age_buckets==2': (435,\n", + " [0.2828094536399566, 0.35775924637179646],\n", + " [False, False],\n", + " 0.016789396214171054),\n", + " 'x3_education==2 & age_buckets==3': (1180,\n", + " [0.3694620990998062, 0.3471884692568875],\n", + " [False, False],\n", + " 0.016577500161728514),\n", + " 'x3_education==2 & age_buckets==1': (1502,\n", + " [0.29317998898179864, 0.2687271665830179],\n", + " [False, False],\n", + " 0.0165402802952325),\n", + " 'x3_education==2 & age_buckets==2': (1568,\n", + " [0.33068530906480187, 0.39009392224338335],\n", + " [False, False],\n", + " 0.01653410540315531),\n", + " 'x3_education==4 & age_buckets==3': (13, None, 'Not enough observations'),\n", + " 'x3_education==4 & age_buckets==1': (15, None, 'Not enough observations'),\n", + " 'x3_education==4 & age_buckets==2': (12, None, 'Not enough observations'),\n", + " 'x3_education==5 & age_buckets==3': (28, None, 'Not enough observations'),\n", + " 'x3_education==5 & age_buckets==1': (26, None, 'Not enough observations'),\n", + " 'x3_education==5 & age_buckets==2': (21, None, 'Not enough observations'),\n", + " 'x3_education==6 & age_buckets==3': (12, None, 'Not enough observations'),\n", + " 'x3_education==6 & age_buckets==1': (1, None, 'Not enough observations'),\n", + " 'x3_education==6 & age_buckets==2': (1, None, 'Not enough observations'),\n", + " 'x3_education==0 & age_buckets==3': (1, None, 'Not enough observations'),\n", + " 'x3_education==0 & age_buckets==1': (0, None, 'Not enough observations'),\n", + " 'x3_education==0 & age_buckets==2': (2, None, 'Not enough observations'),\n", + " 'x4_marriage==1 & age_buckets==3': (1973,\n", + " [0.379621655532961, 0.36112473512065624],\n", + " [False, False],\n", + " 0.016503273049709347),\n", + " 'x4_marriage==1 & age_buckets==1': (433,\n", + " [0.3529571445758697, 0.25770306238935237],\n", + " [False, False],\n", + " 0.016790640497748737),\n", + " 'x4_marriage==1 & age_buckets==2': (1659,\n", + " [0.37521311260533263, 0.39747610473967265],\n", + " [False, False],\n", + " 0.016526203596578883),\n", + " 'x4_marriage==2 & age_buckets==3': (682,\n", + " [0.33367457657786503, 0.3243599524588463],\n", + " [False, False],\n", + " 0.016680784764350462),\n", + " 'x4_marriage==2 & age_buckets==1': (2450,\n", + " [0.3628271322361155, 0.3393024156176122],\n", + " [False, False],\n", + " 0.01647728432252425),\n", + " 'x4_marriage==2 & age_buckets==2': (1690,\n", + " [0.3795673436649285, 0.47106904171590147],\n", + " [False, False],\n", + " 0.016523658643668417),\n", + " 'x4_marriage==3 & age_buckets==3': (67,\n", + " [0.40117071177669594, 0.22566287072110824],\n", + " [False, False],\n", + " 0.017624406249008434),\n", + " 'x4_marriage==3 & age_buckets==1': (9, None, 'Not enough observations'),\n", + " 'x4_marriage==3 & age_buckets==2': (19, None, 'Not enough observations'),\n", + " 'x4_marriage==0 & age_buckets==3': (5, None, 'Not enough observations'),\n", + " 'x4_marriage==0 & age_buckets==1': (3, None, 'Not enough observations'),\n", + " 'x4_marriage==0 & age_buckets==2': (10, None, 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==1 & age_buckets==3': (530,\n", + " [0.4425027716770654, 0.4519653039256851],\n", + " [False, False],\n", + " 0.01673866877310845),\n", + " 'x3_education==1 & x4_marriage==1 & age_buckets==1': (57,\n", + " [0.5113739208010888, 0.5019439948311757],\n", + " [False, False],\n", + " 0.017740098901698177),\n", + " 'x3_education==1 & x4_marriage==1 & age_buckets==2': (519,\n", + " [0.5414265059292653, 0.5196689353266379],\n", + " [False, False],\n", + " 0.016743820191469413),\n", + " 'x3_education==1 & x4_marriage==2 & age_buckets==3': (174,\n", + " [0.42949249559503866, 0.2849533828553775],\n", + " [False, False],\n", + " 0.017102860299026267),\n", + " 'x3_education==1 & x4_marriage==2 & age_buckets==1': (1013,\n", + " [0.46728611033129075, 0.42824428864825015],\n", + " [False, False],\n", + " 0.016603466125778767),\n", + " 'x3_education==1 & x4_marriage==2 & age_buckets==2': (815,\n", + " [0.43826868351871007, 0.5017685192835523],\n", + " [False, False],\n", + " 0.016644070312308534),\n", + " 'x3_education==1 & x4_marriage==3 & age_buckets==3': (6,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==3 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==3 & age_buckets==2': (4,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==0 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==0 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==1 & x4_marriage==0 & age_buckets==2': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==1 & age_buckets==3': (540,\n", + " [0.29375755204621223, 0.2977854094815917],\n", + " [False, False],\n", + " 0.016734122918275925),\n", + " 'x3_education==3 & x4_marriage==1 & age_buckets==1': (66,\n", + " [0.2977520462199942, 0.18094766636572723],\n", + " [False, False],\n", + " 0.017634779273517497),\n", + " 'x3_education==3 & x4_marriage==1 & age_buckets==2': (236,\n", + " [0.2620627145731571, 0.2891593990185989],\n", + " [False, False],\n", + " 0.016982312624267134),\n", + " 'x3_education==3 & x4_marriage==2 & age_buckets==3': (215,\n", + " [0.2568716673225767, 0.31863017435611196],\n", + " [False, False],\n", + " 0.017017243631904284),\n", + " 'x3_education==3 & x4_marriage==2 & age_buckets==1': (212,\n", + " [0.3758755999451484, 0.25307084100179045],\n", + " [False, False],\n", + " 0.017022653172211376),\n", + " 'x3_education==3 & x4_marriage==2 & age_buckets==2': (189,\n", + " [0.2977520462199942, 0.4760688683527591],\n", + " [False, False],\n", + " 0.017068317088384972),\n", + " 'x3_education==3 & x4_marriage==3 & age_buckets==3': (23,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==3 & age_buckets==1': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==3 & age_buckets==2': (2,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==0 & age_buckets==3': (5,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==0 & age_buckets==1': (2,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==3 & x4_marriage==0 & age_buckets==2': (8,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==2 & x4_marriage==1 & age_buckets==3': (865,\n", + " [0.37992450338664374, 0.3524968775291666],\n", + " [False, False],\n", + " 0.0166325114755164),\n", + " 'x3_education==2 & x4_marriage==1 & age_buckets==1': (298,\n", + " [0.31473664010975755, 0.23391365140897302],\n", + " [False, False],\n", + " 0.016901695002158927),\n", + " 'x3_education==2 & x4_marriage==1 & age_buckets==2': (884,\n", + " [0.31690890667675464, 0.3701290466183629],\n", + " [False, False],\n", + " 0.016628378446622925),\n", + " 'x3_education==2 & x4_marriage==2 & age_buckets==3': (278,\n", + " [0.3398789491933295, 0.35090198280694873],\n", + " [False, False],\n", + " 0.016924730161892075),\n", + " 'x3_education==2 & x4_marriage==2 & age_buckets==1': (1196,\n", + " [0.2894603549750707, 0.27852237597110696],\n", + " [False, False],\n", + " 0.01657530214923101),\n", + " 'x3_education==2 & x4_marriage==2 & age_buckets==2': (671,\n", + " [0.34317261807623434, 0.4317080128171452],\n", + " [False, False],\n", + " 0.01668430143302123),\n", + " 'x3_education==2 & x4_marriage==3 & age_buckets==3': (37,\n", + " [0.35760339259412377, 0.21457646418892706],\n", + " [False, False],\n", + " 0.018099488607185268),\n", + " 'x3_education==2 & x4_marriage==3 & age_buckets==1': (7,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==2 & x4_marriage==3 & age_buckets==2': (12,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==2 & x4_marriage==0 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==2 & x4_marriage==0 & age_buckets==1': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==2 & x4_marriage==0 & age_buckets==2': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==1 & age_buckets==3': (9,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==1 & age_buckets==1': (2,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==1 & age_buckets==2': (6,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==2 & age_buckets==3': (3,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==2 & age_buckets==1': (12,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==2 & age_buckets==2': (6,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==3 & age_buckets==3': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==3 & age_buckets==1': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==3 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==0 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==0 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==4 & x4_marriage==0 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==1 & age_buckets==3': (22,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==1 & age_buckets==1': (10,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==1 & age_buckets==2': (13,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==2 & age_buckets==3': (6,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==2 & age_buckets==1': (16,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==2 & age_buckets==2': (7,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==3 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==3 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==3 & age_buckets==2': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==0 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==0 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==5 & x4_marriage==0 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==1 & age_buckets==3': (6,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==1 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==1 & age_buckets==2': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==2 & age_buckets==3': (6,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==2 & age_buckets==1': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==2 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==3 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==3 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==3 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==0 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==0 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==6 & x4_marriage==0 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==1 & age_buckets==3': (1,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==1 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==1 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==2 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==2 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==2 & age_buckets==2': (2,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==3 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==3 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==3 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==0 & age_buckets==3': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==0 & age_buckets==1': (0,\n", + " None,\n", + " 'Not enough observations'),\n", + " 'x3_education==0 & x4_marriage==0 & age_buckets==2': (0,\n", + " None,\n", + " 'Not enough observations')}" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conditioned_ref" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31101641", + "metadata": {}, + "outputs": [], + "source": [ + "# TODO considerare i risultati nei sottogruppi come test indipendenti (fare ciclo for)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/RiskMeasure_experiments_3.ipynb b/notebooks/RiskMeasure_experiments_3.ipynb new file mode 100644 index 0000000..5f4447b --- /dev/null +++ b/notebooks/RiskMeasure_experiments_3.ipynb @@ -0,0 +1,906 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "0b134d6e", + "metadata": {}, + "outputs": [], + "source": [ + "import os, sys\n", + "dir2 = os.path.abspath('')\n", + "dir1 = os.path.dirname(dir2)\n", + "if not dir1 in sys.path: sys.path.append(dir1)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "77c1e269", + "metadata": {}, + "outputs": [], + "source": [ + "from brio.utils.Preprocessing import Preprocessing\n", + "from sklearn.model_selection import train_test_split\n", + "from pickle import dump, load\n", + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "from brio.bias.FreqVsFreqBiasDetector import FreqVsFreqBiasDetector\n", + "from brio.bias.FreqVsRefBiasDetector import FreqVsRefBiasDetector" + ] + }, + { + "cell_type": "markdown", + "id": "68af6499", + "metadata": {}, + "source": [ + "## Importing Data and Trained Classifier" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "66127e6c", + "metadata": {}, + "outputs": [], + "source": [ + "input_data_path = \"../data/raw_data/uci-default-of-credit-card/data/data.csv\"\n", + "local_path_save = '../data/mlflow_artifacts/'" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "bf0e3b01", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/davideposillipo/.pyenv/versions/3.10.9/envs/prova/lib/python3.10/site-packages/sklearn/base.py:329: UserWarning: Trying to unpickle estimator OneHotEncoder from version 1.2.1 when using version 1.0.2. This might lead to breaking code or invalid results. Use at your own risk. For more info please refer to:\n", + "https://scikit-learn.org/stable/modules/model_persistence.html#security-maintainability-limitations\n", + " warnings.warn(\n", + "/Users/davideposillipo/.pyenv/versions/3.10.9/envs/prova/lib/python3.10/site-packages/sklearn/base.py:329: UserWarning: Trying to unpickle estimator StandardScaler from version 1.2.1 when using version 1.0.2. This might lead to breaking code or invalid results. Use at your own risk. For more info please refer to:\n", + "https://scikit-learn.org/stable/modules/model_persistence.html#security-maintainability-limitations\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "fitted_ohe = load(open(local_path_save + '_ohe.pkl', 'rb')) \n", + "fitted_scaler = load(open(local_path_save + '_scaler.pkl', 'rb'))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6646c312", + "metadata": {}, + "outputs": [], + "source": [ + "pp = Preprocessing(input_data_path, \"default\")\n", + "X, Y = pp.read_dataframe()\n", + "\n", + "X_train, X_test, Y_train, Y_test = train_test_split(X,Y, test_size=0.3, random_state=420)\n", + "\n", + "X_test_ohe, _, _ = pp.preprocess_for_classification(df=X_test, \n", + " fit_ohe=True, \n", + " fitted_ohe=fitted_ohe,\n", + " perform_scaling=True,\n", + " fitted_scaler=fitted_scaler)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "ba010d39", + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"./mlruns/1/1e4a0667c7a64cbe8c7b023410e5781c/artifacts/model/model.pkl\", \"rb\") as file:\n", + " classifier = load(file)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "04cacf92", + "metadata": {}, + "outputs": [], + "source": [ + "predicted_prob = classifier.predict_proba(X_test_ohe)\n", + "predicted_values = classifier.predict(X_test_ohe)" + ] + }, + { + "cell_type": "markdown", + "id": "01057c6d", + "metadata": {}, + "source": [ + "#### Definition of conditioning variables" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d7e96a84", + "metadata": {}, + "outputs": [], + "source": [ + "def age_buckets(x):\n", + " if x < 30:\n", + " return 1\n", + " elif x < 40:\n", + " return 2\n", + " else:\n", + " return 3\n", + "\n", + "X_test['age_buckets'] = X.x5_age.apply(age_buckets)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "c24a0c9c", + "metadata": {}, + "outputs": [], + "source": [ + "conditioning_variables = ['x3_education', 'x4_marriage', 'age_buckets']" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "7950602d", + "metadata": {}, + "outputs": [], + "source": [ + "df_with_predictions = pd.concat(\n", + " [X_test.reset_index(drop=True), pd.Series(predicted_values)], axis=1).rename(columns={0:\"predictions\"})" + ] + }, + { + "cell_type": "markdown", + "id": "d6f80bfb", + "metadata": {}, + "source": [ + "## Hazard and risk functions" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "e6a1b053", + "metadata": {}, + "outputs": [], + "source": [ + "def as_list(x):\n", + " if type(x) is list:\n", + " return x\n", + " else:\n", + " return [x]" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "cf4062af", + "metadata": {}, + "outputs": [], + "source": [ + "def hazard_function(\n", + " overall_result, \n", + " conditioned_results, \n", + " tot_observations,\n", + " conditioning_variables,\n", + " weight_logic=\"group\"):\n", + " \n", + " #tot number features=conditioning + root (+1)\n", + " n_features_total = len(conditioning_variables) + 1\n", + " \n", + " hazard_overall = 0\n", + " # Iterating over each reference distribution, if available (FreqVsRef)\n", + " # In case of FreqVsFreq, there will be a single iteration\n", + " num_iterations = len(as_list(overall_result[0]))\n", + " for k in np.arange(0, num_iterations):\n", + " \n", + " # test result, threshold, num_samples, boolean, num_used_features\n", + " test_results = []\n", + " test_results.append((\n", + " as_list(overall_result[0])[k], \n", + " overall_result[2], \n", + " tot_observations, \n", + " as_list(overall_result[1])[k],\n", + " 1 #for the overall test, only 1 feature used, the root variable\n", + " ))\n", + "\n", + " for group_name, group in conditioned_results.items():\n", + " if (group[1] is not None):\n", + " test_results.append(\n", + " (\n", + " as_list(group[1])[k], #test result\n", + " group[3], #threshold\n", + " group[0], #num_samples\n", + " as_list(group[2])[k], #boolean\n", + " len(group_name.split(\"&\"))+1 #num_used_features, cond.+root\n", + " )\n", + " ) \n", + "\n", + " if weight_logic==\"group\":\n", + " #T_i in Risk Function document\n", + " weight_denominator = 0 \n", + " for line in test_results:\n", + " weight_denominator += n_features_total - line[4] + 1\n", + " elif weight_logic==\"individual\":\n", + " #S_i in Risk Function document\n", + " weight_denominator = np.sum([x[4] for x in test_results]) \n", + " else:\n", + " raise Exception('Only \"group\" or \"individual\" are allowed for parameter weight_logic')\n", + "\n", + "\n", + " hazard = 0\n", + " for line in test_results:\n", + " if weight_logic==\"group\":\n", + " c_info = n_features_total - line[4] + 1\n", + " weight = c_info/weight_denominator\n", + " elif weight_logic==\"individual\":\n", + " weight = line[4]/weight_denominator\n", + " else:\n", + " raise Exception('Only \"group\" or \"individual\" are allowed for parameter weight_logic')\n", + "\n", + " delta = 1 if line[3]==False else 0\n", + " q = line[2]/tot_observations\n", + " e = line[0] - line[1]\n", + " hazard += delta * weight * q * e * line[1]\n", + " \n", + " hazard_overall+= hazard\n", + " \n", + " return hazard_overall" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "d6e084dc", + "metadata": {}, + "outputs": [], + "source": [ + "def risk_function(test_hazards):\n", + " # test_hazards = [list_of_hazards]\n", + " \n", + " risk = np.sum(test_hazards)/len(test_hazards)**2\n", + " \n", + " return risk" + ] + }, + { + "cell_type": "markdown", + "id": "0e6e5723", + "metadata": {}, + "source": [ + "### Test 1: TVD, A1=high" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "38346302", + "metadata": {}, + "outputs": [], + "source": [ + "bd_1 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"high\")" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "ebde5b3d", + "metadata": {}, + "outputs": [], + "source": [ + "overall_1 = bd_1.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "9dc1af6e", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_1 = bd_1.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "e4ad51ba", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_1 = hazard_function(\n", + " overall_1, \n", + " conditioned_1, \n", + " df_with_predictions.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "f24335e4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3.662715426591436e-05" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hazard_test_1" + ] + }, + { + "cell_type": "markdown", + "id": "e7914be4", + "metadata": {}, + "source": [ + "### Test 2 (TVD, low)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "e8377772", + "metadata": {}, + "outputs": [], + "source": [ + "bd_2 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"low\")" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "14e80b7e", + "metadata": {}, + "outputs": [], + "source": [ + "overall_2 = bd_2.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "468b603a", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_2 = bd_2.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "4016a74d", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_2 = hazard_function(\n", + " overall_2, \n", + " conditioned_2, \n", + " df_with_predictions.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")" + ] + }, + { + "cell_type": "markdown", + "id": "847b9871", + "metadata": {}, + "source": [ + "### Test 3 (JS, high)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "e8ce1a46", + "metadata": {}, + "outputs": [], + "source": [ + "bd_3 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"high\")" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "5817e2d8", + "metadata": {}, + "outputs": [], + "source": [ + "overall_3 = bd_3.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "ff84ad8a", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_3 = bd_3.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "1043e2b1", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_3 = hazard_function(\n", + " overall_3, \n", + " conditioned_3, \n", + " df_with_predictions.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")" + ] + }, + { + "cell_type": "markdown", + "id": "e65d63c0", + "metadata": {}, + "source": [ + "### Test 4 (JS, low)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "8bd6ad0f", + "metadata": {}, + "outputs": [], + "source": [ + "bd_4 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"low\")" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "f35b30be", + "metadata": {}, + "outputs": [], + "source": [ + "overall_4 = bd_4.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "3ba5c71c", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_4 = bd_4.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "b11aedbb", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_4 = hazard_function(\n", + " overall_4, \n", + " conditioned_4, \n", + " df_with_predictions.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")" + ] + }, + { + "cell_type": "markdown", + "id": "6b08c2f2", + "metadata": {}, + "source": [ + "## Risk results" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "0c8805e1", + "metadata": {}, + "outputs": [], + "source": [ + "hazards = [hazard_test_1, hazard_test_2, hazard_test_3, hazard_test_4]" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "df958149", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3.1655148018808247e-06" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "risk_function(hazards)" + ] + }, + { + "cell_type": "markdown", + "id": "811da932", + "metadata": {}, + "source": [ + "# Experiments with 3 models" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "3022aa0b", + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"./trained_model_for_testing/RF_12_200.pkl\", \"rb\") as file:\n", + " classifier_1 = load(file)\n", + " \n", + "with open(\"./trained_model_for_testing/RF_37_10.pkl\", \"rb\") as file:\n", + " classifier_2 = load(file)\n", + " \n", + "with open(\"./trained_model_for_testing/Tree_depth2.pkl\", \"rb\") as file:\n", + " classifier_3 = load(file)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "b985b114", + "metadata": {}, + "outputs": [], + "source": [ + "predicted_prob_1 = classifier_1.predict_proba(X_test_ohe)\n", + "predicted_values_1 = classifier_1.predict(X_test_ohe)\n", + "df_with_predictions_1 = pd.concat(\n", + " [X_test.reset_index(drop=True), \n", + " pd.Series(predicted_values_1)], axis=1).rename(columns={0:\"predictions\"})\n", + "\n", + "predicted_prob_2 = classifier_2.predict_proba(X_test_ohe)\n", + "predicted_values_2 = classifier_2.predict(X_test_ohe)\n", + "df_with_predictions_2 = pd.concat(\n", + " [X_test.reset_index(drop=True), \n", + " pd.Series(predicted_values_2)], axis=1).rename(columns={0:\"predictions\"})\n", + "\n", + "predicted_prob_3 = classifier_3.predict_proba(X_test_ohe)\n", + "predicted_values_3 = classifier_3.predict(X_test_ohe)\n", + "df_with_predictions_3 = pd.concat(\n", + " [X_test.reset_index(drop=True), \n", + " pd.Series(predicted_values_3)], axis=1).rename(columns={0:\"predictions\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "23ba3a67", + "metadata": {}, + "outputs": [], + "source": [ + "def test_model(data_frame):\n", + " ### Test 1: TVD, A1=high\n", + "\n", + " bd_1 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"high\")\n", + "\n", + " overall_1 = bd_1.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_1 = bd_1.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_1 = hazard_function(\n", + " overall_1, \n", + " conditioned_1, \n", + " data_frame.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")\n", + " \n", + " print(\"Test 1 (TVD, A1=high) hazard: \", hazard_test_1)\n", + "\n", + " ### Test 2 (TVD, low)\n", + "\n", + " bd_2 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"low\")\n", + "\n", + " overall_2 = bd_2.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_2 = bd_2.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_2 = hazard_function(\n", + " overall_2, \n", + " conditioned_2, \n", + " data_frame.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")\n", + " \n", + " print(\"Test 2 (TVD, A1=low) hazard: \", hazard_test_2)\n", + "\n", + " ### Test 3 (JS, high)\n", + "\n", + " bd_3 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"high\")\n", + "\n", + " overall_3 = bd_3.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_3 = bd_3.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_3 = hazard_function(\n", + " overall_3, \n", + " conditioned_3, \n", + " data_frame.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")\n", + " \n", + " print(\"Test 3 (JS, A1=high) hazard: \", hazard_test_3)\n", + "\n", + " ### Test 4 (JS, low)\n", + "\n", + " bd_4 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"low\")\n", + "\n", + " overall_4 = bd_4.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_4 = bd_4.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_4 = hazard_function(\n", + " overall_4, \n", + " conditioned_4, \n", + " data_frame.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")\n", + " \n", + " print(\"Test 4 (JS, A1=low) hazard: \", hazard_test_4)\n", + " \n", + " hazards = [hazard_test_1, hazard_test_2, hazard_test_3, hazard_test_4]\n", + " \n", + " return risk_function(hazards)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "7f9c5d36", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test 1 (TVD, A1=high) hazard: 3.662715426591436e-05\n", + "Test 2 (TVD, A1=low) hazard: 1.4001756250959011e-05\n", + "Test 3 (JS, A1=high) hazard: 1.932631321983019e-08\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model RF_12_200: 3.1655148018808247e-06\n", + "\n", + "\n", + "Test 1 (TVD, A1=high) hazard: 3.231114243613055e-05\n", + "Test 2 (TVD, A1=low) hazard: 8.844513845377398e-06\n", + "Test 3 (JS, A1=high) hazard: 7.713366782296505e-10\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model RF_37_10: 2.572276726136636e-06\n", + "\n", + "\n", + "Test 1 (TVD, A1=high) hazard: 1.0247396005717305e-05\n", + "Test 2 (TVD, A1=low) hazard: 3.7820077895012226e-06\n", + "Test 3 (JS, A1=high) hazard: 3.654431188743626e-08\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model Tree_depth2: 8.791217566941227e-07\n", + "\n", + "\n" + ] + } + ], + "source": [ + "for model, df in zip([\"RF_12_200\", \"RF_37_10\", \"Tree_depth2\"],\n", + " [df_with_predictions_1, df_with_predictions_2, df_with_predictions_3]):\n", + " print(f\"Overall risk measure for model {model}: \", test_model(df))\n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "6f0b3966", + "metadata": {}, + "source": [ + "## Freq Vs Ref" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "4b3771a0", + "metadata": {}, + "outputs": [], + "source": [ + "bd_ref = FreqVsRefBiasDetector()" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "24f7cf26", + "metadata": {}, + "outputs": [], + "source": [ + "male_0_ref = 55/100\n", + "male_1_ref = 45/100\n", + "\n", + "female_0_ref = 50/100\n", + "female_1_ref = 50/100\n", + "\n", + "ref_distribution = [np.array([female_0_ref, female_1_ref]), np.array([male_0_ref, male_1_ref])]" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "7dfb89a5", + "metadata": {}, + "outputs": [], + "source": [ + "overall_ref = bd_ref.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " #threshold=0.1,\n", + " reference_distribution=ref_distribution\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "a094a694", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_ref = bd_ref.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables,\n", + " #threshold=0.1,\n", + " min_obs_per_group=30,\n", + " reference_distribution=ref_distribution)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "b9aefa9b", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_ref = hazard_function(\n", + " overall_ref, \n", + " conditioned_ref, \n", + " df_with_predictions.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "4f4a0f26", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.0022374318004642693" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hazard_test_ref" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/RiskMeasure_experiments_4.ipynb b/notebooks/RiskMeasure_experiments_4.ipynb new file mode 100644 index 0000000..b27d7c1 --- /dev/null +++ b/notebooks/RiskMeasure_experiments_4.ipynb @@ -0,0 +1,821 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "aa617bce", + "metadata": {}, + "source": [ + "Replica of experiments_3, but using the RiskCalculator and HazardFromBiasDetectionCalculator classes" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "0b134d6e", + "metadata": {}, + "outputs": [], + "source": [ + "import os, sys\n", + "dir2 = os.path.abspath('')\n", + "dir1 = os.path.dirname(dir2)\n", + "if not dir1 in sys.path: sys.path.append(dir1)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "77c1e269", + "metadata": {}, + "outputs": [], + "source": [ + "from brio.utils.Preprocessing import Preprocessing\n", + "from sklearn.model_selection import train_test_split\n", + "from pickle import dump, load\n", + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "from brio.bias.FreqVsFreqBiasDetector import FreqVsFreqBiasDetector\n", + "from brio.bias.FreqVsRefBiasDetector import FreqVsRefBiasDetector\n", + "from brio.risk.HazardFromBiasDetectionCalculator import HazardFromBiasDetectionCalculator\n", + "from brio.risk.RiskCalculator import RiskCalculator" + ] + }, + { + "cell_type": "markdown", + "id": "68af6499", + "metadata": {}, + "source": [ + "## Importing Data and Trained Classifier" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "66127e6c", + "metadata": {}, + "outputs": [], + "source": [ + "input_data_path = \"../data/raw_data/uci-default-of-credit-card/data/data.csv\"\n", + "local_path_save = '../data/mlflow_artifacts/'" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "bf0e3b01", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/davideposillipo/.pyenv/versions/3.10.9/envs/prova/lib/python3.10/site-packages/sklearn/base.py:329: UserWarning: Trying to unpickle estimator OneHotEncoder from version 1.2.1 when using version 1.0.2. This might lead to breaking code or invalid results. Use at your own risk. For more info please refer to:\n", + "https://scikit-learn.org/stable/modules/model_persistence.html#security-maintainability-limitations\n", + " warnings.warn(\n", + "/Users/davideposillipo/.pyenv/versions/3.10.9/envs/prova/lib/python3.10/site-packages/sklearn/base.py:329: UserWarning: Trying to unpickle estimator StandardScaler from version 1.2.1 when using version 1.0.2. This might lead to breaking code or invalid results. Use at your own risk. For more info please refer to:\n", + "https://scikit-learn.org/stable/modules/model_persistence.html#security-maintainability-limitations\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "fitted_ohe = load(open(local_path_save + '_ohe.pkl', 'rb')) \n", + "fitted_scaler = load(open(local_path_save + '_scaler.pkl', 'rb'))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6646c312", + "metadata": {}, + "outputs": [], + "source": [ + "pp = Preprocessing(input_data_path, \"default\")\n", + "X, Y = pp.read_dataframe()\n", + "\n", + "X_train, X_test, Y_train, Y_test = train_test_split(X,Y, test_size=0.3, random_state=420)\n", + "\n", + "X_test_ohe, _, _ = pp.preprocess_for_classification(df=X_test, \n", + " fit_ohe=True, \n", + " fitted_ohe=fitted_ohe,\n", + " perform_scaling=True,\n", + " fitted_scaler=fitted_scaler)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "ba010d39", + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"./mlruns/1/1e4a0667c7a64cbe8c7b023410e5781c/artifacts/model/model.pkl\", \"rb\") as file:\n", + " classifier = load(file)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "04cacf92", + "metadata": {}, + "outputs": [], + "source": [ + "predicted_prob = classifier.predict_proba(X_test_ohe)\n", + "predicted_values = classifier.predict(X_test_ohe)" + ] + }, + { + "cell_type": "markdown", + "id": "01057c6d", + "metadata": {}, + "source": [ + "#### Definition of conditioning variables" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d7e96a84", + "metadata": {}, + "outputs": [], + "source": [ + "def age_buckets(x):\n", + " if x < 30:\n", + " return 1\n", + " elif x < 40:\n", + " return 2\n", + " else:\n", + " return 3\n", + "\n", + "X_test['age_buckets'] = X.x5_age.apply(age_buckets)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "c24a0c9c", + "metadata": {}, + "outputs": [], + "source": [ + "conditioning_variables = ['x3_education', 'x4_marriage', 'age_buckets']" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "7950602d", + "metadata": {}, + "outputs": [], + "source": [ + "df_with_predictions = pd.concat(\n", + " [X_test.reset_index(drop=True), pd.Series(predicted_values)], axis=1).rename(columns={0:\"predictions\"})" + ] + }, + { + "cell_type": "markdown", + "id": "f6f951a0", + "metadata": {}, + "source": [ + "## Testing Risk Calculator" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "0f3e064c", + "metadata": {}, + "outputs": [], + "source": [ + "rc = RiskCalculator()\n", + "hc = HazardFromBiasDetectionCalculator()" + ] + }, + { + "cell_type": "markdown", + "id": "0e6e5723", + "metadata": {}, + "source": [ + "### Test 1: TVD, A1=high" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "38346302", + "metadata": {}, + "outputs": [], + "source": [ + "bd_1 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"high\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "ebde5b3d", + "metadata": {}, + "outputs": [], + "source": [ + "overall_1 = bd_1.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "9dc1af6e", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_1 = bd_1.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "e4ad51ba", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_1 = hc.compute_hazard_from_freqvsfreq_or_freqvsref(\n", + " overall_1, \n", + " conditioned_1, \n", + " df_with_predictions.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "f24335e4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.009333101114095434" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hazard_test_1" + ] + }, + { + "cell_type": "markdown", + "id": "e7914be4", + "metadata": {}, + "source": [ + "### Test 2 (TVD, low)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "e8377772", + "metadata": {}, + "outputs": [], + "source": [ + "bd_2 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"low\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "14e80b7e", + "metadata": {}, + "outputs": [], + "source": [ + "overall_2 = bd_2.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "468b603a", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_2 = bd_2.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "4016a74d", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_2 = hc.compute_hazard_from_freqvsfreq_or_freqvsref(\n", + " overall_2, \n", + " conditioned_2, \n", + " df_with_predictions.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")" + ] + }, + { + "cell_type": "markdown", + "id": "847b9871", + "metadata": {}, + "source": [ + "### Test 3 (JS, high)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "e8ce1a46", + "metadata": {}, + "outputs": [], + "source": [ + "bd_3 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"high\")" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "5817e2d8", + "metadata": {}, + "outputs": [], + "source": [ + "overall_3 = bd_3.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "ff84ad8a", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_3 = bd_3.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "1043e2b1", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_3 = hc.compute_hazard_from_freqvsfreq_or_freqvsref(\n", + " overall_3, \n", + " conditioned_3, \n", + " df_with_predictions.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")" + ] + }, + { + "cell_type": "markdown", + "id": "e65d63c0", + "metadata": {}, + "source": [ + "### Test 4 (JS, low)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "8bd6ad0f", + "metadata": {}, + "outputs": [], + "source": [ + "bd_4 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"low\")" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "f35b30be", + "metadata": {}, + "outputs": [], + "source": [ + "overall_4 = bd_4.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "3ba5c71c", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_4 = bd_4.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "b11aedbb", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_4 = hc.compute_hazard_from_freqvsfreq_or_freqvsref(\n", + " overall_4, \n", + " conditioned_4, \n", + " df_with_predictions.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")" + ] + }, + { + "cell_type": "markdown", + "id": "6b08c2f2", + "metadata": {}, + "source": [ + "## Risk results" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "0c8805e1", + "metadata": {}, + "outputs": [], + "source": [ + "hazards = [hazard_test_1, hazard_test_2, hazard_test_3, hazard_test_4]" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "df958149", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.0028434304317325647" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rc.compute_risk(hazards)" + ] + }, + { + "cell_type": "markdown", + "id": "811da932", + "metadata": {}, + "source": [ + "# Experiments with 3 models" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "3022aa0b", + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"./trained_model_for_testing/RF_12_200.pkl\", \"rb\") as file:\n", + " classifier_1 = load(file)\n", + " \n", + "with open(\"./trained_model_for_testing/RF_37_10.pkl\", \"rb\") as file:\n", + " classifier_2 = load(file)\n", + " \n", + "with open(\"./trained_model_for_testing/Tree_depth2.pkl\", \"rb\") as file:\n", + " classifier_3 = load(file)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "b985b114", + "metadata": {}, + "outputs": [], + "source": [ + "predicted_prob_1 = classifier_1.predict_proba(X_test_ohe)\n", + "predicted_values_1 = classifier_1.predict(X_test_ohe)\n", + "df_with_predictions_1 = pd.concat(\n", + " [X_test.reset_index(drop=True), \n", + " pd.Series(predicted_values_1)], axis=1).rename(columns={0:\"predictions\"})\n", + "\n", + "predicted_prob_2 = classifier_2.predict_proba(X_test_ohe)\n", + "predicted_values_2 = classifier_2.predict(X_test_ohe)\n", + "df_with_predictions_2 = pd.concat(\n", + " [X_test.reset_index(drop=True), \n", + " pd.Series(predicted_values_2)], axis=1).rename(columns={0:\"predictions\"})\n", + "\n", + "predicted_prob_3 = classifier_3.predict_proba(X_test_ohe)\n", + "predicted_values_3 = classifier_3.predict(X_test_ohe)\n", + "df_with_predictions_3 = pd.concat(\n", + " [X_test.reset_index(drop=True), \n", + " pd.Series(predicted_values_3)], axis=1).rename(columns={0:\"predictions\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "23ba3a67", + "metadata": {}, + "outputs": [], + "source": [ + "def test_model(data_frame):\n", + " ### Test 1: TVD, A1=high\n", + "\n", + " bd_1 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"high\")\n", + "\n", + " overall_1 = bd_1.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_1 = bd_1.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_1 = hc.compute_hazard_from_freqvsfreq_or_freqvsref(\n", + " overall_1, \n", + " conditioned_1, \n", + " data_frame.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")\n", + " \n", + " print(\"Test 1 (TVD, A1=high) hazard: \", hazard_test_1)\n", + "\n", + " ### Test 2 (TVD, low)\n", + "\n", + " bd_2 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"low\")\n", + "\n", + " overall_2 = bd_2.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_2 = bd_2.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_2 = hc.compute_hazard_from_freqvsfreq_or_freqvsref(\n", + " overall_2, \n", + " conditioned_2, \n", + " data_frame.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")\n", + " \n", + " print(\"Test 2 (TVD, A1=low) hazard: \", hazard_test_2)\n", + "\n", + " ### Test 3 (JS, high)\n", + "\n", + " bd_3 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"high\")\n", + "\n", + " overall_3 = bd_3.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_3 = bd_3.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_3 = hc.compute_hazard_from_freqvsfreq_or_freqvsref(\n", + " overall_3, \n", + " conditioned_3, \n", + " data_frame.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")\n", + " \n", + " print(\"Test 3 (JS, A1=high) hazard: \", hazard_test_3)\n", + "\n", + " ### Test 4 (JS, low)\n", + "\n", + " bd_4 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"low\")\n", + "\n", + " overall_4 = bd_4.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_4 = bd_4.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_4 = hc.compute_hazard_from_freqvsfreq_or_freqvsref(\n", + " overall_4, \n", + " conditioned_4, \n", + " data_frame.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")\n", + " \n", + " print(\"Test 4 (JS, A1=low) hazard: \", hazard_test_4)\n", + " \n", + " hazards = [hazard_test_1, hazard_test_2, hazard_test_3, hazard_test_4]\n", + " \n", + " return rc.compute_risk(hazards)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "7f9c5d36", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test 1 (TVD, A1=high) hazard: 0.009333101114095434\n", + "Test 2 (TVD, A1=low) hazard: 0.0020279631068363525\n", + "Test 3 (JS, A1=high) hazard: 1.2657505998471251e-05\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model RF_12_200: 0.0028434304317325647\n", + "\n", + "\n", + "Test 1 (TVD, A1=high) hazard: 0.00873354115132899\n", + "Test 2 (TVD, A1=low) hazard: 0.0014683531134022521\n", + "Test 3 (JS, A1=high) hazard: 3.5455676319511333e-06\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model RF_37_10: 0.002551359958090798\n", + "\n", + "\n", + "Test 1 (TVD, A1=high) hazard: 0.0022889741320904415\n", + "Test 2 (TVD, A1=low) hazard: 0.0006153636933853124\n", + "Test 3 (JS, A1=high) hazard: 1.9261143460997856e-05\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model Tree_depth2: 0.000730899742234188\n", + "\n", + "\n" + ] + } + ], + "source": [ + "for model, df in zip([\"RF_12_200\", \"RF_37_10\", \"Tree_depth2\"],\n", + " [df_with_predictions_1, df_with_predictions_2, df_with_predictions_3]):\n", + " print(f\"Overall risk measure for model {model}: \", test_model(df))\n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "6f0b3966", + "metadata": {}, + "source": [ + "## Freq Vs Ref" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "4b3771a0", + "metadata": {}, + "outputs": [], + "source": [ + "bd_ref = FreqVsRefBiasDetector()" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "24f7cf26", + "metadata": {}, + "outputs": [], + "source": [ + "male_0_ref = 55/100\n", + "male_1_ref = 45/100\n", + "\n", + "female_0_ref = 50/100\n", + "female_1_ref = 50/100\n", + "\n", + "ref_distribution = [np.array([female_0_ref, female_1_ref]), np.array([male_0_ref, male_1_ref])]" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "7dfb89a5", + "metadata": {}, + "outputs": [], + "source": [ + "overall_ref = bd_ref.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " #threshold=0.1,\n", + " reference_distribution=ref_distribution\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "a094a694", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_ref = bd_ref.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables,\n", + " #threshold=0.1,\n", + " min_obs_per_group=30,\n", + " reference_distribution=ref_distribution)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "b9aefa9b", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_ref = hc.compute_hazard_from_freqvsfreq_or_freqvsref(\n", + " overall_ref, \n", + " conditioned_ref, \n", + " df_with_predictions.shape[0],\n", + " conditioning_variables,\n", + " weight_logic=\"group\")" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "4f4a0f26", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.0687693765858981" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hazard_test_ref" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/RiskMeasure_implementation_and_experiments.ipynb b/notebooks/RiskMeasure_implementation_and_experiments.ipynb new file mode 100644 index 0000000..019e3ed --- /dev/null +++ b/notebooks/RiskMeasure_implementation_and_experiments.ipynb @@ -0,0 +1,721 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "0b134d6e", + "metadata": {}, + "outputs": [], + "source": [ + "import os, sys\n", + "dir2 = os.path.abspath('')\n", + "dir1 = os.path.dirname(dir2)\n", + "if not dir1 in sys.path: sys.path.append(dir1)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "77c1e269", + "metadata": {}, + "outputs": [], + "source": [ + "from brio.utils.Preprocessing import Preprocessing\n", + "from sklearn.model_selection import train_test_split\n", + "from pickle import dump, load\n", + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "from brio.bias.FreqVsFreqBiasDetector import FreqVsFreqBiasDetector" + ] + }, + { + "cell_type": "markdown", + "id": "68af6499", + "metadata": {}, + "source": [ + "## Importing Data and Trained Classifier" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "66127e6c", + "metadata": {}, + "outputs": [], + "source": [ + "input_data_path = \"../data/raw_data/uci-default-of-credit-card/data/data.csv\"\n", + "local_path_save = '../data/mlflow_artifacts/'" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "bf0e3b01", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/davideposillipo/.pyenv/versions/3.10.9/envs/prova/lib/python3.10/site-packages/sklearn/base.py:329: UserWarning: Trying to unpickle estimator OneHotEncoder from version 1.2.1 when using version 1.0.2. This might lead to breaking code or invalid results. Use at your own risk. For more info please refer to:\n", + "https://scikit-learn.org/stable/modules/model_persistence.html#security-maintainability-limitations\n", + " warnings.warn(\n", + "/Users/davideposillipo/.pyenv/versions/3.10.9/envs/prova/lib/python3.10/site-packages/sklearn/base.py:329: UserWarning: Trying to unpickle estimator StandardScaler from version 1.2.1 when using version 1.0.2. This might lead to breaking code or invalid results. Use at your own risk. For more info please refer to:\n", + "https://scikit-learn.org/stable/modules/model_persistence.html#security-maintainability-limitations\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "fitted_ohe = load(open(local_path_save + '_ohe.pkl', 'rb')) \n", + "fitted_scaler = load(open(local_path_save + '_scaler.pkl', 'rb'))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6646c312", + "metadata": {}, + "outputs": [], + "source": [ + "pp = Preprocessing(input_data_path, \"default\")\n", + "X, Y = pp.read_dataframe()\n", + "\n", + "X_train, X_test, Y_train, Y_test = train_test_split(X,Y, test_size=0.3, random_state=420)\n", + "\n", + "X_test_ohe, _, _ = pp.preprocess_for_classification(df=X_test, \n", + " fit_ohe=True, \n", + " fitted_ohe=fitted_ohe,\n", + " perform_scaling=True,\n", + " fitted_scaler=fitted_scaler)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "ba010d39", + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"./mlruns/1/1e4a0667c7a64cbe8c7b023410e5781c/artifacts/model/model.pkl\", \"rb\") as file:\n", + " classifier = load(file)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "04cacf92", + "metadata": {}, + "outputs": [], + "source": [ + "predicted_prob = classifier.predict_proba(X_test_ohe)\n", + "predicted_values = classifier.predict(X_test_ohe)" + ] + }, + { + "cell_type": "markdown", + "id": "01057c6d", + "metadata": {}, + "source": [ + "#### Definition of conditioning variables" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d7e96a84", + "metadata": {}, + "outputs": [], + "source": [ + "def age_buckets(x):\n", + " if x < 30:\n", + " return 1\n", + " elif x < 40:\n", + " return 2\n", + " else:\n", + " return 3\n", + "\n", + "X_test['age_buckets'] = X.x5_age.apply(age_buckets)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "c24a0c9c", + "metadata": {}, + "outputs": [], + "source": [ + "conditioning_variables = ['x3_education', 'x4_marriage', 'age_buckets']" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "7950602d", + "metadata": {}, + "outputs": [], + "source": [ + "df_with_predictions = pd.concat(\n", + " [X_test.reset_index(drop=True), pd.Series(predicted_values)], axis=1).rename(columns={0:\"predictions\"})" + ] + }, + { + "cell_type": "markdown", + "id": "d6f80bfb", + "metadata": {}, + "source": [ + "## Hazard and risk functions" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "7e6183a2", + "metadata": {}, + "outputs": [], + "source": [ + "def hazard_function(overall_result, conditioned_results, tot_observations):\n", + " \n", + " # test result, threshold, num_samples, boolean\n", + " test_results = []\n", + " test_results.append((overall_result[0], \n", + " overall_result[2], \n", + " tot_observations, \n", + " overall_result[1]))\n", + " \n", + " for group in conditioned_results.values():\n", + " if (group[1] is not None):\n", + " test_results.append((group[1], group[3], group[0], group[2]))\n", + " \n", + " hazard = 0\n", + " for line in test_results:\n", + " weight = 1 #to be implemented\n", + " delta = 1 if line[3]==False else 0\n", + " q = line[2]/tot_observations\n", + " e = line[0] - line[1]\n", + " hazard += delta * weight * q * e\n", + " \n", + " average_threshold = np.mean([x[1] for x in test_results])\n", + " \n", + " return hazard, average_threshold" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "9dec052f", + "metadata": {}, + "outputs": [], + "source": [ + "def risk_function(test_hazards, average_thresholds):\n", + " # test_hazards = [list_of_hazards]\n", + " # average_thresholds = [mean(thresholds_of_test1), mean(thresholds_of_a_test2), ...], \n", + " # needed if automatic threshold is used\n", + " risk = 0\n", + " for hazard, threshold in zip(test_hazards, average_thresholds):\n", + " risk += hazard * threshold\n", + " \n", + " risk = risk/len(test_hazards)**2\n", + " \n", + " return risk" + ] + }, + { + "cell_type": "markdown", + "id": "0e6e5723", + "metadata": {}, + "source": [ + "### Test 1: TVD, A1=high" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "38346302", + "metadata": {}, + "outputs": [], + "source": [ + "bd_1 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"high\")" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "ebde5b3d", + "metadata": {}, + "outputs": [], + "source": [ + "overall_1 = bd_1.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "9dc1af6e", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_1 = bd_1.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "e4ad51ba", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_1, average_threshold_1 = hazard_function(\n", + " overall_1, \n", + " conditioned_1, \n", + " df_with_predictions.shape[0])" + ] + }, + { + "cell_type": "markdown", + "id": "e7914be4", + "metadata": {}, + "source": [ + "### Test 2 (TVD, low)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "e8377772", + "metadata": {}, + "outputs": [], + "source": [ + "bd_2 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"low\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "14e80b7e", + "metadata": {}, + "outputs": [], + "source": [ + "overall_2 = bd_2.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "468b603a", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_2 = bd_2.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "4016a74d", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_2, average_threshold_2 = hazard_function(\n", + " overall_2, \n", + " conditioned_2, \n", + " df_with_predictions.shape[0])" + ] + }, + { + "cell_type": "markdown", + "id": "847b9871", + "metadata": {}, + "source": [ + "### Test 3 (JS, high)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "e8ce1a46", + "metadata": {}, + "outputs": [], + "source": [ + "bd_3 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"high\")" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "5817e2d8", + "metadata": {}, + "outputs": [], + "source": [ + "overall_3 = bd_3.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "ff84ad8a", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_3 = bd_3.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "1043e2b1", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_3, average_threshold_3 = hazard_function(\n", + " overall_3, \n", + " conditioned_3, \n", + " df_with_predictions.shape[0])" + ] + }, + { + "cell_type": "markdown", + "id": "e65d63c0", + "metadata": {}, + "source": [ + "### Test 4 (JS, low)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "8bd6ad0f", + "metadata": {}, + "outputs": [], + "source": [ + "bd_4 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"low\")" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "f35b30be", + "metadata": {}, + "outputs": [], + "source": [ + "overall_4 = bd_4.compare_root_variable_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "3ba5c71c", + "metadata": {}, + "outputs": [], + "source": [ + "conditioned_4 = bd_4.compare_root_variable_conditioned_groups(\n", + " dataframe=df_with_predictions,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "b11aedbb", + "metadata": {}, + "outputs": [], + "source": [ + "hazard_test_4, average_threshold_4 = hazard_function(\n", + " overall_4, \n", + " conditioned_4, \n", + " df_with_predictions.shape[0])" + ] + }, + { + "cell_type": "markdown", + "id": "6b08c2f2", + "metadata": {}, + "source": [ + "## Risk results" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "0c8805e1", + "metadata": {}, + "outputs": [], + "source": [ + "hazards = [hazard_test_1, hazard_test_2, hazard_test_3, hazard_test_4]\n", + "average_thresholds = [average_threshold_1, average_threshold_2, average_threshold_3, average_threshold_4]" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "df958149", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.00015458111237839916" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "risk_function(hazards, average_thresholds)" + ] + }, + { + "cell_type": "markdown", + "id": "811da932", + "metadata": {}, + "source": [ + "# Experiments with 3 models" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "3022aa0b", + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"./trained_model_for_testing/RF_12_200.pkl\", \"rb\") as file:\n", + " classifier_1 = load(file)\n", + " \n", + "with open(\"./trained_model_for_testing/RF_37_10.pkl\", \"rb\") as file:\n", + " classifier_2 = load(file)\n", + " \n", + "with open(\"./trained_model_for_testing/Tree_depth2.pkl\", \"rb\") as file:\n", + " classifier_3 = load(file)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "b985b114", + "metadata": {}, + "outputs": [], + "source": [ + "predicted_prob_1 = classifier_1.predict_proba(X_test_ohe)\n", + "predicted_values_1 = classifier_1.predict(X_test_ohe)\n", + "df_with_predictions_1 = pd.concat(\n", + " [X_test.reset_index(drop=True), \n", + " pd.Series(predicted_values_1)], axis=1).rename(columns={0:\"predictions\"})\n", + "\n", + "predicted_prob_2 = classifier_2.predict_proba(X_test_ohe)\n", + "predicted_values_2 = classifier_2.predict(X_test_ohe)\n", + "df_with_predictions_2 = pd.concat(\n", + " [X_test.reset_index(drop=True), \n", + " pd.Series(predicted_values_2)], axis=1).rename(columns={0:\"predictions\"})\n", + "\n", + "predicted_prob_3 = classifier_3.predict_proba(X_test_ohe)\n", + "predicted_values_3 = classifier_3.predict(X_test_ohe)\n", + "df_with_predictions_3 = pd.concat(\n", + " [X_test.reset_index(drop=True), \n", + " pd.Series(predicted_values_3)], axis=1).rename(columns={0:\"predictions\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "23ba3a67", + "metadata": {}, + "outputs": [], + "source": [ + "def test_model(data_frame):\n", + " ### Test 1: TVD, A1=high\n", + "\n", + " bd_1 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"high\")\n", + "\n", + " overall_1 = bd_1.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_1 = bd_1.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_1, average_threshold_1 = hazard_function(\n", + " overall_1, \n", + " conditioned_1, \n", + " data_frame.shape[0])\n", + " \n", + " print(\"Test 1 (TVD, A1=high) hazard: \", hazard_test_1)\n", + "\n", + " ### Test 2 (TVD, low)\n", + "\n", + " bd_2 = FreqVsFreqBiasDetector(distance=\"TVD\", A1=\"low\")\n", + "\n", + " overall_2 = bd_2.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_2 = bd_2.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_2, average_threshold_2 = hazard_function(\n", + " overall_2, \n", + " conditioned_2, \n", + " data_frame.shape[0])\n", + " \n", + " print(\"Test 2 (TVD, A1=low) hazard: \", hazard_test_2)\n", + "\n", + " ### Test 3 (JS, high)\n", + "\n", + " bd_3 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"high\")\n", + "\n", + " overall_3 = bd_3.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_3 = bd_3.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_3, average_threshold_3 = hazard_function(\n", + " overall_3, \n", + " conditioned_3, \n", + " data_frame.shape[0])\n", + " \n", + " print(\"Test 3 (JS, A1=high) hazard: \", hazard_test_3)\n", + "\n", + " ### Test 4 (JS, low)\n", + "\n", + " bd_4 = FreqVsFreqBiasDetector(distance=\"JS\", A1=\"low\")\n", + "\n", + " overall_4 = bd_4.compare_root_variable_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex')\n", + "\n", + " conditioned_4 = bd_4.compare_root_variable_conditioned_groups(\n", + " dataframe=data_frame,\n", + " target_variable='predictions',\n", + " root_variable='x2_sex',\n", + " conditioning_variables=conditioning_variables)\n", + "\n", + " hazard_test_4, average_threshold_4 = hazard_function(\n", + " overall_4, \n", + " conditioned_4, \n", + " data_frame.shape[0])\n", + " \n", + " print(\"Test 4 (JS, A1=low) hazard: \", hazard_test_4)\n", + " \n", + " hazards = [hazard_test_1, hazard_test_2, hazard_test_3, hazard_test_4]\n", + " average_thresholds = [average_threshold_1, \n", + " average_threshold_2, average_threshold_3, average_threshold_4]\n", + " \n", + " return risk_function(hazards, average_thresholds)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "7f9c5d36", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test 1 (TVD, A1=high) hazard: 0.09976465885178575\n", + "Test 2 (TVD, A1=low) hazard: 0.02015304845287825\n", + "Test 3 (JS, A1=high) hazard: 0.00011458216656976323\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model RF_12_200: 0.00015458111237839916\n", + "\n", + "\n", + "Test 1 (TVD, A1=high) hazard: 0.09085147869902101\n", + "Test 2 (TVD, A1=low) hazard: 0.014801760181546463\n", + "Test 3 (JS, A1=high) hazard: 1.52371151916934e-06\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model RF_37_10: 0.00013193466737245095\n", + "\n", + "\n", + "Test 1 (TVD, A1=high) hazard: 0.03355105791241006\n", + "Test 2 (TVD, A1=low) hazard: 0.006384298991373367\n", + "Test 3 (JS, A1=high) hazard: 0.00014383137973982362\n", + "Test 4 (JS, A1=low) hazard: 0.0\n", + "Overall risk measure for model Tree_depth2: 5.113018082906323e-05\n", + "\n", + "\n" + ] + } + ], + "source": [ + "for model, df in zip([\"RF_12_200\", \"RF_37_10\", \"Tree_depth2\"],\n", + " [df_with_predictions_1, df_with_predictions_2, df_with_predictions_3]):\n", + " print(f\"Overall risk measure for model {model}: \", test_model(df))\n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6f6f9ae", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notes on risk/main.aux b/notes on risk/main.aux new file mode 100644 index 0000000..78a600f --- /dev/null +++ b/notes on risk/main.aux @@ -0,0 +1,27 @@ +\relax +\@writefile{toc}{\contentsline {section}{\numberline {1}Overview}{1}{}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {1.1}Risk associated to a single test}{2}{}\protected@file@percent } +\newlabel{risk_single}{{1.1}{2}} +\newlabel{risk_single@cref}{{[subsection][1][1]1.1}{[1][2][]2}} +\@writefile{toc}{\contentsline {subsection}{\numberline {1.2}Risk associated to a battery of tests}{3}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {2}Execution of the module}{3}{}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Pipeline}{3}{}\protected@file@percent } +\bibdata{temp} +\bibcite{DBLP:conf/beware/CoragliaDGGPPQ23}{CDG{$^{+}$}23} +\newlabel{qui}{{2}{4}} +\newlabel{qui@cref}{{[enumi][2][]2}{[1][4][]4}} +\newlabel{qui2}{{3}{4}} +\newlabel{qui2@cref}{{[enumi][3][]3}{[1][4][]4}} +\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Strategy}{4}{}\protected@file@percent } +\newlabel{strategy}{{2.2}{4}} +\newlabel{strategy@cref}{{[subsection][2][2]2.2}{[1][4][]4}} +\newlabel{quy}{{1}{4}} +\newlabel{quy@cref}{{[enumi][1][]1}{[1][4][]4}} +\newlabel{bad_record}{{3}{4}} +\newlabel{bad_record@cref}{{[enumi][3][]3}{[1][4][]4}} +\newlabel{quy2}{{4}{4}} +\newlabel{quy2@cref}{{[enumi][4][]4}{[1][4][]4}} +\bibcite{dkl}{KL51} +\bibcite{lin_divergence}{Lin91} +\bibstyle{alpha} +\gdef \@abspage@last{5} diff --git a/notes on risk/main.bbl b/notes on risk/main.bbl new file mode 100644 index 0000000..1ba1ec8 --- /dev/null +++ b/notes on risk/main.bbl @@ -0,0 +1,26 @@ +\newcommand{\etalchar}[1]{$^{#1}$} +\begin{thebibliography}{CDG{\etalchar{+}}23} + +\bibitem[CDG{\etalchar{+}}23]{DBLP:conf/beware/CoragliaDGGPPQ23} +Greta Coraglia, Fabio~Aurelio D'Asaro, Francesco~Antonio Genco, Davide + Giannuzzi, Davide Posillipo, Giuseppe Primiero, and Christian Quaggio. +\newblock Brioxalkemy: a bias detecting tool. +\newblock In Guido Boella, Fabio~Aurelio D'Asaro, Abeer Dyoub, Laura Gorrieri, + Francesca~A. Lisi, Chiara Manganini, and Giuseppe Primiero, editors, {\em + Proceedings of the 2nd Workshop on Bias, Ethical AI, Explainability and the + role of Logic and Logic Programming co-located with the 22nd International + Conference of the Italian Association for Artificial Intelligence (AI*IA + 2023), Rome, Italy, November 6, 2023}, volume 3615 of {\em {CEUR} Workshop + Proceedings}, pages 44--60. CEUR-WS.org, 2023. + +\bibitem[KL51]{dkl} +S.~Kullback and R.~A. Leibler. +\newblock {On Information and Sufficiency}. +\newblock {\em The Annals of Mathematical Statistics}, 22(1):79 -- 86, 1951. + +\bibitem[Lin91]{lin_divergence} +J.~Lin. +\newblock Divergence measures based on the shannon entropy. +\newblock {\em IEEE Transactions on Information Theory}, 37(1):145--151, 1991. + +\end{thebibliography} diff --git a/notes on risk/main.blg b/notes on risk/main.blg new file mode 100644 index 0000000..3fe7aa3 --- /dev/null +++ b/notes on risk/main.blg @@ -0,0 +1,59 @@ +This is BibTeX, Version 0.99d +Capacity: max_strings=200000, hash_size=200000, hash_prime=170003 +The top-level auxiliary file: main.aux +Reallocating 'name_of_file' (item size: 1) to 5 items. +Reallocating 'name_of_file' (item size: 1) to 6 items. +The style file: alpha.bst +Database file #1: temp.bib +I was expecting a `,' or a `}'---line 2949 of file temp.bib + : + : @article{Castelnovo_2022, +(Error may have been on previous line) +I'm skipping whatever remains of this entry +I was expecting a `,' or a `}'---line 2973 of file temp.bib + : + : % incol due to presence of booktitle +(Error may have been on previous line) +I'm skipping whatever remains of this entry +You've used 3 entries, + 2543 wiz_defined-function locations, + 845 strings with 10756 characters, +and the built_in function-call counts, 1584 in all, are: += -- 147 +> -- 95 +< -- 3 ++ -- 32 +- -- 32 +* -- 137 +:= -- 270 +add.period$ -- 10 +call.type$ -- 3 +change.case$ -- 22 +chr.to.int$ -- 3 +cite$ -- 3 +duplicate$ -- 54 +empty$ -- 104 +format.name$ -- 35 +if$ -- 318 +int.to.chr$ -- 1 +int.to.str$ -- 0 +missing$ -- 3 +newline$ -- 19 +num.names$ -- 11 +pop$ -- 17 +preamble$ -- 1 +purify$ -- 25 +quote$ -- 0 +skip$ -- 43 +stack$ -- 0 +substring$ -- 91 +swap$ -- 13 +text.length$ -- 3 +text.prefix$ -- 1 +top$ -- 0 +type$ -- 24 +warning$ -- 0 +while$ -- 15 +width$ -- 5 +write$ -- 44 +(There were 2 error messages) diff --git a/notes on risk/main.pdf b/notes on risk/main.pdf new file mode 100644 index 0000000..b6c0714 Binary files /dev/null and b/notes on risk/main.pdf differ diff --git a/notes on risk/main.synctex.gz b/notes on risk/main.synctex.gz new file mode 100644 index 0000000..91d9ea0 Binary files /dev/null and b/notes on risk/main.synctex.gz differ diff --git a/notes on risk/main.tex b/notes on risk/main.tex new file mode 100644 index 0000000..ff5fa1a --- /dev/null +++ b/notes on risk/main.tex @@ -0,0 +1,109 @@ +\documentclass{article} +\usepackage{graphicx} % Required for inserting images +\usepackage{subcaption} +\usepackage{amsmath} +\usepackage{cleveref} +\usepackage{color} +\usepackage{url} + + + +\newcommand{\ehi}{\color{red}} +\newcommand{\brio}{BRIO} + +\title{Notes on risk} +\date{\today} + +\begin{document} + +\maketitle +\tableofcontents + +\section{Overview} +The \brio{} system features a module devoted to the measurement of the risk related to fairness violations by AI systems. The risk measure produced aggregates the results of all available relevant tests detecting fairness violations relative to an AI system. The risk module, therefore, takes in input a series of $n$ different test results, relative to possibly different sensitive features, and returns one value in the real unit interval $[0,1]$ which represents how high in the interval $[0,1]$ is the risk that the tested AI system behaves in an unfair manner. + +As the \brio{} bias detection module does not only compare the behaviour of the AI algorithm on the classes relative to the sensitive feature but can also execute similar checks on possibly several subclasses, in general the result of one fairness test will consist of $m$ lines. Each one of these lines will be relative to a subclass of the considered classes. Suppose, for example, that our sensitive feature is \texttt{gender}, the detection module of \brio{} will not only compare the behaviour of the AI algorithm on the classes obtained by selecting a particular value of \texttt{gender}, but will also compare the behaviour of the AI algorithm on the subclasses obtained by fixing the values of features different from \texttt{gender} and by varying the value of \texttt{gender}. For instance, one line of the output will be about the behaviour of the AI system on the class of male individuals as compared to its behaviour on the class of female individuals, another line will be about the behaviour of the AI system on the subclass of rich male individuals as compared to its behaviour on the class of rich female individuals, yet another line will be about the behaviour on the subclass of poor male individuals as compared to its behaviour on the class of poor female individuals, and so on. + +Therefore, each line of the output will provide the following information: + +\begin{itemize} +\item the set of non-sensitive feature values used to determine the considered subclasses, if any, + +\item the number of elements of the union of all considered (sub)-classes, + +\item the value of the divergence for the considered (sub)-classes, + +\item the threshold employed. +\end{itemize} + +This information will be used to compute the risk measure emerging from a series of tests. In computing this measure, it is also possible to choose whether to focus on group fairness or individual fairness. Intuitively, focusing on {\it group fairness} means deeming more serious a discrimination based on very little information. For instance, a choice made only on the basis of the value of the sensitive feature will be a group discrimination. Focusing on {\it individual fairness}, on the other hand, means deeming more serious a discrimination between two individuals which have many values in common but a different value relatively to the sensitive feature. + +\subsection{Risk associated to a single test}\label{risk_single} +If $n$ tests are available, the risk coefficient for a given test $i\in\{1,\dots,n\}$ is computed as follows, +\[\mathrm{R}_i=\sum^m_{j=1} \delta (i,j)\cdot q(i,j)\cdot \sqrt[3]{|e(i,j)|}\cdot \sqrt[3]{\varepsilon (i,j)}\cdot w(i,j) \]where $m$ is the number of lines in the output of test $i$ and +\begin{enumerate} +\item $\delta (i,j)=1 $ if line $j$ of test $i$ is about a violation of fairness, and $\delta (i,j)=0 $ otherwise, + +\item $q(i,j)$ is the number of elements in the union of the two classes (or subclasses) used for the comparison relative to line $j$ over the total number of datapoints, + +\item $e(i,j)$ is the distance between the divergence and the threshold relative to line $j$, + +\item $\varepsilon (i,j)$ is the threshold employed at line $j$, + +\item $w(i,j)$ is the weight of the possible fairness violation relative to line $j$. +\end{enumerate} + +Hence, $\delta (i,j)$ simply sets the addend relative to line $j$ to $0$ if line $j$ does not correspond to a fairness violation, $q(i,j)$ makes the addend proportional to the number of individuals involved in the possible violation over all individuals, $e(i,j)$ makes the addend proportional to the gravity of the violation in terms of distance from the threshold, $\varepsilon (i,j)$ makes the addend inversely proportional to the strictness of the threshold employed. Factors involving $e$ and $\varepsilon$ are typically\footnote{Using the automated threshold they are, but it is always possible to use customized thresholds. Notice that the closer that is to $1$, the smaller is the effect of taking the cube root.} two or three orders of magnitude smaller than the others, so we scale their weight taking their cube root. + +The weight $w(i,j)$ of the violation depends, in turn, on whether one focuses on {\it group fairness} or on {\it individual fairness}. In the first case, the weight increases if the possible fairness violation concerns a class determined by a few features (thus, a rather general class). In the second case, the weight increases if the possible fairness violation concerns a class determined by many features (thus, a rather specific class). + +\subsection{Risk associated to a battery of tests} +The risk measurement function can be formally defined as follows: +\[\frac{1}{n}\cdot \sum ^n_{i=1}\mathrm{R}_i\] +where $n$ is the number of executed tests and $R_i$ is as above. + +\section{Execution of the module} +The risk module can be executed in two modes, +\begin{enumerate} +\item the \emph{standard} mode: the user is only required to provide which features in the database are deemed `sensitive', +\item the \emph{customizable} mode: the user is required to provide the sensitive features, the tolerance (\texttt{high}/\texttt{low}), the choice to favour either \texttt{group} or \texttt{individual} fairness, the aggregating function for featured with multiple classes (\texttt{max}/\texttt{average}/\texttt{min}). +\end{enumerate} +The standard mode is simply an execution of the customizable mode with fixed parameters: \texttt{high} and \texttt{average}, and a message calculating the average and \texttt{group} and \texttt{individual}, with it broken down to each. + +\subsection{Pipeline} +Assume then that all parameters in the section above are defined. We only describe the process of checking \emph{one} sensitive feature \texttt{f}: when more are required, the user gets in output a list of each individual risks and their minimum, maximum, and average. + +Moreover, assume that we have +\begin{itemize} +\item a fixed upper bound for the execution time of single checks (=test line computations, cf. \ref{strategy}), and call this \texttt{T}, +\item a fixed lower bound for meaningful correlation indexes, and call this $\texttt{C}_0$. +\end{itemize}. + +Then the risk module + +\begin{enumerate} +\item computes the correlation between the features and the output, and orders the features in order of decreasing correlation; +\item selects only features that show correlation above $\texttt{C}_0$;\label{qui} +\item computes the greatest maximum runtime (cf. \ref{strategy}) of the algorithm with sensitive feature \texttt{f} and conditioning those selected in \ref{qui};\label{qui2} +\item returns a message showing the number of conditioning features and the upper bound in \ref{qui2}, and asks the user if they want to proceed; +\item if the user wants to proceed, it executes the module and returns the risk value, if not, it asks the user to select a new $\texttt{C}>\texttt{C}_0$ and returns to \ref{qui}. +\end{enumerate} + +\subsection{Strategy}\label{strategy} +Now we only need to provide a suitable way of using the \texttt{freqvfreq} option in our bias module. The check proceeds breadth first. For a line in the output (that is, the $j$s in \ref{risk_single}) the algorithm +\begin{enumerate} +\item starts computing the line,\label{quy} +\item if it succeeds in time $\leq\texttt{T}$, it moves on to \ref{quy2}, if not +\item it records the `bad' combination of features, and closes it for extension\footnote{Meaning that if we have conditioning $\{a,b,c,d,e\}$ and it fails at $abc$, then to the `bad' record one adds $\{abc, abcd, abce\}$, then iterate\dots},\label{bad_record} +\item $j=j+1$,\label{quy2} +\item if the combination in $j$ is in the `bad' record, go straight to \ref{quy2}, +\item go back to \ref{quy}. +\end{enumerate} +This way, it is possible to combinatorially estimate an upper bound for the computation time\footnote{Modulo everything else, that should not account for much.} (possible combinations $\times$ \texttt{T}), and depending on the user's computational capability they can decide whether they want to proceed to the calculus or not. This procedure also guarantees that failure of a check aborts all possible checks that are `extensions' of it, so that, all in all, the runtime will usually be \emph{way below} that calculated. + +\bibliography{temp} +\bibliographystyle{alpha} + +\end{document} + + diff --git a/notes on risk/main.toc b/notes on risk/main.toc new file mode 100644 index 0000000..2b33e1b --- /dev/null +++ b/notes on risk/main.toc @@ -0,0 +1,6 @@ +\contentsline {section}{\numberline {1}Overview}{1}{}% +\contentsline {subsection}{\numberline {1.1}Risk associated to a single test}{2}{}% +\contentsline {subsection}{\numberline {1.2}Risk associated to a battery of tests}{3}{}% +\contentsline {section}{\numberline {2}Execution of the module}{3}{}% +\contentsline {subsection}{\numberline {2.1}Pipeline}{3}{}% +\contentsline {subsection}{\numberline {2.2}Strategy}{4}{}% diff --git a/notes on risk/temp.bib b/notes on risk/temp.bib new file mode 100644 index 0000000..025e4b3 --- /dev/null +++ b/notes on risk/temp.bib @@ -0,0 +1,1945 @@ + +% Journals + +% First the Full Name is given, then the abbreviation used in the AMS Math +% Reviews, with an indication if it could not be found there. +% Note the 2nd overwrites the 1st, so swap them if you want the full name. + + %{AMS} + @String{AMSTrans = "American Mathematical Society Translations" } + @String{AMSTrans = "Amer. Math. Soc. Transl." } + @String{BullAMS = "Bulletin of the American Mathematical Society" } + @String{BullAMS = "Bull. Amer. Math. Soc." } + @String{ProcAMS = "Proceedings of the American Mathematical Society" } + @String{ProcAMS = "Proc. Amer. Math. Soc." } + @String{TransAMS = "Transactions of the American Mathematical Society" } + @String{TransAMS = "Trans. Amer. Math. Soc." } + + %ACM + @String{CACM = "Communications of the {ACM}" } + @String{CACM = "Commun. {ACM}" } + @String{CompServ = "Comput. Surveys" } + @String{JACM = "J. ACM" } + @String{ACMMathSoft = "{ACM} Transactions on Mathematical Software" } + @String{ACMMathSoft = "{ACM} Trans. Math. Software" } + @String{SIGNUM = "{ACM} {SIGNUM} Newsletter" } + @String{SIGNUM = "{ACM} {SIGNUM} Newslett." } + + @String{AmerSocio = "American Journal of Sociology" } + @String{AmerStatAssoc = "Journal of the American Statistical Association" } + @String{AmerStatAssoc = "J. Amer. Statist. Assoc." } + @String{ApplMathComp = "Applied Mathematics and Computation" } + @String{ApplMathComp = "Appl. Math. Comput." } + @String{AmerMathMonthly = "American Mathematical Monthly" } + @String{AmerMathMonthly = "Amer. Math. Monthly" } + @String{BIT = "{BIT}" } + @String{BritStatPsych = "British Journal of Mathematical and Statistical + Psychology" } + @String{BritStatPsych = "Brit. J. Math. Statist. Psych." } + @String{CanMathBull = "Canadian Mathematical Bulletin" } + @String{CanMathBull = "Canad. Math. Bull." } + @String{CompApplMath = "Journal of Computational and Applied Mathematics" } + @String{CompApplMath = "J. Comput. Appl. Math." } + @String{CompPhys = "Journal of Computational Physics" } + @String{CompPhys = "J. Comput. Phys." } + @String{CompStruct = "Computers and Structures" } + @String{CompStruct = "Comput. \& Structures" } + @String{CompJour = "The Computer Journal" } + @String{CompJour = "Comput. J." } + @String{CompSysSci = "Journal of Computer and System Sciences" } + @String{CompSysSci = "J. Comput. System Sci." } + @String{Computing = "Computing" } + @String{ContempMath = "Contemporary Mathematics" } + @String{ContempMath = "Contemp. Math." } + @String{Crelle = "Crelle's Journal" } + @String{GiornaleMath = "Giornale di Mathematiche" } + @String{GiornaleMath = "Giorn. Mat." } % didn't find in AMS MR., ibid. + + %IEEE + @String{Computer = "{IEEE} Computer" } + @String{IEEETransComp = "{IEEE} Transactions on Computers" } + @String{IEEETransComp = "{IEEE} Trans. Comput." } + @String{IEEETransAC = "{IEEE} Transactions on Automatic Control" } + @String{IEEETransAC = "{IEEE} Trans. Automat. Control" } + @String{IEEESpec = "{IEEE} Spectrum" } % didn't find in AMS MR + @String{ProcIEEE = "Proceedings of the {IEEE}" } + @String{ProcIEEE = "Proc. {IEEE}" } % didn't find in AMS MR + @String{IEEETransAeroElec = "{IEEE} Transactions on Aerospace and Electronic + Systems" } + @String{IEEETransAeroElec = "{IEEE} Trans. Aerospace Electron. Systems" } + + @String{IMANumerAna = "{IMA} Journal of Numerical Analysis" } + @String{IMANumerAna = "{IMA} J. Numer. Anal." } + @String{InfProcLet = "Information Processing Letters" } + @String{InfProcLet = "Inform. Process. Lett." } + @String{InstMathApp = "Journal of the Institute of Mathematics and + its Applications" } + @String{InstMathApp = "J. Inst. Math. Appl." } + @String{IntControl = "International Journal of Control" } + @String{IntControl = "Internat. J. Control" } + @String{IntNumerEng = "International Journal for Numerical Methods in + Engineering" } + @String{IntNumerEng = "Internat. J. Numer. Methods Engrg." } + @String{IntSuper = "International Journal of Supercomputing Applications" } + @String{IntSuper = "Internat. J. Supercomputing Applic." } % didn't find +%% in AMS MR + @String{Kibernetika = "Kibernetika" } + @String{JResNatBurStand = "Journal of Research of the National Bureau + of Standards" } + @String{JResNatBurStand = "J. Res. Nat. Bur. Standards" } + @String{LinAlgApp = "Linear Algebra and its Applications" } + @String{LinAlgApp = "Linear Algebra Appl." } + @String{MathAnaAppl = "Journal of Mathematical Analysis and Applications" } + @String{MathAnaAppl = "J. Math. Anal. Appl." } + @String{MathAnnalen = "Mathematische Annalen" } + @String{MathAnnalen = "Math. Ann." } + @String{MathPhys = "Journal of Mathematical Physics" } + @String{MathPhys = "J. Math. Phys." } + @String{MathComp = "Mathematics of Computation" } + @String{MathComp = "Math. Comp." } + @String{MathScand = "Mathematica Scandinavica" } + @String{MathScand = "Math. Scand." } + @String{TablesAidsComp = "Mathematical Tables and Other Aids to Computation" } + @String{TablesAidsComp = "Math. Tables Aids Comput." } + @String{NumerMath = "Numerische Mathematik" } + @String{NumerMath = "Numer. Math." } + @String{PacificMath = "Pacific Journal of Mathematics" } + @String{PacificMath = "Pacific J. Math." } + @String{ParDistComp = "Journal of Parallel and Distributed Computing" } + @String{ParDistComp = "J. Parallel and Distrib. Comput." } % didn't find +%% in AMS MR + @String{ParComputing = "Parallel Computing" } + @String{ParComputing = "Parallel Comput." } + @String{PhilMag = "Philosophical Magazine" } + @String{PhilMag = "Philos. Mag." } + @String{ProcNAS = "Proceedings of the National Academy of Sciences + of the USA" } + @String{ProcNAS = "Proc. Nat. Acad. Sci. U. S. A." } + @String{Psychometrika = "Psychometrika" } + @String{QuartMath = "Quarterly Journal of Mathematics, Oxford, Series (2)" } + @String{QuartMath = "Quart. J. Math. Oxford Ser. (2)" } + @String{QuartApplMath = "Quarterly of Applied Mathematics" } + @String{QuartApplMath = "Quart. Appl. Math." } + @String{RevueInstStat = "Review of the International Statisical Institute" } + @String{RevueInstStat = "Rev. Inst. Internat. Statist." } + + %SIAM + @String{JSIAM = "Journal of the Society for Industrial and Applied + Mathematics" } + @String{JSIAM = "J. Soc. Indust. Appl. Math." } + @String{JSIAMB = "Journal of the Society for Industrial and Applied + Mathematics, Series B, Numerical Analysis" } + @String{JSIAMB = "J. Soc. Indust. Appl. Math. Ser. B Numer. Anal." } + @String{SIAMAlgMeth = "{SIAM} Journal on Algebraic and Discrete Methods" } + @String{SIAMAlgMeth = "{SIAM} J. Algebraic Discrete Methods" } + @String{SIAMAppMath = "{SIAM} Journal on Applied Mathematics" } + @String{SIAMAppMath = "{SIAM} J. Appl. Math." } + @String{SIAMComp = "{SIAM} Journal on Computing" } + @String{SIAMComp = "{SIAM} J. Comput." } + @String{SIAMMatrix = "{SIAM} Journal on Matrix Analysis and Applications" } + @String{SIAMMatrix = "{SIAM} J. Matrix Anal. Appl." } + @String{SIAMNumAnal = "{SIAM} Journal on Numerical Analysis" } + @String{SIAMNumAnal = "{SIAM} J. Numer. Anal." } + @String{SIAMReview = "{SIAM} Review" } + @String{SIAMReview = "{SIAM} Rev." } + @String{SIAMSciStat = "{SIAM} Journal on Scientific and Statistical + Computing" } + @String{SIAMSciStat = "{SIAM} J. Sci. Statist. Comput." } + + @String{SoftPracExp = "Software Practice and Experience" } + @String{SoftPracExp = "Software Prac. Experience" } % didn't find in AMS MR + @String{StatScience = "Statistical Science" } + @String{StatScience = "Statist. Sci." } + @String{Techno = "Technometrics" } + @String{USSRCompMathPhys = "{USSR} Computational Mathematics and Mathematical + Physics" } + @String{USSRCompMathPhys = "{U. S. S. R.} Comput. Math. and Math. Phys." } + @String{VLSICompSys = "Journal of {VLSI} and Computer Systems" } + @String{VLSICompSys = "J. {VLSI} Comput. Syst." } + @String{ZAngewMathMech = "Zeitschrift fur Angewandte Mathematik und + Mechanik" } + @String{ZAngewMathMech = "Z. Angew. Math. Mech." } + @String{ZAngewMathPhys = "Zeitschrift fur Angewandte Mathematik und Physik" } + @String{ZAngewMathPhys = "Z. Angew. Math. Phys." } + +% Publishers % ================================================= | + + @String{Academic = "Academic Press" } + @String{ACMPress = "{ACM} Press" } + @String{AdamHilger = "Adam Hilger" } + @String{AddisonWesley = "Addison-Wesley" } + @String{AllynBacon = "Allyn and Bacon" } + @String{AMS = "American Mathematical Society" } + @String{Birkhauser = "Birkha{\"u}ser" } + @String{CambridgePress = "Cambridge University Press" } + @String{Chelsea = "Chelsea" } + @String{ClaredonPress = "Claredon Press" } + @String{DoverPub = "Dover Publications" } + @String{Eyolles = "Eyolles" } + @String{HoltRinehartWinston = "Holt, Rinehart and Winston" } + @String{Interscience = "Interscience" } + @String{JohnsHopkinsPress = "The Johns Hopkins University Press" } + @String{JohnWileySons = "John Wiley and Sons" } + @String{Macmillan = "Macmillan" } + @String{MathWorks = "The Math Works Inc." } + @String{McGrawHill = "McGraw-Hill" } + @String{NatBurStd = "National Bureau of Standards" } + @String{NorthHolland = "North-Holland" } + @String{OxfordPress = "Oxford University Press" } %address Oxford or London? + @String{PergamonPress = "Pergamon Press" } + @String{PlenumPress = "Plenum Press" } + @String{PrenticeHall = "Prentice-Hall" } + @String{SIAMPub = "{SIAM} Publications" } + @String{Springer = "Springer-Verlag" } + @String{TexasPress = "University of Texas Press" } + @String{VanNostrand = "Van Nostrand" } + @String{WHFreeman = "W. H. Freeman and Co." } + +%Entries + + +@inproceedings{DBLP:conf/beware/CoragliaDGGPPQ23, + author = {Greta Coraglia and + Fabio Aurelio D'Asaro and + Francesco Antonio Genco and + Davide Giannuzzi and + Davide Posillipo and + Giuseppe Primiero and + Christian Quaggio}, + editor = {Guido Boella and + Fabio Aurelio D'Asaro and + Abeer Dyoub and + Laura Gorrieri and + Francesca A. Lisi and + Chiara Manganini and + Giuseppe Primiero}, + title = {BRIOxAlkemy: a Bias Detecting Tool}, + booktitle = {Proceedings of the 2nd Workshop on Bias, Ethical AI, Explainability + and the role of Logic and Logic Programming co-located with the 22nd + International Conference of the Italian Association for Artificial + Intelligence (AI*IA 2023), Rome, Italy, November 6, 2023}, + series = {{CEUR} Workshop Proceedings}, + volume = {3615}, + pages = {44--60}, + publisher = {CEUR-WS.org}, + year = {2023}, + url = {https://ceur-ws.org/Vol-3615/paper4.pdf}, + timestamp = {Thu, 25 Jan 2024 16:38:44 +0100}, + biburl = {https://dblp.org/rec/conf/beware/CoragliaDGGPPQ23.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + + + +@article{gp23, + author = {Genco, F.A. and Primiero, G.}, + title = {A Typed Lambda-Calculus for Establishing Trust in Probabilistic Programs}, + journal={{A}rXiv e-prints}, + year = {2023}} + +@article{dagp22, + title={Checking Trustworthiness of Probabilistic Computations in a Typed Natural Deduction System}, + author={D'Asaro, F.A. and Genco, F.A. and Primiero, G.}, + journal={{A}rXiv e-prints}, + year={2022} +} + +@article{pk16, + title={The Semantics of Untrustworthiness}, + author={Primiero, G. and Kosolosky, L.}, + journal={Topoi}, + volume={35}, + pages={253--266}, + year={2016} +} + + +@inproceedings{dap21, + title={Probabilistic typed natural deduction for trustworthy computations}, + author={D’Asaro, F.A. and Primiero, G.}, + booktitle={Proceedings of the 22nd International Workshop on Trust in Agent Societies (TRUST2021@ AAMAS)}, + year={2021} +} + + +@article{YEH20092473, + abstract = {This research aimed at the case of customers' default payments in Taiwan and compares the predictive accuracy of probability of default among six data mining methods. From the perspective of risk management, the result of predictive accuracy of the estimated probability of default will be more valuable than the binary result of classification - credible or not credible clients. Because the real probability of default is unknown, this study presented the novel ``Sorting Smoothing Method'' to estimate the real probability of default. With the real probability of default as the response variable (Y), and the predictive probability of default as the independent variable (X), the simple linear regression result (Y=A+BX) shows that the forecasting model produced by artificial neural network has the highest coefficient of determination; its regression intercept (A) is close to zero, and regression coefficient (B) to one. Therefore, among the six data mining techniques, artificial neural network is the only one that can accurately estimate the real probability of default.}, + author = {I-Cheng Yeh and {Che-hui} Lien}, + doi = {https://doi.org/10.1016/j.eswa.2007.12.020}, + issn = {0957-4174}, + journal = {Expert Systems with Applications}, + keywords = {Banking, Neural network, Probability, Data mining}, + number = {2, Part 1}, + pages = {2473-2480}, + title = {The comparisons of data mining techniques for the predictive accuracy of probability of default of credit card clients}, + url = {https://www.sciencedirect.com/science/article/pii/S0957417407006719}, + volume = {36}, + year = {2009}, + bdsk-url-1 = {https://www.sciencedirect.com/science/article/pii/S0957417407006719}, + bdsk-url-2 = {https://doi.org/10.1016/j.eswa.2007.12.020}} + + + +@Article{Abril07, + author = "Patricia S. Abril and Robert Plant", + title = "The patent holder's dilemma: Buy, sell, or troll?", + journal = "Communications of the ACM", + volume = "50", + number = "1", + month = jan, + year = "2007", + pages = "36--44", + doi = "10.1145/1188913.1188915", + OPTurl = "http://doi.acm.org/10.1145/1219092.1219093", + note = "", +} + +@book{levin2017markov, + title={Markov Chains and Mixing Times}, + author={Levin, D.A. and Peres, Y.}, + isbn={9781470429621}, + lccn={2017017451}, + series={MBK}, + url={https://books.google.ch/books?id=f208DwAAQBAJ}, + year={2017}, + publisher={American Mathematical Society} +} + + +@ARTICLE{lin_divergence, + + author={Lin, J.}, + + journal={IEEE Transactions on Information Theory}, + + title={Divergence measures based on the Shannon entropy}, + + year={1991}, + + volume={37}, + + number={1}, + + pages={145-151}, + + doi={10.1109/18.61115}} + + +@Article{Cohen07, + author = "Sarah Cohen and Werner Nutt and Yehoshua Sagic", + title = "Deciding equivalances among conjunctive aggregate queries", + journal = JACM, + articleno = "5", + numpages = "50", + volume = "54", + number = "2", + month = apr, + year = "2007", + doi = "10.1145/1219092.1219093", + OPTurl = "http://doi.acm.org/10.1145/1219092.1219093", + acmid = "1219093", + note = "", +} + + +@Proceedings{JCohen96, + key = "Cohen", + editor = "Jacques Cohen", + title = "Special issue: Digital Libraries", + journal = CACM, + volume = "39", + number = "11", + month = nov, + year = "1996", +} + + +@Book{Kosiur01, + author = "David Kosiur", + title = "Understanding Policy-Based Networking", + publisher = "Wiley", + year = "2001", + address = "New York, NY", + edition = "2nd.", + editor = "", + volume = "", + number = "", + series = "", + month = "", + note = "", +} + + +@Book{Harel79, + author = "David Harel", + year = "1979", + title = "First-Order Dynamic Logic", + series = "Lecture Notes in Computer Science", + volume = "68", + address = "New York, NY", + publisher = "Springer-Verlag", + doi = "10.1007/3-540-09237-4", + OPTurl = "http://dx.doi.org/10.1007/3-540-09237-4", + editor = "", + number = "", + month = "", + note = "", +} + + +@Inbook{Editor00, + author = "", + editor = "Ian Editor", + title = "The title of book one", + subtitle = "The book subtitle", + series = "The name of the series one", + year = "2007", + volume = "9", + address = "Chicago", + edition = "1st.", + publisher = "University of Chicago Press", + doi = "10.1007/3-540-09237-4", + OPTurl = "http://dx.doi.org/10.1007/3-540-09456-9", + chapter = "", + pages = "", + number = "", + type = "", + month = "", + note = "", +} + +% +@InBook{Editor00a, + author = "", + editor = "Ian Editor", + title = "The title of book two", + subtitle = "The book subtitle", + series = "The name of the series two", + year = "2008", + address = "Chicago", + edition = "2nd.", + publisher = "University of Chicago Press", + doi = "10.1007/3-540-09237-4", + OPTurl = "http://dx.doi.org/10.1007/3-540-09456-9", + volume = "", + chapter = "100", + pages = "", + number = "", + type = "", + month = "", + note = "", +} + + +% incollection (has an editor, title, and possibly a booktitle) +@Incollection{Spector90, + author = "Asad Z. Spector", + title = "Achieving application requirements", + booktitle = "Distributed Systems", + publisher = "ACM Press", + address = "New York, NY", + year = "1990", + edition = "2nd.", + chapter = "", + editor = "Sape Mullender", + pages = "19--33", + doi = "10.1145/90417.90738", + OPTurl = "http://doi.acm.org/10.1145/90417.90738", + volume = "", + number = "", + series = "", + type = "", + month = "", + note = "", +} + + +@INPROCEEDINGS{6413831, + + author={Kamiran, Faisal and Karim, Asim and Zhang, Xiangliang}, + + booktitle={2012 IEEE 12th International Conference on Data Mining}, + + title={Decision Theory for Discrimination-Aware Classification}, + + year={2012}, + + volume={}, + + number={}, + + pages={924-929}, + + doi={10.1109/ICDM.2012.45}} + + + +@inproceedings{NIPS2017_b8b9c74a, + author = {Pleiss, Geoff and Raghavan, Manish and Wu, Felix and Kleinberg, Jon and Weinberger, Kilian Q}, + booktitle = {Advances in Neural Information Processing Systems}, + editor = {I. Guyon and U. Von Luxburg and S. Bengio and H. Wallach and R. Fergus and S. Vishwanathan and R. Garnett}, + pages = {}, + publisher = {Curran Associates, Inc.}, + title = {On Fairness and Calibration}, + url = {https://proceedings.neurips.cc/paper_files/paper/2017/file/b8b9c74ac526fffbeb2d39ab038d1cd7-Paper.pdf}, + volume = {30}, + year = {2017} +} + + + +@inproceedings{NIPS2016_9d268236, + author = {Hardt, Moritz and Price, Eric and Price, Eric and Srebro, Nati}, + booktitle = {Advances in Neural Information Processing Systems}, + editor = {D. Lee and M. Sugiyama and U. Luxburg and I. Guyon and R. Garnett}, + pages = {}, + publisher = {Curran Associates, Inc.}, + title = {Equality of Opportunity in Supervised Learning}, + url = {https://proceedings.neurips.cc/paper_files/paper/2016/file/9d2682367c3935defcb1f9e247a97c0d-Paper.pdf}, + volume = {29}, + year = {2016} +} + + +@article{dAlessandro2017ConscientiousCA, + title={Conscientious Classification: A Data Scientist's Guide to Discrimination-Aware Classification}, + author={Brian d'Alessandro and Cathy O'Neil and Tom LaGatta}, + journal={Big data}, + year={2017}, + volume={5 2}, + pages={ + 120-134 + }, + url={https://api.semanticscholar.org/CorpusID:4414223} +} + +@ARTICLE{beletal2019, + author={Bellamy, R. K. E. and Dey, K. and Hind, M. and Hoffman, S. C. and Houde, S. and Kannan, K. and Lohia, P. and Martino, J. and Mehta, S. and Mojsilović, A. and Nagar, S. and Ramamurthy, K. Natesan and Richards, J. and Saha, D. and Sattigeri, P. and Singh, M. and Varshney, K. R. and Zhang, Y.}, + journal={IBM Journal of Research and Development}, + title={AI Fairness 360: An extensible toolkit for detecting and mitigating algorithmic bias}, + year={2019}, + volume={63}, + number={4/5}, + pages={4:1-15}, + doi={10.1147/JRD.2019.2942287}} + +@ARTICLE{fuetal2020, +author={Runshan Fu and Yan Huang and Param Vir Singh}, +journal={INFORMS TutORials in Operations Research}, +title={Artificial Intelligence and Algorithmic Bias: Source, Detection, Mitigation, and Implications}, +year={2020}, +pages={39-63} +} + + +@INPROCEEDINGS{6413831, + + author={Kamiran, Faisal and Karim, Asim and Zhang, Xiangliang}, + + booktitle={2012 IEEE 12th International Conference on Data Mining}, + + title={Decision Theory for Discrimination-Aware Classification}, + + year={2012}, + + volume={}, + + number={}, + + pages={924-929}, + + doi={10.1109/ICDM.2012.45}} + + + +@inproceedings{NIPS2017_b8b9c74a, + author = {Pleiss, Geoff and Raghavan, Manish and Wu, Felix and Kleinberg, Jon and Weinberger, Kilian Q}, + booktitle = {Advances in Neural Information Processing Systems}, + editor = {I. Guyon and U. Von Luxburg and S. Bengio and H. Wallach and R. Fergus and S. Vishwanathan and R. Garnett}, + pages = {}, + publisher = {Curran Associates, Inc.}, + title = {On Fairness and Calibration}, + url = {https://proceedings.neurips.cc/paper_files/paper/2017/file/b8b9c74ac526fffbeb2d39ab038d1cd7-Paper.pdf}, + volume = {30}, + year = {2017} +} + + + +@inproceedings{NIPS2016_9d268236, + author = {Hardt, Moritz and Price, Eric and Price, Eric and Srebro, Nati}, + booktitle = {Advances in Neural Information Processing Systems}, + editor = {D. Lee and M. Sugiyama and U. Luxburg and I. Guyon and R. Garnett}, + pages = {}, + publisher = {Curran Associates, Inc.}, + title = {Equality of Opportunity in Supervised Learning}, + url = {https://proceedings.neurips.cc/paper_files/paper/2016/file/9d2682367c3935defcb1f9e247a97c0d-Paper.pdf}, + volume = {29}, + year = {2016} +} + + +@article{dAlessandro2017ConscientiousCA, + title={Conscientious Classification: A Data Scientist's Guide to Discrimination-Aware Classification}, + author={Brian d'Alessandro and Cathy O'Neil and Tom LaGatta}, + journal={Big data}, + year={2017}, + volume={5 2}, + pages={ + 120-134 + }, + url={https://api.semanticscholar.org/CorpusID:4414223} +} + +@misc{hrw, + title = {EU: Artificial Intelligence Regulation Should Protect People’s Rights}, + author = {{Human Rights Watch}}, + year = 2023, + note = {\url{https://www.hrw.org/news/2023/07/12/eu-artificial-intelligence-regulation-should-protect-peoples-rights} [Accessed: October 2023]} +} + +@article{NINOADAN2021115424, +title = {Feature weighting methods: A review}, +journal = {Expert Systems with Applications}, +volume = {184}, +pages = {115424}, +year = {2021}, +issn = {0957-4174}, +doi = {https://doi.org/10.1016/j.eswa.2021.115424}, +url = {https://www.sciencedirect.com/science/article/pii/S0957417421008423}, +author = {Iratxe Niño-Adan and Diana Manjarres and Itziar Landa-Torres and Eva Portillo}, +keywords = {Feature weighting, Feature importance, Feature relevance, Review}, +abstract = {In the last decades, a wide portfolio of Feature Weighting (FW) methods have been proposed in the literature. Their main potential is the capability to transform the features in order to contribute to the Machine Learning (ML) algorithm metric proportionally to their estimated relevance for inferring the output pattern. Nevertheless, the extensive number of FW related works makes difficult to do a scientific study in this field of knowledge. Therefore, in this paper a global taxonomy for FW methods is proposed by focusing on: (1) the learning approach (supervised or unsupervised), (2) the methodology used to calculate the weights (global or local), and (3) the feedback obtained from the ML algorithm when estimating the weights (filter or wrapper). Among the different taxonomy levels, an extensive review of the state-of-the-art is presented, followed by some considerations and guide points for the FW strategies selection regarding significant aspects of real-world data analysis problems. Finally, a summary of conclusions and challenges in the FW field is briefly outlined.} +} + + +% incollection (has an editor, title, and possibly a booktitle) +@Incollection{Douglass98, + author = "Bruce P. Douglass and David Harel and Mark B. Trakhtenbrot", + title = "Statecarts in use: structured analysis and object-orientation", + series = "Lecture Notes in Computer Science", + booktitle = "Lectures on Embedded Systems", + publisher = "Springer-Verlag", + address = "London", + volume = "1494", + year = "1998", + chapter = "", + editor = "Grzegorz Rozenberg and Frits W. Vaandrager", + pages = "368--394", + doi = "10.1007/3-540-65193-4_29", + OPTurl = "http://dx.doi.org/10.1007/3-540-65193-4_29", + edition = "", + number = "", + type = "", + month = "", + note = "", +} + + +@Book{Knuth97, + author = "Donald E. Knuth", + title = "The Art of Computer Programming, Vol. 1: Fundamental Algorithms (3rd. ed.)", + publisher = "Addison Wesley Longman Publishing Co., Inc.", + year = "1997", + address = "", + edition = "", + editor = "", + volume = "", + number = "", + series = "", + month = "", + note = "", +} + + +@Book{Knuth98, + author = "Donald E. Knuth", + year = "1998", + title = "The Art of Computer Programming", + series = "Fundamental Algorithms", + volume = "1", + edition = "3rd", + address = "", + publisher = "Addison Wesley Longman Publishing Co., Inc.", + doi = "", + url = "", + editor = "", + number = "", + month = "", + note = "(book)", +} + +%Inbook{Knuth97, +% author = "Donald E. Knuth", +% title = "The Art of Computer Programming", +% booktitle = "the booktitle", +% edition = "3", +% volume = "1", +% year = "1997", +% publisher = "Addison Wesley Longman Publishing Co., Inc.", +% editor = "", +% number = "", +% series = "Fundamental Algorithms", +% type = "", +% chapter = "", +% pages = "", +% address = "", +% month = "", +% note = "(inbook)", +%} + +%INBOOK{DK:73-inbook-full, +% author = "Donald E. Knuth", +% title = "Fundamental Algorithms (inbook w series)", +% volume = 1, +% series = "The Art of Computer Programming", +% publisher = "Addison-Wesley", +% address = "Reading, Massachusetts", +% edition = "Second", +% month = "10~" # jan, +% year = "1973", +% type = "Section", +% chapter = "1.2", +% pages = "10--119", +% note = "Full INBOOK entry (w series)", +%} + +%INcollection{DK:74-incoll, +% author = "Donald E. Knuth", +% title = "Fundamental Algorithms (incoll)", +% volume = 1, +% booktitle = "The Art of Computer Programming", +% publisher = "Addison-Wesley", +% address = "Reading, Massachusetts", +% month = "10~" # jan, +% year = "1974", +% pages = "10--119", +% editor = "Bernard Rous", +% note = "This is a full incoll entry with an editor", +%} + +%INcollection{DK:75-incollws, +% author = "Donald E. Knuth", +% title = "Fundamental Algorithms (incoll w series)", +% volume = 1, +% booktitle = "The Art of Computer Programming", +% series = "The Art of Computer Programming", +% publisher = "Addison-Wesley", +% address = "Reading, Massachusetts", +% month = "10~" # jan, +% year = "1975", +% pages = "10--119", +% editor = "Bernard Rous", +% note = "This is a full incoll entry with an editor and series", +%} + + +@incollection{GM05, +Author= "Dan Geiger and Christopher Meek", +Title= "Structured Variational Inference Procedures and their Realizations (as incol)", +Year= 2005, +Booktitle="Proceedings of Tenth International Workshop on Artificial Intelligence and Statistics, {\rm The Barbados}", +Publisher="The Society for Artificial Intelligence and Statistics", +Month= jan, +Editors= "Z. Ghahramani and R. Cowell" +} + +@Inproceedings{Smith10, + author = "Stan W. Smith", + title = "An experiment in bibliographic mark-up: Parsing metadata for XML export", + booktitle = "Proceedings of the 3rd. annual workshop on Librarians and Computers", + series = "LAC '10", + editor = "Reginald N. Smythe and Alexander Noble", + volume = "3", + year = "2010", + publisher = "Paparazzi Press", + address = "Milan Italy", + pages = "422--431", + doi = "99.9999/woot07-S422", + OPTurl = "http://dx.doi.org/99.0000/woot07-S422", + number = "", + month = "", + organization = "", + note = "", +} + +@Inproceedings{VanGundy07, + author = "Matthew Van Gundy and Davide Balzarotti and Giovanni Vigna", + year = "2007", + title = "Catch me, if you can: Evading network signatures with web-based polymorphic worms", + booktitle = "Proceedings of the first USENIX workshop on Offensive Technologies", + series = "WOOT '07", + publisher = "USENIX Association", + address = "Berkley, CA", + articleno = "7", + numpages = "9", + editor = "", + volume = "", + number = "", + pages = "", + month = "", + organization = "", + note = "", +} + +@Inproceedings{VanGundy08, + author = "Matthew Van Gundy and Davide Balzarotti and Giovanni Vigna", + year = "2008", + title = "Catch me, if you can: Evading network signatures with web-based polymorphic worms", + booktitle = "Proceedings of the first USENIX workshop on Offensive Technologies", + series = "WOOT '08", + publisher = "USENIX Association", + address = "Berkley, CA", + articleno = "7", + numpages = "2", + editor = "", + volume = "", + number = "", + pages = "99-100", + month = "", + organization = "", + note = "", +} + +@Inproceedings{VanGundy09, + author = "Matthew Van Gundy and Davide Balzarotti and Giovanni Vigna", + year = "2009", + title = "Catch me, if you can: Evading network signatures with web-based polymorphic worms", + booktitle = "Proceedings of the first USENIX workshop on Offensive Technologies", + series = "WOOT '09", + publisher = "USENIX Association", + address = "Berkley, CA", + articleno = "", + numpages = "", + editor = "", + volume = "", + number = "", + pages = "90--100", + month = "", + organization = "", + note = "", +} + +@Inproceedings{Andler79, + author = "Sten Andler", + title = "Predicate Path expressions", + booktitle = "Proceedings of the 6th. ACM SIGACT-SIGPLAN symposium on Principles of Programming Languages", + series = "POPL '79", + year = "1979", + publisher = "ACM Press", + address = "New York, NY", + pages = "226--236", + doi = "10.1145/567752.567774", + OPTurl = "http://doi.acm.org/10.1145/567752.567774", + editor = "", + volume = "", + number = "", + month = "", + organization = "", + note = "", +} + +@Techreport{Harel78, + author = "David Harel", + year = "1978", + title = "LOGICS of Programs: AXIOMATICS and DESCRIPTIVE POWER", + institution = "Massachusetts Institute of Technology", + type = "MIT Research Lab Technical Report", + number = "TR-200", + address = "Cambridge, MA", + month = "", + note = "", +} + +@MASTERSTHESIS{anisi03, +author = {David A. Anisi}, +title = {Optimal Motion Control of a Ground Vehicle}, +school = {Royal Institute of Technology (KTH), Stockholm, Sweden}, +intitution = {FOI-R-0961-SE, Swedish Defence Research Agency (FOI)}, +year = {2003}, +} + + +@Phdthesis{Clarkson85, + author = "Kenneth L. Clarkson", + year = "1985", + title = "Algorithms for Closest-Point Problems (Computational Geometry)", + school = "Stanford University", + address = "Palo Alto, CA", + note = "UMI Order Number: AAT 8506171", + type = "", + month = "", +} + + +@misc{Thornburg01, + author = "Harry Thornburg", + year = "2001", + title = "Introduction to Bayesian Statistics", + url = "http://ccrma.stanford.edu/~jos/bayes/bayes.html", + month = mar, + lastaccessed = "March 2, 2005", +} + + +@misc{Ablamowicz07, + author = "Rafal Ablamowicz and Bertfried Fauser", + year = "2007", + title = "CLIFFORD: a Maple 11 Package for Clifford Algebra Computations, version 11", + url = "http://math.tntech.edu/rafal/cliff11/index.html", + lastaccessed = "February 28, 2008", +} + + +@misc{Poker06, + author = "Poker-Edge.Com", + year = "2006", + month = mar, + title = "Stats and Analysis", + lastaccessed = "June 7, 2006", + url = "http://www.poker-edge.com/stats.php", +} + +@misc{Obama08, + author = "Barack Obama", + year = "2008", + title = "A more perfect union", + howpublished = "Video", + day = "5", + url = "http://video.google.com/videoplay?docid=6528042696351994555", + month = mar, + lastaccessed = "March 21, 2008", + note = "", +} + +@misc{JoeScientist001, + author = "Joseph Scientist", + year = "2009", + title = "The fountain of youth", + note = "Patent No. 12345, Filed July 1st., 2008, Issued Aug. 9th., 2009", + url = "", + howpublished = "", + month = aug, + lastaccessed = "", +} + + +@Inproceedings{Novak03, + author = "Dave Novak", + title = "Solder man", + booktitle = "ACM SIGGRAPH 2003 Video Review on Animation theater Program: Part I - Vol. 145 (July 27--27, 2003)", + year = "2003", + publisher = "ACM Press", + address = "New York, NY", + pages = "4", + month = "March 21, 2008", + doi = "99.9999/woot07-S422", + url = "http://video.google.com/videoplay?docid=6528042696351994555", + note = "", + howpublished = "Video", + editor = "", + volume = "", + number = "", + series = "", + organization = "", +} + + +@article{Lee05, + author = "Newton Lee", + year = "2005", + title = "Interview with Bill Kinder: January 13, 2005", + journal = "Comput. Entertain.", + eid = "4", + volume = "3", + number = "1", + month = "Jan.-March", + doi = "10.1145/1057270.1057278", + OPTurl = "http://doi.acm.org/10.1145/1057270.1057278", + howpublished = "Video", + note = "", +} + +@article{Rous08, + author = "Bernard Rous", + year = "2008", + title = "The Enabling of Digital Libraries", + journal = "Digital Libraries", + volume = "12", + number = "3", + month = jul, + articleno = "5", + doi = "", + url = "", + howpublished = "", + note = "To appear", +} + +@article{384253, + author = {Werneck,, Renato and Setubal,, Jo\~{a}o and da Conceic\~{a}o,, Arlindo}, + title = {(old) Finding minimum congestion spanning trees}, + journal = {J. Exp. Algorithmics}, + volume = {5}, + year = {2000}, + issn = {1084-6654}, + pages = {11}, + doi = {10.1145/351827.384253}, + publisher = {ACM}, + address = {New York, NY, USA}, + } + + +@article{Werneck:2000:FMC:351827.384253, + author = {Werneck, Renato and Setubal, Jo\~{a}o and da Conceic\~{a}o, Arlindo}, + title = {(new) Finding minimum congestion spanning trees}, + journal = {J. Exp. Algorithmics}, + volume = {5}, + month = dec, + year = {2000}, + issn = {1084-6654}, + articleno = {11}, + OPTurl = {http://portal.acm.org/citation.cfm?id=351827.384253}, + doi = {10.1145/351827.384253}, + acmid = {384253}, + publisher = {ACM}, + address = {New York, NY, USA}, +} + +@article{1555162, + author = {Conti, Mauro and Di Pietro, Roberto and Mancini, Luigi V. and Mei, Alessandro}, + title = {(old) Distributed data source verification in wireless sensor networks}, + journal = {Inf. Fusion}, + volume = {10}, + number = {4}, + year = {2009}, + issn = {1566-2535}, + pages = {342--353}, + doi = {10.1016/j.inffus.2009.01.002}, + publisher = {Elsevier Science Publishers B. V.}, + address = {Amsterdam, The Netherlands, The Netherlands}, + } + +@article{Conti:2009:DDS:1555009.1555162, + author = {Conti, Mauro and Di Pietro, Roberto and Mancini, Luigi V. and Mei, Alessandro}, + title = {(new) Distributed data source verification in wireless sensor networks}, + journal = {Inf. Fusion}, + volume = {10}, + number = {4}, + month = oct, + year = {2009}, + issn = {1566-2535}, + pages = {342--353}, + numpages = {12}, + OPTurl = {http://portal.acm.org/citation.cfm?id=1555009.1555162}, + doi = {10.1016/j.inffus.2009.01.002}, + acmid = {1555162}, + publisher = {Elsevier Science Publishers B. V.}, + address = {Amsterdam, The Netherlands, The Netherlands}, + keywords = {Clone detection, Distributed protocol, Securing data fusion, Wireless sensor networks}, +} + +@inproceedings{Li:2008:PUC:1358628.1358946, + author = {Li, Cheng-Lun and Buyuktur, Ayse G. and Hutchful, David K. and Sant, Natasha B. and Nainwal, Satyendra K.}, + title = {Portalis: using competitive online interactions to support aid initiatives for the homeless}, + booktitle = {CHI '08 extended abstracts on Human factors in computing systems}, + year = {2008}, + isbn = {978-1-60558-012-X}, + location = {Florence, Italy}, + pages = {3873--3878}, + numpages = {6}, + OPTurl = {http://portal.acm.org/citation.cfm?id=1358628.1358946}, + doi = {10.1145/1358628.1358946}, + acmid = {1358946}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {cscw, distributed knowledge acquisition, incentive design, online games, recommender systems, reputation systems, user studies, virtual community}, +} + +@book{Hollis:1999:VBD:519964, + author = {Hollis, Billy S.}, + title = {Visual Basic 6: Design, Specification, and Objects with Other}, + year = {1999}, + isbn = {0130850845}, + edition = {1st}, + publisher = {Prentice Hall PTR}, + address = {Upper Saddle River, NJ, USA}, + } + + +@book{Goossens:1999:LWC:553897, + author = {Goossens, Michel and Rahtz, S. P. and Moore, Ross and Sutor, Robert S.}, + title = {The Latex Web Companion: Integrating TEX, HTML, and XML}, + year = {1999}, + isbn = {0201433117}, + edition = {1st}, + publisher = {Addison-Wesley Longman Publishing Co., Inc.}, + address = {Boston, MA, USA}, + } + +% need to test genres for errant isbn output + +% techreport +@techreport{897367, + author = {Buss, Jonathan F. and Rosenberg, Arnold L. and Knott, Judson D.}, + title = {Vertex Types in Book-Embeddings}, + year = {1987}, + source = {http://www.ncstrl.org:8900/ncstrl/servlet/search?formname=detail\&id=oai%3Ancstrlh%3Aumass_cs%3Ancstrl.umassa_cs%2F%2FUM-CS-1987-018}, + publisher = {University of Massachusetts}, + address = {Amherst, MA, USA}, + } + +@techreport{Buss:1987:VTB:897367, + author = {Buss, Jonathan F. and Rosenberg, Arnold L. and Knott, Judson D.}, + title = {Vertex Types in Book-Embeddings}, + year = {1987}, + source = {http://www.ncstrl.org:8900/ncstrl/servlet/search?formname=detail\&id=oai%3Ancstrlh%3Aumass_cs%3Ancstrl.umassa_cs%2F%2FUM-CS-1987-018}, + publisher = {University of Massachusetts}, + address = {Amherst, MA, USA}, + } + +% whole proceedings + +@proceedings{Czerwinski:2008:1358628, + author = {}, + note = {General Chair-Czerwinski, Mary and General Chair-Lund, Arnie and Program Chair-Tan, Desney}, + title = {CHI '08: CHI '08 extended abstracts on Human factors in computing systems}, + year = {2008}, + isbn = {978-1-60558-012-X}, + location = {Florence, Italy}, + order_no = {608085}, + publisher = {ACM}, + address = {New York, NY, USA}, + } + +% phdthesis + +@phdthesis{Clarkson:1985:ACP:911891, + author = {Clarkson, Kenneth Lee}, + advisor = {Yao, Andrew C.}, + title = {Algorithms for Closest-Point Problems (Computational Geometry)}, + year = {1985}, + note = {AAT 8506171}, + school = {Stanford University}, + address = {Stanford, CA, USA}, + } +% school is being picked up -- but not publisher (which is OK) +% Also -- the title is NOT being output in italics !!! Arrrrgh! - I fixed it. :-) + + +%%% compare with 'old' +%%% atsign-Phdthesis{Clarkson85, +%%% author = "Kenneth L. Clarkson", +%%% year = "1985", +%%% title = "Algorithms for Closest-Point Problems (Computational Geometry)", +%%% school = "Stanford University", +%%% address = "Palo Alto, CA", +%%% note = "UMI Order Number: AAT 8506171", +%%% type = "", +%%% month = "", +%%%} + +% A bibliography +@Article{1984:1040142, + key = {{$\!\!$}}, + journal = {SIGCOMM Comput. Commun. Rev.}, + year = {1984}, + issn = {0146-4833}, + volume = {13-14}, + number = {5-1}, + issue_date = {January/April 1984}, + publisher = {ACM}, + address = {New York, NY, USA}, + } + + +% grinder +@inproceedings{2004:ITE:1009386.1010128, + key = {IEEE}, + title = {IEEE TCSC Executive Committee}, + booktitle = {Proceedings of the IEEE International Conference on Web Services}, + series = {ICWS '04}, + year = {2004}, + isbn = {0-7695-2167-3}, + pages = {21--22}, + OPTurl = {http://dx.doi.org/10.1109/ICWS.2004.64}, + doi = {10.1109/ICWS.2004.64}, + acmid = {1010128}, + publisher = {IEEE Computer Society}, + address = {Washington, DC, USA}, +} + +% div book +@book{Mullender:1993:DS(:302430, + editor = {Mullender, Sape}, + title = {Distributed systems (2nd Ed.)}, + year = {1993}, + isbn = {0-201-62427-3}, + publisher = {ACM Press/Addison-Wesley Publishing Co.}, + address = {New York, NY, USA}, + } + +% master thesis (as techreport and thesis) + +@techreport{Petrie:1986:NAD:899644, + author = {Petrie, Charles J.}, + title = {New Algorithms for Dependency-Directed Backtracking (Master's thesis)}, + year = {1986}, + source = {http://www.ncstrl.org:8900/ncstrl/servlet/search?formname=detail\&id=oai%3Ancstrlh%3Autexas_cs%3AUTEXAS_CS%2F%2FAI86-33}, + publisher = {University of Texas at Austin}, + address = {Austin, TX, USA}, + } + +@MASTERSTHESIS{Petrie:1986:NAD:12345, + author = {Petrie, Charles J.}, + title = {New Algorithms for Dependency-Directed Backtracking (Master's thesis)}, + year = {1986}, + source = {http://www.ncstrl.org:8900/ncstrl/servlet/search?formname=detail\&id=oai%3Ancstrlh%3Autexas_cs%3AUTEXAS_CS%2F%2FAI86-33}, + school = {University of Texas at Austin}, + address = {Austin, TX, USA}, + } + + + + +@BOOK{book-minimal, + author = "Donald E. Knuth", + title = "Seminumerical Algorithms", + publisher = "Addison-Wesley", + year = "1981", +} + +% incollection (has an editor, title, and possibly a booktitle) +@INcollection{KA:2001, + author = {Kong, Wei-Chang}, + Title = {The implementation of electronic commerce in SMEs in Singapore (as Incoll)}, + booktitle = {E-commerce and cultural values}, + year = {2001}, + isbn = {1-59140-056-2}, + pages = {51--74}, + numpages = {24}, + OPTurl = {http://portal.acm.org/citation.cfm?id=887006.887010}, + acmid = {887010}, + publisher = {IGI Publishing}, + address = {Hershey, PA, USA}, +} + + +% with bibfield 'type' before chapter (note no editor) +@INBOOK{KAGM:2001, + author = {Kong, Wei-Chang}, + type = {Name of Chapter:}, + chapter = {The implementation of electronic commerce in SMEs in Singapore (Inbook-w-chap-w-type)}, + title = {E-commerce and cultural values}, + year = {2001}, + isbn = {1-59140-056-2}, + pages = {51--74}, + numpages = {24}, + OPTurl = {http://portal.acm.org/citation.cfm?id=887006.887010}, + acmid = {887010}, + publisher = {IGI Publishing}, + address = {Hershey, PA, USA}, +} + +%%% Notes! This is because the atsign-INBOOK citation type specifies EITHER +%%% editor or author, but not both. In my experiments with the harvard/dcu +%%% bibtex style (and presumably this applies to other styles too), bibtex +%%% ignores the editor information if author information exists in an +%%% atsign-INBOOK entry. atsign-INCOLLECTION is far more commonly used in my references, +%%% and in the absence of an editor I believe most bibtex styles will just +%%% ommit the editor from the reference - the chapter information will not +%%% end up in the in-text citation as you suggest it should be but at least +%%% there is a place to put the editor if necessary. + + + +% was 'Inbook' -- changed to incollection - (editor is different to author) - need to tell Asad to codify as such. +@incollection{Kong:2002:IEC:887006.887010, + author = {Kong, Wei-Chang}, + editor = {Theerasak Thanasankit}, + title = {Chapter 9}, + booktitle = {E-commerce and cultural values (Incoll-w-text (chap 9) 'title')}, + year = {2002}, + address = {Hershey, PA, USA}, + publisher = {IGI Publishing}, + OPTurl = {http://portal.acm.org/citation.cfm?id=887006.887010}, + pages = {51--74}, + numpages = {24}, + acmid = {887010}, + isbn = {1-59140-056-2}, + number = "", + type = "", + month = "", + note = "", +} + +% incol when the chapter is 'text' - due to presence of editor (different to author) +@incollection{Kong:2003:IEC:887006.887011, + author = {Kong, Wei-Chang}, + title = {The implementation of electronic commerce in SMEs in Singapore (Incoll)}, + booktitle = {E-commerce and cultural values}, + editor = {Thanasankit, Theerasak}, + year = {2003}, + isbn = {1-59140-056-2}, + pages = {51--74}, + numpages = {24}, + OPTurl = {http://portal.acm.org/citation.cfm?id=887006.887010}, + acmid = {887010}, + publisher = {IGI Publishing}, + address = {Hershey, PA, USA}, +} + +% ------ test +%incollection{Kong:2003:IEC:887006.887010, +% author = {Kong, Wei-Chang}, +% chapter = {The implementation of electronic commerce in SMEs in Singapore (Incoll-text-in-chap)}, +% booktitle = {booktitle E-commerce and cultural values}, +% title = {The title}, +% editor = {Thanasankit, Theerasak}, +% year = {2003}, +% isbn = {1-59140-056-2}, +% pages = {51--74}, +% numpages = {24}, +% url = {http://portal.acm.org/citation.cfm?id=887006.887010}, +% acmid = {887010}, +% publisher = {IGI Publishing}, +% address = {Hershey, PA, USA}, +%} + + +% --------- + + + + + +% Need inbook with num in chapter + +% and inbook with number in chapter +@InBook{Kong:2004:IEC:123456.887010, + author = {Kong, Wei-Chang}, + editor = {Theerasak Thanasankit}, + title = {E-commerce and cultural values - (InBook-num-in-chap)}, + chapter = {9}, + year = {2004}, + address = {Hershey, PA, USA}, + publisher = {IGI Publishing}, + OPTurl = {http://portal.acm.org/citation.cfm?id=887006.887010}, + pages = {51--74}, + numpages = {24}, + acmid = {887010}, + isbn = {1-59140-056-2}, + number = "", + type = "", + month = "", + note = "", +} + + +% and inbook with text in chapter +@Inbook{Kong:2005:IEC:887006.887010, + author = {Kong, Wei-Chang}, + editor = {Theerasak Thanasankit}, + title = {E-commerce and cultural values (Inbook-text-in-chap)}, + chapter = {The implementation of electronic commerce in SMEs in Singapore}, + year = {2005}, + address = {Hershey, PA, USA}, + publisher = {IGI Publishing}, + OPTurl = {http://portal.acm.org/citation.cfm?id=887006.887010}, + type = {Chapter:}, + pages = {51--74}, + numpages = {24}, + acmid = {887010}, + isbn = {1-59140-056-2}, + number = "", + month = "", + note = "", +} + + +% and inbook with a num and type field +@Inbook{Kong:2006:IEC:887006.887010, + author = {Kong, Wei-Chang}, + editor = {Theerasak Thanasankit}, + title = {E-commerce and cultural values (Inbook-num chap)}, + chapter = {22}, + year = {2006}, + address = {Hershey, PA, USA}, + publisher = {IGI Publishing}, + OPTurl = {http://portal.acm.org/citation.cfm?id=887006.887010}, + type = {Chapter (in type field)}, + pages = {51--74}, + numpages = {24}, + acmid = {887010}, + isbn = {1-59140-056-2}, + number = "", + month = "", + note = "", +} + + +% and incol coz we have a BLANK chapter - due to presence of editor +%atIncollection{Kong:2006:IEC:887006.887011, +% author = {Kong, Wei-Chang}, +% editor = {Theerasak Thanasankit}, +% title = "The title" +% booktitle = {E-commerce and cultural values (Incol-coz-blank-chap)}, +% year = {2006}, +% address = {Hershey, PA, USA}, +% publisher = {IGI Publishing}, +% url = {http://portal.acm.org/citation.cfm?id=887006.887010}, +% type = {Type!}, +% chapter = {}, +% pages = {51--74}, +% numpages = {24}, +% acmid = {887010}, +% isbn = {1-59140-056-2}, +% number = "", +% month = "", +% note = "", +%} + +@article{SaeediMEJ10, + author = {Mehdi Saeedi and Morteza Saheb Zamani and Mehdi Sedighi}, + title = {A library-based synthesis methodology for reversible logic}, + journal = {Microelectron. J.}, + volume = {41}, + number = {4}, + month = apr, + year = {2010}, + pages = {185--194}, +} + +@ARTICLE{SaeediJETC10, + author = {Mehdi Saeedi and Morteza Saheb Zamani and Mehdi Sedighi and Zahra Sasanian}, + title = {Synthesis of Reversible Circuit Using Cycle-Based Approach}, + journal = {J. Emerg. Technol. Comput. Syst.}, + volume = {6}, + number = {4}, + month = dec, + year = {2010} + } + +% Asad's new version +@article{Kirschmer:2010:AEI:1958016.1958018, + author = {Kirschmer, Markus and Voight, John}, + title = {Algorithmic Enumeration of Ideal Classes for Quaternion Orders}, + journal = {SIAM J. Comput.}, + issue_date = {January 2010}, + volume = {39}, + number = {5}, + month = jan, + year = {2010}, + issn = {0097-5397}, + pages = {1714--1747}, + numpages = {34}, + url = {http://dx.doi.org/10.1137/080734467}, + doi = {10.1137/080734467}, + acmid = {1958018}, + publisher = {Society for Industrial and Applied Mathematics}, + address = {Philadelphia, PA, USA}, + keywords = {ideal classes, maximal orders, number theory, quaternion algebras}, +} + +@inproceedings{10.1145/3194770.3194776, +author = {Verma, Sahil and Rubin, Julia}, +title = {Fairness Definitions Explained}, +year = {2018}, +isbn = {9781450357463}, +publisher = {Association for Computing Machinery}, +address = {New York, NY, USA}, +url = {https://doi.org/10.1145/3194770.3194776}, +doi = {10.1145/3194770.3194776}, +abstract = {Algorithm fairness has started to attract the attention of researchers in AI, Software Engineering and Law communities, with more than twenty different notions of fairness proposed in the last few years. Yet, there is no clear agreement on which definition to apply in each situation. Moreover, the detailed differences between multiple definitions are difficult to grasp. To address this issue, this paper collects the most prominent definitions of fairness for the algorithmic classification problem, explains the rationale behind these definitions, and demonstrates each of them on a single unifying case-study. Our analysis intuitively explains why the same case can be considered fair according to some definitions and unfair according to others.}, +booktitle = {Proceedings of the International Workshop on Software Fairness}, +pages = {1–7}, +numpages = {7}, +location = {Gothenburg, Sweden}, +series = {FairWare '18} +} + +@misc{chouldechova2018frontiers, + title={The Frontiers of Fairness in Machine Learning}, + author={Alexandra Chouldechova and Aaron Roth}, + year={2018}, + eprint={1810.08810}, + archivePrefix={arXiv}, + primaryClass={cs.LG} +} + +@online{fairness_catalogue, + author = {OECD.AI}, + title = {Catalogue of Tools and Metrics for Trustworthy AI}, + url = {https://oecd.ai/en/catalogue/metrics?objectiveIds=2&page=1 +} + +@article{Castelnovo_2022, + doi = {10.1038/s41598-022-07939-1}, +title = {The Zoo of Fairness Metrics in Machine Learning}, +author={Alessandro Castelnovo and Riccardo Crupi and Greta Greco and Daniele Regoli and Ilaria Giuseppina Penco and Andrea Claudio Cosentini}, + url = {https://doi.org/10.1038%2Fs41598-022-07939-1}, + + year = 2022, + month = {mar}, + + publisher = {Springer Science and Business Media {LLC} +} + +% incol due to presence of booktitle +@incollection{Hoare:1972:CIN:1243380.1243382, + author = {Hoare, C. A. R.}, + title = {Chapter II: Notes on data structuring}, + booktitle = {Structured programming (incoll)}, + editor = {Dahl, O. J. and Dijkstra, E. W. and Hoare, C. A. R.}, + year = {1972}, + isbn = {0-12-200550-3}, + pages = {83--174}, + numpages = {92}, + OPTurl = {http://portal.acm.org/citation.cfm?id=1243380.1243382}, + acmid = {1243382}, + publisher = {Academic Press Ltd.}, + address = {London, UK, UK}, +} + +% incol due to presence of booktitle +@incollection{Lee:1978:TQA:800025.1198348, + author = {Lee, Jan}, + title = {Transcript of question and answer session}, + booktitle = {History of programming languages I (incoll)}, + editor = {Wexelblat, Richard L.}, + year = {1981}, + isbn = {0-12-745040-8}, + pages = {68--71}, + numpages = {4}, + OPTurl = {http://doi.acm.org/10.1145/800025.1198348}, + doi = {10.1145/800025.1198348}, + acmid = {1198348}, + publisher = {ACM}, + address = {New York, NY, USA}, +} + +% incol due to booktitle +@incollection{Dijkstra:1979:GSC:1241515.1241518, + author = {Dijkstra, E.}, + title = {Go to statement considered harmful}, + booktitle = {Classics in software engineering (incoll)}, + year = {1979}, + isbn = {0-917072-14-6}, + pages = {27--33}, + numpages = {7}, + OPTurl = {http://portal.acm.org/citation.cfm?id=1241515.1241518}, + acmid = {1241518}, + publisher = {Yourdon Press}, + address = {Upper Saddle River, NJ, USA}, +} + +% incol due to booktitle +@incollection{Wenzel:1992:TVA:146022.146089, + author = {Wenzel, Elizabeth M.}, + title = {Three-dimensional virtual acoustic displays}, + booktitle = {Multimedia interface design (incoll)}, + year = {1992}, + isbn = {0-201-54981-6}, + pages = {257--288}, + numpages = {32}, + OPTurl = {http://portal.acm.org/citation.cfm?id=146022.146089}, + doi = {10.1145/146022.146089}, + acmid = {146089}, + publisher = {ACM}, + address = {New York, NY, USA}, +} + +% incol due to booktitle +@incollection{Mumford:1987:MES:54905.54911, + author = {Mumford, E.}, + title = {Managerial expert systems and organizational change: some critical research issues}, + booktitle = {Critical issues in information systems research (incoll)}, + year = {1987}, + isbn = {0-471-91281-6}, + pages = {135--155}, + numpages = {21}, + OPTurl = {http://portal.acm.org/citation.cfm?id=54905.54911}, + acmid = {54911}, + publisher = {John Wiley \& Sons, Inc.}, + address = {New York, NY, USA}, +} + +@book{McCracken:1990:SSC:575315, + author = {McCracken, Daniel D. and Golden, Donald G.}, + title = {Simplified Structured COBOL with Microsoft/MicroFocus COBOL}, + year = {1990}, + isbn = {0471514071}, + publisher = {John Wiley \& Sons, Inc.}, + address = {New York, NY, USA}, +} + +% Let's include Boris / BBeeton entries (multi-volume works) + +@book {MR781537, + AUTHOR = {H{\"o}rmander, Lars}, + TITLE = {The analysis of linear partial differential operators. {III}}, + SERIES = {Grundlehren der Mathematischen Wissenschaften [Fundamental + Principles of Mathematical Sciences]}, + VOLUME = {275}, + NOTE = {Pseudodifferential operators}, +PUBLISHER = {Springer-Verlag}, + ADDRESS = {Berlin, Germany}, + YEAR = {1985}, + PAGES = {viii+525}, + ISBN = {3-540-13828-5}, + MRCLASS = {35-02 (35Sxx 47G05 58G15)}, + MRNUMBER = {781536 (87d:35002a)}, +MRREVIEWER = {Min You Qi}, +} + +@book {MR781536, + AUTHOR = {H{\"o}rmander, Lars}, + TITLE = {The analysis of linear partial differential operators. {IV}}, + SERIES = {Grundlehren der Mathematischen Wissenschaften [Fundamental + Principles of Mathematical Sciences]}, + VOLUME = {275}, + NOTE = {Fourier integral operators}, +PUBLISHER = {Springer-Verlag}, + ADDRESS = {Berlin, Germany}, + YEAR = {1985}, + PAGES = {vii+352}, + ISBN = {3-540-13829-3}, + MRCLASS = {35-02 (35Sxx 47G05 58G15)}, + MRNUMBER = {781537 (87d:35002b)}, +MRREVIEWER = {Min You Qi}, +} + +%%%%%%%%%%%%%%%%%%%%%% Start of Aptara sample bib entries + +% acmsmall-sam.bib +@InProceedings{Adya-01, + author = {A. Adya and P. Bahl and J. Padhye and A.Wolman and L. Zhou}, + title = {A multi-radio unification protocol for {IEEE} 802.11 wireless networks}, + booktitle = {Proceedings of the IEEE 1st International Conference on Broadnets Networks (BroadNets'04)}, + publisher = "IEEE", + address = "Los Alamitos, CA", + year = {2004}, + pages = "210--217" +} + +@article{Akyildiz-01, + author = {I. F. Akyildiz and W. Su and Y. Sankarasubramaniam and E. Cayirci}, + title = {Wireless Sensor Networks: A Survey}, + journal = {Comm. ACM}, + volume = 38, + number = "4", + year = {2002}, + pages = "393--422" +} + +@article{Akyildiz-02, + author = {I. F. Akyildiz and T. Melodia and K. R. Chowdhury}, + title = {A Survey on Wireless Multimedia Sensor Networks}, + journal = {Computer Netw.}, + volume = 51, + number = "4", + year = {2007}, + pages = "921--960" +} + +@InProceedings{Bahl-02, + author = {P. Bahl and R. Chancre and J. Dungeon}, + title = {{SSCH}: Slotted Seeded Channel Hopping for Capacity Improvement in {IEEE} 802.11 Ad-Hoc Wireless Networks}, + booktitle = {Proceeding of the 10th International Conference on Mobile Computing and Networking (MobiCom'04)}, + publisher = "ACM", + address = "New York, NY", + year = {2004}, + pages = "112--117" +} + +@misc{CROSSBOW, + key = {CROSSBOW}, + title = {{XBOW} Sensor Motes Specifications}, + note = {http://www.xbow.com}, + year = 2008 +} + +@article{Culler-01, + author = {D. Culler and D. Estrin and M. Srivastava}, + title = {Overview of Sensor Networks}, + journal = {IEEE Comput.}, + volume = 37, + number = "8 (Special Issue on Sensor Networks)", + publisher = "IEEE", + address = "Los Alamitos, CA", + year = {2004}, + pages = "41--49" +} + +@misc{Harvard-01, + key = {Harvard CodeBlue}, + title = {{CodeBlue}: Sensor Networks for Medical Care}, + note = {http://www.eecs.harvard.edu/mdw/ proj/codeblue/}, + year = 2008 +} + +@InProceedings{Natarajan-01, + author = {A. Natarajan and M. Motani and B. de Silva and K. Yap and K. C. Chua}, + title = {Investigating Network Architectures for Body Sensor Networks}, + booktitle = {Network Architectures}, + editor = {G. Whitcomb and P. Neece}, + publisher = "Keleuven Press", + address = "Dayton, OH", + year = {2007}, + pages = "322--328", + eprint = "960935712", + primaryclass = "cs", +} + +@techreport{Tzamaloukas-01, + author = {A. Tzamaloukas and J. J. Garcia-Luna-Aceves}, + title = {Channel-Hopping Multiple Access}, + number = {I-CA2301}, + institution = {Department of Computer Science, University of California}, + address = {Berkeley, CA}, + year = {2000} +} + +@BOOK{Zhou-06, + author = {G. Zhou and J. Lu and C.-Y. Wan and M. D. Yarvis and J. A. Stankovic}, + title = {Body Sensor Networks}, + publisher = "MIT Press", + address = "Cambridge, MA", + year = {2008} +} + +@mastersthesis{ko94, +author = "Jacob Kornerup", +title = "Mapping Powerlists onto Hypercubes", +school = "The University of Texas at Austin", +note = "(In preparation)", +year = "1994"} +%month = "dec",} + +@PhdThesis{gerndt:89, + author = "Michael Gerndt", + title = "Automatic Parallelization for Distributed-Memory + Multiprocessing Systems", + school = "University of Bonn", + year = 1989, + address = "Bonn, Germany", + month = dec +} + +@article{6:1:1, +author = "J. E. {Archer, Jr.} and R. Conway and F. B. Schneider", +title = "User recovery and reversal in interactive systems", +journal = "ACM Trans. Program. Lang. Syst.", +volume = "6", +number = "1", +month = jan, +year = 1984, +pages = "1--19"} + +@article{7:1:137, +author = "D. D. Dunlop and V. R. Basili", +title = "Generalizing specifications for uniformly implemented loops", +journal = "ACM Trans. Program. Lang. Syst.", +volume = "7", +number = "1", +month = jan, +year = 1985, +pages = "137--158"} + +@article{7:2:183, +author = "J. Heering and P. Klint", +title = "Towards monolingual programming environments", +journal = "ACM Trans. Program. Lang. Syst.", +volume = "7", +number = "2", +month = apr, +year = 1985, +pages = "183--213"} + +@book{knuth:texbook, +author = "Donald E. Knuth", +title = "The {\TeX{}book}", +publisher = "Addison-Wesley", +address = "Reading, MA.", +year = 1984} + +@article{6:3:380, +author = "E. Korach and D. Rotem and N. Santoro", +title = "Distributed algorithms for finding centers and medians in networks", +journal = "ACM Trans. Program. Lang. Syst.", +volume = "6", +number = "3", +month = jul, +year = 1984, +pages = "380--401"} + +@book{lamport:latex, +author = "Leslie Lamport", +title = "{\LaTeX}: A Document Preparation System", +publisher = "Addison-Wesley", +address = "Reading, MA.", +year = 1986} + +@article{7:3:359, +author = "F. Nielson", +title = "Program transformations in a denotational setting", +journal = "ACM Trans. Program. Lang. Syst.", +volume = "7", +number = "3", +month = jul, +year = 1985, +pages = "359--379"} + +%testing +@BOOK{test, + author = "Donald E. Knuth", + title = "Seminumerical Algorithms", + volume = 2, + series = "The Art of Computer Programming", + publisher = "Addison-Wesley", + address = "Reading, MA", + edition = "2nd", + month = "10~" # jan, + year = "1981", +} + +@article{dkl, +author = {S. Kullback and R. A. Leibler}, +title = {{On Information and Sufficiency}}, +volume = {22}, +journal = {The Annals of Mathematical Statistics}, +number = {1}, +publisher = {Institute of Mathematical Statistics}, +pages = {79 -- 86}, +year = {1951}, +doi = {10.1214/aoms/1177729694}, +URL = {https://doi.org/10.1214/aoms/1177729694} +} + + +@inproceedings{reid:scribe, +author = "Brian K. Reid", +title = "A high-level approach to computer document formatting", +booktitle = "Proceedings of the 7th Annual Symposium on Principles of + Programming Languages", +month = jan, +year = 1980, +publisher = "ACM", +address = "New York", +pages = "24--31"} + +@article{Zhou:2010:MMS:1721695.1721705, + author = {Zhou, Gang and Wu, Yafeng and Yan, Ting and He, Tian and Huang, Chengdu and Stankovic, John A. and Abdelzaher, Tarek F.}, + title = {A multifrequency MAC specially designed for wireless sensor network applications}, + journal = {ACM Trans. Embed. Comput. Syst.}, + issue_date = {March 2010}, + volume = 9, + number = 4, + month = {April}, + year = 2010, + issn = {1539-9087}, + pages = {39:1--39:41}, + articleno = 39, + numpages = 41, + OPTurl = {http://doi.acm.org/10.1145/1721695.1721705}, + doi = {10.1145/1721695.1721705}, + acmid = 1721705, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {Wireless sensor networks, media access control, multi-channel, radio interference, time synchronization}, +} + + +@misc{TUGInstmem, + key = {TUG}, + year = 2017, + title = "Institutional members of the {\TeX} Users Group", + url = "http://www.tug.org/instmem.html", + lastaccessed = "May 27, 2017", +} + +@ARTICLE{bowman:reasoning, + author = {Bowman, Mic and Debray, Saumya K. and Peterson, Larry L.}, + title = {Reasoning About Naming Systems}, + journal = {ACM Trans. Program. Lang. Syst.}, + volume = {15}, + number = {5}, + pages = {795-825}, + month = {November}, + year = {1993}, + doi = {10.1145/161468.161471}, +} + +@ARTICLE{braams:babel, + author = {Braams, Johannes}, + title = {Babel, a Multilingual Style-Option System for Use with LaTeX's Standard Document Styles}, + journal = {TUGboat}, + volume = {12}, + number = {2}, + pages = {291-301}, + month = {June}, + year = {1991}, +} + +@INPROCEEDINGS{clark:pct, + AUTHOR = "Malcolm Clark", + TITLE = "Post Congress Tristesse", + BOOKTITLE = "TeX90 Conference Proceedings", + PAGES = "84-89", + ORGANIZATION = "TeX Users Group", + MONTH = "March", + YEAR = {1991} +} + +@ARTICLE{herlihy:methodology, + author = {Herlihy, Maurice}, + title = {A Methodology for Implementing Highly Concurrent Data Objects}, + journal = {ACM Trans. Program. Lang. Syst.}, + volume = {15}, + number = {5}, + pages = {745-770}, + month = {November}, + year = {1993}, + doi = {10.1145/161468.161469}, +} + +@BOOK{salas:calculus, + AUTHOR = "S.L. Salas and Einar Hille", + TITLE = "Calculus: One and Several Variable", + PUBLISHER = "John Wiley and Sons", + ADDRESS = "New York", + YEAR = "1978" +} + +@MANUAL{Fear05, + title = {Publication quality tables in {\LaTeX}}, + author = {Simon Fear}, + month = {April}, + year = 2005, + note = {\url{http://www.ctan.org/pkg/booktabs}} +} + +@Manual{Amsthm15, + title = {Using the amsthm Package}, + organization = {American Mathematical Society}, + month = {April}, + year = 2015, + note = {\url{http://www.ctan.org/pkg/amsthm}} +} + +@misc{R, + title = {R: A Language and Environment for Statistical Computing}, + author = {{R Core Team}}, + organization = {R Foundation for Statistical Computing}, + address = {Vienna, Austria}, + year = {2019}, + url = {https://www.R-project.org/}, +} + +@misc{UMassCitations, + author = {Sam Anzaroot and Andrew McCallum}, + title = {{UMass} Citation Field Extraction Dataset}, + year = 2013, + url = + {http://www.iesl.cs.umass.edu/data/data-umasscitationfield}, + lastaccessed = {May 27, 2019} +} diff --git a/tests/unit/TestBiasDetector.py b/tests/unit/TestBiasDetector.py index 56318b5..3b73142 100644 --- a/tests/unit/TestBiasDetector.py +++ b/tests/unit/TestBiasDetector.py @@ -1,6 +1,6 @@ import unittest import sys -from pickle import load +from pickle import load, dump from sklearn.model_selection import train_test_split import pandas as pd import numpy as np @@ -68,9 +68,14 @@ def test_compare_root_variable_groups_with_TVD(self): target_variable='predictions', root_variable='x2_sex', threshold=0.1) + + # Saving results for Risk tests + with open("./tests/unit/test_data/results_test_compare_root_variable_groups_with_TVD.pkl", "wb") as file: + dump(results, file) self.assertEqual(results[0], 0.025269625352224545) + def test_compare_root_variable_groups_with_JS(self): ''' Test the compare_root_variable_groups method against a @@ -85,6 +90,10 @@ def test_compare_root_variable_groups_with_JS(self): target_variable='predictions', root_variable='x2_sex', threshold=0.1) + + # Saving results for Risk tests + with open("./tests/unit/test_data/results_test_compare_root_variable_groups_with_JS.pkl", "wb") as file: + dump(results, file) self.assertEqual(results[0], 0.0011441803173238346) @@ -120,6 +129,11 @@ def test_compare_root_variable_groups_with_KL_and_ref_distribution(self): root_variable='x2_sex', threshold=0.1, reference_distribution=self.ref) + + # Saving results for Risk tests + with open("./tests/unit/test_data/results_test_compare_root_variable_groups_with_KL_and_ref_distribution.pkl", "wb") as file: + dump(results, file) + self.assertEqual(results[0], [0.07485260878313427, 0.11543085607355452]) def test_compare_root_variable_groups_with_KL_and_ref_distribution_probs(self): @@ -160,6 +174,10 @@ def test_compare_root_variable_conditioned_groups_with_TVD(self): ['x3_education', 'x4_marriage'], 0.1, min_obs_per_group=30) + + # Saving results for Risk tests + with open("./tests/unit/test_data/results_test_compare_root_variable_conditioned_groups_with_TVD.pkl", "wb") as file: + dump(results, file) violations = {k: v for k, v in results.items() if not v[2]} @@ -229,6 +247,10 @@ def test_compare_root_variable_conditioned_groups_with_KL_and_ref_distribution(s reference_distribution=self.ref, min_obs_per_group=30, threshold=0.1) + + # Saving results for Risk tests + with open("./tests/unit/test_data/results_test_compare_root_variable_conditioned_groups_with_KL_and_ref_distribution.pkl", "wb") as file: + dump(results, file) violations = {k: v for k, v in results.items() if (not v[2][0] or not v[2][1])} self.assertEqual(len(violations), 9) diff --git a/tests/unit/TestRiskCalculator.py b/tests/unit/TestRiskCalculator.py new file mode 100644 index 0000000..5f628d1 --- /dev/null +++ b/tests/unit/TestRiskCalculator.py @@ -0,0 +1,58 @@ +import unittest +from pickle import load +from sklearn.model_selection import train_test_split + +from brio.utils.Preprocessing import Preprocessing +from brio.risk.RiskCalculator import RiskCalculator +from brio.risk.HazardFromBiasDetectionCalculator import HazardFromBiasDetectionCalculator + +class TestRiskCalculator(unittest.TestCase): + + def setUp(self): + input_data_path = "./tests/unit/test_data/data.csv" + pp = Preprocessing(input_data_path, "default") + X, Y = pp.read_dataframe() + X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=420) + self.n_obs = X_test.shape[0] + self.conditioning_variables = ['x3_education', 'x4_marriage'] + + #### Import FreqVsRef results #### + with open("./tests/unit/test_data/results_test_compare_root_variable_conditioned_groups_with_KL_and_ref_distribution.pkl", "rb") as file: + self.results_ref_conditioned = load(file) + + with open("./tests/unit/test_data/results_test_compare_root_variable_groups_with_KL_and_ref_distribution.pkl", "rb") as file: + self.results_ref_overall = load(file) + + #### Import FreqVsFreq results #### + with open("./tests/unit/test_data/results_test_compare_root_variable_groups_with_TVD.pkl", "rb") as file: + self.results_freq_overall = load(file) + + with open("./tests/unit/test_data/results_test_compare_root_variable_conditioned_groups_with_TVD.pkl", "rb") as file: + self.results_freq_conditioned = load(file) + + + def test_risk_calculator(self): + ''' + Test the risk_calculator method, using a set of FreqVsFreq and + FreqVsRef results. The overall risk measure is a combination + coming from all the input results. + ''' + hc = HazardFromBiasDetectionCalculator() + + hazard_ref = hc.compute_hazard_from_freqvsfreq_or_freqvsref(self.results_ref_overall, + self.results_ref_conditioned, + self.n_obs, + self.conditioning_variables) + + hazard_freq = hc.compute_hazard_from_freqvsfreq_or_freqvsref(self.results_freq_overall, + self.results_freq_conditioned, + self.n_obs, + self.conditioning_variables) + + rc = RiskCalculator() + risk = rc.compute_risk(test_hazards=[hazard_ref, hazard_freq]) + + self.assertAlmostEqual(risk, 0.018531866342260846, delta=1e-8) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/unit/test_data/results_test_compare_root_variable_conditioned_groups_with_KL_and_ref_distribution.pkl b/tests/unit/test_data/results_test_compare_root_variable_conditioned_groups_with_KL_and_ref_distribution.pkl new file mode 100644 index 0000000..8b882a2 Binary files /dev/null and b/tests/unit/test_data/results_test_compare_root_variable_conditioned_groups_with_KL_and_ref_distribution.pkl differ diff --git a/tests/unit/test_data/results_test_compare_root_variable_conditioned_groups_with_TVD.pkl b/tests/unit/test_data/results_test_compare_root_variable_conditioned_groups_with_TVD.pkl new file mode 100644 index 0000000..6c65ee0 Binary files /dev/null and b/tests/unit/test_data/results_test_compare_root_variable_conditioned_groups_with_TVD.pkl differ diff --git a/tests/unit/test_data/results_test_compare_root_variable_groups_with_JS.pkl b/tests/unit/test_data/results_test_compare_root_variable_groups_with_JS.pkl new file mode 100644 index 0000000..c13f165 Binary files /dev/null and b/tests/unit/test_data/results_test_compare_root_variable_groups_with_JS.pkl differ diff --git a/tests/unit/test_data/results_test_compare_root_variable_groups_with_KL_and_ref_distribution.pkl b/tests/unit/test_data/results_test_compare_root_variable_groups_with_KL_and_ref_distribution.pkl new file mode 100644 index 0000000..ae08413 Binary files /dev/null and b/tests/unit/test_data/results_test_compare_root_variable_groups_with_KL_and_ref_distribution.pkl differ diff --git a/tests/unit/test_data/results_test_compare_root_variable_groups_with_TVD.pkl b/tests/unit/test_data/results_test_compare_root_variable_groups_with_TVD.pkl new file mode 100644 index 0000000..78c4b06 Binary files /dev/null and b/tests/unit/test_data/results_test_compare_root_variable_groups_with_TVD.pkl differ