def test_multiclass_confusion_matrix(): data = np.array([[0, 1], [0, 0], [1, 0], [1, 1], [1, 0], [1, 2], [2, 1], [2, 0], [2, 2], [2, 1]]) pred = data.copy() pred[3, 1] = 0 pred[4, 1] = 2 df = pd.DataFrame(data, columns=['feat', 'label']) df2 = pd.DataFrame(pred, columns=['feat', 'label']) favorable_values = [0, 1] unfavorable_values = [2] mcld = MulticlassLabelDataset(favorable_label=favorable_values, unfavorable_label=unfavorable_values, df=df, label_names=['label'], protected_attribute_names=['feat']) mcld2 = MulticlassLabelDataset(favorable_label=favorable_values, unfavorable_label=unfavorable_values, df=df2, label_names=['label'], protected_attribute_names=['feat']) cm = ClassificationMetric(mcld, mcld2, unprivileged_groups=[{ 'feat': 2 }], privileged_groups=[{ 'feat': 0 }, { 'feat': 1 }]) confusion_matrix = cm.binary_confusion_matrix() actual_labels_df = df[['label']].values actual_labels_df2 = df2[['label']].values assert np.all(actual_labels_df == mcld.labels) assert np.all(actual_labels_df2 == mcld2.labels) assert confusion_matrix == {'TP': 7.0, 'FN': 1.0, 'TN': 2.0, 'FP': 0.0} fnr = cm.false_negative_rate_difference() assert fnr == -0.2
def fairness_check(object_storage_url, object_storage_username, object_storage_password, data_bucket_name, result_bucket_name, model_id, feature_testset_path='processed_data/X_test.npy', label_testset_path='processed_data/y_test.npy', protected_label_testset_path='processed_data/p_test.npy', model_class_file='model.py', model_class_name='model', favorable_label=0.0, unfavorable_label=1.0, privileged_groups=[{ 'race': 0.0 }], unprivileged_groups=[{ 'race': 4.0 }]): url = re.compile(r"https?://") cos = Minio(url.sub('', object_storage_url), access_key=object_storage_username, secret_key=object_storage_password, secure=False) # Local Minio server won't have HTTPS dataset_filenamex = "X_test.npy" dataset_filenamey = "y_test.npy" dataset_filenamep = "p_test.npy" weights_filename = "model.pt" model_files = model_id + '/_submitted_code/model.zip' cos.fget_object(data_bucket_name, feature_testset_path, dataset_filenamex) cos.fget_object(data_bucket_name, label_testset_path, dataset_filenamey) cos.fget_object(data_bucket_name, protected_label_testset_path, dataset_filenamep) cos.fget_object(result_bucket_name, model_id + '/' + weights_filename, weights_filename) cos.fget_object(result_bucket_name, model_files, 'model.zip') # Load PyTorch model definition from the source code. zip_ref = zipfile.ZipFile('model.zip', 'r') zip_ref.extractall('model_files') zip_ref.close() modulename = 'model_files.' + model_class_file.split('.')[0].replace( '-', '_') ''' We required users to define where the model class is located or follow some naming convention we have provided. ''' model_class = getattr(importlib.import_module(modulename), model_class_name) # load & compile model device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') model = model_class().to(device) model.load_state_dict(torch.load(weights_filename, map_location=device)) """Load the necessary labels and protected features for fairness check""" x_test = np.load(dataset_filenamex) y_test = np.load(dataset_filenamey) p_test = np.load(dataset_filenamep) _, y_pred = evaluate(model, x_test, y_test) """Calculate the fairness metrics""" original_test_dataset = dataset_wrapper( outcome=y_test, protected=p_test, unprivileged_groups=unprivileged_groups, privileged_groups=privileged_groups, favorable_label=favorable_label, unfavorable_label=unfavorable_label) plain_predictions_test_dataset = dataset_wrapper( outcome=y_pred, protected=p_test, unprivileged_groups=unprivileged_groups, privileged_groups=privileged_groups, favorable_label=favorable_label, unfavorable_label=unfavorable_label) classified_metric_nodebiasing_test = ClassificationMetric( original_test_dataset, plain_predictions_test_dataset, unprivileged_groups=unprivileged_groups, privileged_groups=privileged_groups) TPR = classified_metric_nodebiasing_test.true_positive_rate() TNR = classified_metric_nodebiasing_test.true_negative_rate() bal_acc_nodebiasing_test = 0.5 * (TPR + TNR) print( "#### Plain model - without debiasing - classification metrics on test set" ) metrics = { "Classification accuracy": classified_metric_nodebiasing_test.accuracy(), "Balanced classification accuracy": bal_acc_nodebiasing_test, "Statistical parity difference": classified_metric_nodebiasing_test.statistical_parity_difference(), "Disparate impact": classified_metric_nodebiasing_test.disparate_impact(), "Equal opportunity difference": classified_metric_nodebiasing_test.equal_opportunity_difference(), "Average odds difference": classified_metric_nodebiasing_test.average_odds_difference(), "Theil index": classified_metric_nodebiasing_test.theil_index(), "False negative rate difference": classified_metric_nodebiasing_test.false_negative_rate_difference() } print("metrics: ", metrics) return metrics
ClassificationMetric( dataset_ground_truth, dataset_classifier, unprivileged_groups=unprivileged_groups, privileged_groups=privileged_groups) TPR = classificaltion_metric.true_positive_rate() TNR = classificaltion_metric.true_negative_rate() bal_acc_nodebiasing_test = 0.5 * (TPR + TNR) metrics = { "classification_accuracy": classificaltion_metric.accuracy(), "balanced_classification_accuracy": bal_acc_nodebiasing_test, "statistical_parity_difference": classificaltion_metric.statistical_parity_difference(), "disparate_impact": classificaltion_metric.disparate_impact(), "equal_opportunity_difference": classificaltion_metric.equal_opportunity_difference(), "average_odds_difference": classificaltion_metric.average_odds_difference(), "theil_index": classificaltion_metric.theil_index(), "false_negative_rate_difference": classificaltion_metric.false_negative_rate_difference() } sys.stdout.write(json.dumps(metrics))
"#### Plain model - without debiasing - classification metrics on test set" ) # print("Test set: Classification accuracy = %f" % classified_metric_nodebiasing_test.accuracy()) # print("Test set: Balanced classification accuracy = %f" % bal_acc_nodebiasing_test) # print("Test set: Statistical parity difference = %f" % classified_metric_nodebiasing_test.statistical_parity_difference()) # print("Test set: Disparate impact = %f" % classified_metric_nodebiasing_test.disparate_impact()) # print("Test set: Equal opportunity difference = %f" % classified_metric_nodebiasing_test.equal_opportunity_difference()) # print("Test set: Average odds difference = %f" % classified_metric_nodebiasing_test.average_odds_difference()) # print("Test set: Theil index = %f" % classified_metric_nodebiasing_test.theil_index()) # print("Test set: False negative rate difference = %f" % classified_metric_nodebiasing_test.false_negative_rate_difference()) metrics = { "Classification accuracy": classified_metric_nodebiasing_test.accuracy(), "Balanced classification accuracy": bal_acc_nodebiasing_test, "Statistical parity difference": classified_metric_nodebiasing_test.statistical_parity_difference(), "Disparate impact": classified_metric_nodebiasing_test.disparate_impact(), "Equal opportunity difference": classified_metric_nodebiasing_test.equal_opportunity_difference(), "Average odds difference": classified_metric_nodebiasing_test.average_odds_difference(), "Theil index": classified_metric_nodebiasing_test.theil_index(), "False negative rate difference": classified_metric_nodebiasing_test.false_negative_rate_difference() } print("metrics: ", metrics)
def fairness_check(s3_url, bucket_name, s3_username, s3_password, training_id): cos = boto3.resource("s3", endpoint_url=s3_url, aws_access_key_id=s3_username, aws_secret_access_key=s3_password) y_test_out = 'y_test.out' p_test_out = 'p_test.out' y_pred_out = 'y_pred.out' get_s3_item(cos, bucket_name, training_id + '/' + y_test_out, y_test_out) get_s3_item(cos, bucket_name, training_id + '/' + p_test_out, p_test_out) get_s3_item(cos, bucket_name, training_id + '/' + y_pred_out, y_pred_out) """Need to generalize the protected features""" unprivileged_groups = [{'race': 4.0}] privileged_groups = [{'race': 0.0}] favorable_label = 0.0 unfavorable_label = 1.0 """Load the necessary labels and protected features for fairness check""" y_test = np.loadtxt(y_test_out) p_test = np.loadtxt(p_test_out) y_pred = np.loadtxt(y_pred_out) """Calculate the fairness metrics""" original_test_dataset = dataset_wrapper(outcome=y_test, protected=p_test, unprivileged_groups=unprivileged_groups, privileged_groups=privileged_groups, favorable_label=favorable_label, unfavorable_label=unfavorable_label) plain_predictions_test_dataset = dataset_wrapper(outcome=y_pred, protected=p_test, unprivileged_groups=unprivileged_groups, privileged_groups=privileged_groups, favorable_label=favorable_label, unfavorable_label=unfavorable_label) classified_metric_nodebiasing_test = ClassificationMetric(original_test_dataset, plain_predictions_test_dataset, unprivileged_groups=unprivileged_groups, privileged_groups=privileged_groups) TPR = classified_metric_nodebiasing_test.true_positive_rate() TNR = classified_metric_nodebiasing_test.true_negative_rate() bal_acc_nodebiasing_test = 0.5*(TPR+TNR) print("#### Plain model - without debiasing - classification metrics on test set") metrics = { "Classification accuracy": classified_metric_nodebiasing_test.accuracy(), "Balanced classification accuracy": bal_acc_nodebiasing_test, "Statistical parity difference": classified_metric_nodebiasing_test.statistical_parity_difference(), "Disparate impact": classified_metric_nodebiasing_test.disparate_impact(), "Equal opportunity difference": classified_metric_nodebiasing_test.equal_opportunity_difference(), "Average odds difference": classified_metric_nodebiasing_test.average_odds_difference(), "Theil index": classified_metric_nodebiasing_test.theil_index(), "False negative rate difference": classified_metric_nodebiasing_test.false_negative_rate_difference() } print("metrics: ", metrics) return metrics
def fairness_check(label_dir, model_dir): """Need to generalize the protected features""" # races_to_consider = [0,4] unprivileged_groups = [{'race': 4.0}] privileged_groups = [{'race': 0.0}] favorable_label = 0.0 unfavorable_label = 1.0 """Load the necessary labels and protected features for fairness check""" # y_train = np.loadtxt(label_dir + '/y_train.out') # p_train = np.loadtxt(label_dir + '/p_train.out') y_test = np.loadtxt(label_dir + '/y_test.out') p_test = np.loadtxt(label_dir + '/p_test.out') y_pred = np.loadtxt(label_dir + '/y_pred.out') """Calculate the fairness metrics""" # original_traning_dataset = dataset_wrapper(outcome=y_train, protected=p_train, # unprivileged_groups=unprivileged_groups, # privileged_groups=privileged_groups, # favorable_label=favorable_label, # unfavorable_label=unfavorable_label) original_test_dataset = dataset_wrapper(outcome=y_test, protected=p_test, unprivileged_groups=unprivileged_groups, privileged_groups=privileged_groups, favorable_label=favorable_label, unfavorable_label=unfavorable_label) plain_predictions_test_dataset = dataset_wrapper(outcome=y_pred, protected=p_test, unprivileged_groups=unprivileged_groups, privileged_groups=privileged_groups, favorable_label=favorable_label, unfavorable_label=unfavorable_label) classified_metric_nodebiasing_test = ClassificationMetric(original_test_dataset, plain_predictions_test_dataset, unprivileged_groups=unprivileged_groups, privileged_groups=privileged_groups) TPR = classified_metric_nodebiasing_test.true_positive_rate() TNR = classified_metric_nodebiasing_test.true_negative_rate() bal_acc_nodebiasing_test = 0.5*(TPR+TNR) print("#### Plain model - without debiasing - classification metrics on test set") # print("Test set: Classification accuracy = %f" % classified_metric_nodebiasing_test.accuracy()) # print("Test set: Balanced classification accuracy = %f" % bal_acc_nodebiasing_test) # print("Test set: Statistical parity difference = %f" % classified_metric_nodebiasing_test.statistical_parity_difference()) # print("Test set: Disparate impact = %f" % classified_metric_nodebiasing_test.disparate_impact()) # print("Test set: Equal opportunity difference = %f" % classified_metric_nodebiasing_test.equal_opportunity_difference()) # print("Test set: Average odds difference = %f" % classified_metric_nodebiasing_test.average_odds_difference()) # print("Test set: Theil index = %f" % classified_metric_nodebiasing_test.theil_index()) # print("Test set: False negative rate difference = %f" % classified_metric_nodebiasing_test.false_negative_rate_difference()) metrics = { "Classification accuracy": classified_metric_nodebiasing_test.accuracy(), "Balanced classification accuracy": bal_acc_nodebiasing_test, "Statistical parity difference": classified_metric_nodebiasing_test.statistical_parity_difference(), "Disparate impact": classified_metric_nodebiasing_test.disparate_impact(), "Equal opportunity difference": classified_metric_nodebiasing_test.equal_opportunity_difference(), "Average odds difference": classified_metric_nodebiasing_test.average_odds_difference(), "Theil index": classified_metric_nodebiasing_test.theil_index(), "False negative rate difference": classified_metric_nodebiasing_test.false_negative_rate_difference() } return {"metrics": metrics}