#!/usr/bin/env python
# coding: utf-8

import sys
sys.path.append('../utils/')
# sys.path.insert(1, '../utils/')
from packages import *
from ml_fairness import *

import csv
from pathlib import Path
dir = 'home/res/model6/'
Path(dir).mkdir(parents=True, exist_ok=True)
f_count = len([name for name in os.listdir(dir) if os.path.isfile(os.path.join(dir, name)) and not name.startswith('.')])

fields = ['Acc', 'F1', 'DI','SPD', 'EOD', 'AOD', 'ERD', 'CNT', 'TI']
filename = dir + str(f_count+1) + '.csv'
with open(filename, 'a') as csvfile:
    csvwriter = csv.writer(csvfile)
    csvwriter.writerow(fields)

def fair_metrics(dataset, pred, pred_is_dataset=False):
    if pred_is_dataset:
        dataset_pred = pred
    else:
        dataset_pred = dataset.copy()
        dataset_pred.labels = pred

    cols = ['Accuracy', 'F1', 'DI','SPD', 'EOD', 'AOD', 'ERD', 'CNT', 'TI']
    obj_fairness = [[1,1,1,0,0,0,0,1,0]]

    fair_metrics = pd.DataFrame(data=obj_fairness, index=['objective'], columns=cols)

    for attr in dataset_pred.protected_attribute_names:
        idx = dataset_pred.protected_attribute_names.index(attr)

        classified_metric = ClassificationMetric(dataset,
                                                     dataset_pred,
                                                     unprivileged_groups=unprivileged_groups,
                                                     privileged_groups=privileged_groups)

        metric_pred = BinaryLabelDatasetMetric(dataset_pred,
                                                     unprivileged_groups=unprivileged_groups,
                                                     privileged_groups=privileged_groups)

        distortion_metric = SampleDistortionMetric(dataset,
                                                     dataset_pred,
                                                     unprivileged_groups=unprivileged_groups,
                                                     privileged_groups=privileged_groups)

        acc = classified_metric.accuracy()
        f1_sc = 2 * (classified_metric.precision() * classified_metric.recall()) / (classified_metric.precision() + classified_metric.recall())

        mt = [acc, f1_sc,
                        classified_metric.disparate_impact(),
                        classified_metric.mean_difference(),
                        classified_metric.equal_opportunity_difference(),
                        classified_metric.average_odds_difference(),
                        classified_metric.error_rate_difference(),
                        metric_pred.consistency(),
                        classified_metric.theil_index()
                    ]
        w_row = []
        for i in mt:
            print("%.8f"%i)
            w_row.append("%.8f"%i)
        with open(filename, 'a') as csvfile:
            csvwriter = csv.writer(csvfile)
            csvwriter.writerow(w_row)
        row = pd.DataFrame([mt],
                           columns  = cols,
                           index = [attr]
                          )
        fair_metrics = fair_metrics.append(row)

    fair_metrics = fair_metrics.replace([-np.inf, np.inf], 2)
    return fair_metrics

def get_fair_metrics_and_plot(data, model, plot=False, model_aif=False):
    pred = model.predict(data).labels if model_aif else model.predict(data.features)
    fair = fair_metrics(data, pred)

    if plot:
        pass

    return fair


def get_model_performance(X_test, y_true, y_pred, probs):
    accuracy = accuracy_score(y_true, y_pred)
    matrix = confusion_matrix(y_true, y_pred)
    f1 = f1_score(y_true, y_pred)
    return accuracy, matrix, f1

def plot_model_performance(model, X_test, y_true):
    y_pred = model.predict(X_test)
    probs = model.predict_proba(X_test)
    accuracy, matrix, f1 = get_model_performance(X_test, y_true, y_pred, probs)


algo_metrics = pd.DataFrame(columns=['model', 'fair_metrics', 'prediction', 'probs'])

def add_to_df_algo_metrics(algo_metrics, model, fair_metrics, preds, probs, name):
    return algo_metrics.append(pd.DataFrame(data=[[model, fair_metrics, preds, probs]], columns=['model', 'fair_metrics', 'prediction', 'probs'], index=[name]))

def custom_preprocessing(df):
        def group_race(x):
            if x == "White":
                return 1.0
            else:
                return 0.0
        # Recode sex and race
        df['sex'] = df['sex'].replace({'Female': 0.0, 'Male': 1.0})
        df['race'] = df['race'].apply(lambda x: group_race(x))

        return df

import gc
import time
from contextlib import contextmanager
from lightgbm import LGBMClassifier

@contextmanager
def timer(title):
    t0 = time.time()
    yield
    print("{} - done in {:.0f}s".format(title, time.time() - t0))

def one_hot_encoder(df, nan_as_category = True):
    original_columns = list(df.columns)
    categorical_columns = [col for col in df.columns if df[col].dtype == 'object']
    df = pd.get_dummies(df, columns= categorical_columns, dummy_na= nan_as_category)
    new_columns = [c for c in df.columns if c not in original_columns]
    return df, new_columns


from sklearn.preprocessing import MinMaxScaler
from sklearn.impute import SimpleImputer
train_control = pd.read_csv('../../dataset/home-data/application_train.csv')

features = train_control

train_ids = features['SK_ID_CURR']

labels = features['TARGET']

# Remove the ids and target
features = features.drop(columns = ['SK_ID_CURR']) #, 'TARGET'

le = LabelEncoder()
le_count = 0
for col in features:
    if features[col].dtype == 'object':
        # If 2 or fewer unique categories
        if len(list(features[col].unique())) <= 2 or col == 'CODE_GENDER':
            # Train on the training data
            le.fit(features[col])
            # Transform both training and testing data
            features[col] = le.transform(features[col])
            # Keep track of how many columns were label encoded
            le_count += 1

features = pd.get_dummies(features)

# No categorical indices to record
cat_indices = 'auto'

# Extract feature names
feature_names = list(features.columns)

col = list(features.columns.values)
# Convert to np arrays
features = np.array(features)
imputer = SimpleImputer(strategy = 'median')
# Scale each feature to 0-1
scaler = MinMaxScaler(feature_range = (0, 1))
# Fit on the training data
imputer.fit(features)
# Transform both training and testing data
features = imputer.transform(features)
features = pd.DataFrame(features, columns=col)

dataset_orig = StandardDataset(features,
                               label_name='TARGET',
                               favorable_classes=[1],
                               protected_attribute_names=['CODE_GENDER'],
                               privileged_classes=[[0]])

privileged_groups = [{'CODE_GENDER': 0}]
unprivileged_groups = [{'CODE_GENDER': 1}]

data_orig_train, data_orig_test = dataset_orig.split([0.7], shuffle=True)

X_train = data_orig_train.features
y_train = data_orig_train.labels.ravel()

X_test = data_orig_test.features
y_test = data_orig_test.labels.ravel()

from catboost import CatBoostClassifier
seed_val = 42
model = CatBoostClassifier(iterations=2000,
                                      learning_rate=0.02,
                                      depth=6,
                                      l2_leaf_reg=40,
                                      bootstrap_type='Bernoulli',
                                      subsample=0.8715623,
                                      scale_pos_weight=5,
                                      eval_metric='AUC',
                                      metric_period=50,
                                      od_type='Iter',
                                      od_wait=45,
                                      random_seed=seed_val,
                                     allow_writing_files=False)

mdl = model.fit(X_train, y_train,
                     eval_set=(X_test, y_test),
                     use_best_model=True,
                     verbose=False)

plot_model_performance(mdl, X_test, y_test)

fair = get_fair_metrics_and_plot(data_orig_test, mdl)


### Reweighing
RW = Reweighing(unprivileged_groups=unprivileged_groups, privileged_groups=privileged_groups)

data_transf_train = RW.fit_transform(data_orig_train)

# Train and save the model
rf_transf = model.fit(data_transf_train.features,
                     data_transf_train.labels.ravel())

data_transf_test = RW.transform(data_orig_test)
fair = get_fair_metrics_and_plot(data_transf_test, rf_transf, plot=False)

### Disperate Impact
DIR = DisparateImpactRemover()
data_transf_train = DIR.fit_transform(data_orig_train)

# Train and save the model
rf_transf = model.fit(data_transf_train.features,
                     data_transf_train.labels.ravel())

fair = get_fair_metrics_and_plot(data_orig_test, rf_transf, plot=False)


# Adversarial Debiasing
sess = tf.compat.v1.Session()
debiased_model = AdversarialDebiasing(privileged_groups = privileged_groups,
                          unprivileged_groups = unprivileged_groups,
                          scope_name='debiased_classifier',
                          num_epochs=10,
                          debias=True,
                          sess=sess)

# Train and save the model
debiased_model.fit(data_orig_train)

fair = get_fair_metrics_and_plot(data_orig_test, debiased_model, plot=False, model_aif=True)


#  Prejudice Remover Regularizer
debiased_model = PrejudiceRemover()

# Train and save the model
debiased_model.fit(data_orig_train)

fair = get_fair_metrics_and_plot(data_orig_test, debiased_model, plot=False, model_aif=True)
y_pred = debiased_model.predict(data_orig_test)


data_orig_test_pred = data_orig_test.copy(deepcopy=True)

scores = np.zeros_like(data_orig_test.labels)
scores = mdl.predict(data_orig_test.features).ravel().reshape(-1,1)
data_orig_test_pred.scores = scores

preds = np.zeros_like(data_orig_test.labels)
preds = mdl.predict(data_orig_test.features)
preds = (preds >= 0.5)*1
preds = preds.reshape(-1,1)
data_orig_test_pred.labels = preds

def format_probs(probs1):
    probs1 = np.array(probs1)
    probs0 = np.array(1-probs1)
    return np.concatenate((probs0, probs1), axis=1)


# Equality of Odds

EOPP = EqOddsPostprocessing(privileged_groups = privileged_groups,
                             unprivileged_groups = unprivileged_groups,
                             seed=42)
EOPP = EOPP.fit(data_orig_test, data_orig_test_pred)
data_transf_test_pred = EOPP.predict(data_orig_test_pred)

fair = fair_metrics(data_orig_test, data_transf_test_pred, pred_is_dataset=True)


### Calibrated Equality of Odds
cost_constraint = "fnr"

CPP = CalibratedEqOddsPostprocessing(privileged_groups = privileged_groups,
                                     unprivileged_groups = unprivileged_groups,
                                     cost_constraint=cost_constraint,
                                     seed=42)

CPP = CPP.fit(data_orig_test, data_orig_test_pred)
data_transf_test_pred = CPP.predict(data_orig_test_pred)

fair = fair_metrics(data_orig_test, data_transf_test_pred, pred_is_dataset=True)

### Reject Option Classifier
ROC = RejectOptionClassification(privileged_groups = privileged_groups,
                             unprivileged_groups = unprivileged_groups)

ROC = ROC.fit(data_orig_test, data_orig_test_pred)
data_transf_test_pred = ROC.predict(data_orig_test_pred)

fair = fair_metrics(data_orig_test, data_transf_test_pred, pred_is_dataset=True)
print('SUCCESS: completed 1 model.')

2f81895af9bce10247211b2c2eb4c7b3c0f106b2
<mask token>


def fair_metrics(dataset, pred, pred_is_dataset=False):
    if pred_is_dataset:
        dataset_pred = pred
    else:
        dataset_pred = dataset.copy()
        dataset_pred.labels = pred
    cols = ['Accuracy', 'F1', 'DI', 'SPD', 'EOD', 'AOD', 'ERD', 'CNT', 'TI']
    obj_fairness = [[1, 1, 1, 0, 0, 0, 0, 1, 0]]
    fair_metrics = pd.DataFrame(data=obj_fairness, index=['objective'],
        columns=cols)
    for attr in dataset_pred.protected_attribute_names:
        idx = dataset_pred.protected_attribute_names.index(attr)
        classified_metric = ClassificationMetric(dataset, dataset_pred,
            unprivileged_groups=unprivileged_groups, privileged_groups=
            privileged_groups)
        metric_pred = BinaryLabelDatasetMetric(dataset_pred,
            unprivileged_groups=unprivileged_groups, privileged_groups=
            privileged_groups)
        distortion_metric = SampleDistortionMetric(dataset, dataset_pred,
            unprivileged_groups=unprivileged_groups, privileged_groups=
            privileged_groups)
        acc = classified_metric.accuracy()
        f1_sc = 2 * (classified_metric.precision() * classified_metric.recall()
            ) / (classified_metric.precision() + classified_metric.recall())
        mt = [acc, f1_sc, classified_metric.disparate_impact(),
            classified_metric.mean_difference(), classified_metric.
            equal_opportunity_difference(), classified_metric.
            average_odds_difference(), classified_metric.
            error_rate_difference(), metric_pred.consistency(),
            classified_metric.theil_index()]
        w_row = []
        for i in mt:
            print('%.8f' % i)
            w_row.append('%.8f' % i)
        with open(filename, 'a') as csvfile:
            csvwriter = csv.writer(csvfile)
            csvwriter.writerow(w_row)
        row = pd.DataFrame([mt], columns=cols, index=[attr])
        fair_metrics = fair_metrics.append(row)
    fair_metrics = fair_metrics.replace([-np.inf, np.inf], 2)
    return fair_metrics


def get_fair_metrics_and_plot(data, model, plot=False, model_aif=False):
    pred = model.predict(data).labels if model_aif else model.predict(data.
        features)
    fair = fair_metrics(data, pred)
    if plot:
        pass
    return fair


def get_model_performance(X_test, y_true, y_pred, probs):
    accuracy = accuracy_score(y_true, y_pred)
    matrix = confusion_matrix(y_true, y_pred)
    f1 = f1_score(y_true, y_pred)
    return accuracy, matrix, f1


def plot_model_performance(model, X_test, y_true):
    y_pred = model.predict(X_test)
    probs = model.predict_proba(X_test)
    accuracy, matrix, f1 = get_model_performance(X_test, y_true, y_pred, probs)


<mask token>


def add_to_df_algo_metrics(algo_metrics, model, fair_metrics, preds, probs,
    name):
    return algo_metrics.append(pd.DataFrame(data=[[model, fair_metrics,
        preds, probs]], columns=['model', 'fair_metrics', 'prediction',
        'probs'], index=[name]))


<mask token>


def format_probs(probs1):
    probs1 = np.array(probs1)
    probs0 = np.array(1 - probs1)
    return np.concatenate((probs0, probs1), axis=1)


<mask token>

<mask token>


def fair_metrics(dataset, pred, pred_is_dataset=False):
    if pred_is_dataset:
        dataset_pred = pred
    else:
        dataset_pred = dataset.copy()
        dataset_pred.labels = pred
    cols = ['Accuracy', 'F1', 'DI', 'SPD', 'EOD', 'AOD', 'ERD', 'CNT', 'TI']
    obj_fairness = [[1, 1, 1, 0, 0, 0, 0, 1, 0]]
    fair_metrics = pd.DataFrame(data=obj_fairness, index=['objective'],
        columns=cols)
    for attr in dataset_pred.protected_attribute_names:
        idx = dataset_pred.protected_attribute_names.index(attr)
        classified_metric = ClassificationMetric(dataset, dataset_pred,
            unprivileged_groups=unprivileged_groups, privileged_groups=
            privileged_groups)
        metric_pred = BinaryLabelDatasetMetric(dataset_pred,
            unprivileged_groups=unprivileged_groups, privileged_groups=
            privileged_groups)
        distortion_metric = SampleDistortionMetric(dataset, dataset_pred,
            unprivileged_groups=unprivileged_groups, privileged_groups=
            privileged_groups)
        acc = classified_metric.accuracy()
        f1_sc = 2 * (classified_metric.precision() * classified_metric.recall()
            ) / (classified_metric.precision() + classified_metric.recall())
        mt = [acc, f1_sc, classified_metric.disparate_impact(),
            classified_metric.mean_difference(), classified_metric.
            equal_opportunity_difference(), classified_metric.
            average_odds_difference(), classified_metric.
            error_rate_difference(), metric_pred.consistency(),
            classified_metric.theil_index()]
        w_row = []
        for i in mt:
            print('%.8f' % i)
            w_row.append('%.8f' % i)
        with open(filename, 'a') as csvfile:
            csvwriter = csv.writer(csvfile)
            csvwriter.writerow(w_row)
        row = pd.DataFrame([mt], columns=cols, index=[attr])
        fair_metrics = fair_metrics.append(row)
    fair_metrics = fair_metrics.replace([-np.inf, np.inf], 2)
    return fair_metrics


def get_fair_metrics_and_plot(data, model, plot=False, model_aif=False):
    pred = model.predict(data).labels if model_aif else model.predict(data.
        features)
    fair = fair_metrics(data, pred)
    if plot:
        pass
    return fair


def get_model_performance(X_test, y_true, y_pred, probs):
    accuracy = accuracy_score(y_true, y_pred)
    matrix = confusion_matrix(y_true, y_pred)
    f1 = f1_score(y_true, y_pred)
    return accuracy, matrix, f1


def plot_model_performance(model, X_test, y_true):
    y_pred = model.predict(X_test)
    probs = model.predict_proba(X_test)
    accuracy, matrix, f1 = get_model_performance(X_test, y_true, y_pred, probs)


<mask token>


def add_to_df_algo_metrics(algo_metrics, model, fair_metrics, preds, probs,
    name):
    return algo_metrics.append(pd.DataFrame(data=[[model, fair_metrics,
        preds, probs]], columns=['model', 'fair_metrics', 'prediction',
        'probs'], index=[name]))


<mask token>


@contextmanager
def timer(title):
    t0 = time.time()
    yield
    print('{} - done in {:.0f}s'.format(title, time.time() - t0))


<mask token>


def format_probs(probs1):
    probs1 = np.array(probs1)
    probs0 = np.array(1 - probs1)
    return np.concatenate((probs0, probs1), axis=1)


<mask token>

<mask token>


def fair_metrics(dataset, pred, pred_is_dataset=False):
    if pred_is_dataset:
        dataset_pred = pred
    else:
        dataset_pred = dataset.copy()
        dataset_pred.labels = pred
    cols = ['Accuracy', 'F1', 'DI', 'SPD', 'EOD', 'AOD', 'ERD', 'CNT', 'TI']
    obj_fairness = [[1, 1, 1, 0, 0, 0, 0, 1, 0]]
    fair_metrics = pd.DataFrame(data=obj_fairness, index=['objective'],
        columns=cols)
    for attr in dataset_pred.protected_attribute_names:
        idx = dataset_pred.protected_attribute_names.index(attr)
        classified_metric = ClassificationMetric(dataset, dataset_pred,
            unprivileged_groups=unprivileged_groups, privileged_groups=
            privileged_groups)
        metric_pred = BinaryLabelDatasetMetric(dataset_pred,
            unprivileged_groups=unprivileged_groups, privileged_groups=
            privileged_groups)
        distortion_metric = SampleDistortionMetric(dataset, dataset_pred,
            unprivileged_groups=unprivileged_groups, privileged_groups=
            privileged_groups)
        acc = classified_metric.accuracy()
        f1_sc = 2 * (classified_metric.precision() * classified_metric.recall()
            ) / (classified_metric.precision() + classified_metric.recall())
        mt = [acc, f1_sc, classified_metric.disparate_impact(),
            classified_metric.mean_difference(), classified_metric.
            equal_opportunity_difference(), classified_metric.
            average_odds_difference(), classified_metric.
            error_rate_difference(), metric_pred.consistency(),
            classified_metric.theil_index()]
        w_row = []
        for i in mt:
            print('%.8f' % i)
            w_row.append('%.8f' % i)
        with open(filename, 'a') as csvfile:
            csvwriter = csv.writer(csvfile)
            csvwriter.writerow(w_row)
        row = pd.DataFrame([mt], columns=cols, index=[attr])
        fair_metrics = fair_metrics.append(row)
    fair_metrics = fair_metrics.replace([-np.inf, np.inf], 2)
    return fair_metrics


def get_fair_metrics_and_plot(data, model, plot=False, model_aif=False):
    pred = model.predict(data).labels if model_aif else model.predict(data.
        features)
    fair = fair_metrics(data, pred)
    if plot:
        pass
    return fair


def get_model_performance(X_test, y_true, y_pred, probs):
    accuracy = accuracy_score(y_true, y_pred)
    matrix = confusion_matrix(y_true, y_pred)
    f1 = f1_score(y_true, y_pred)
    return accuracy, matrix, f1


def plot_model_performance(model, X_test, y_true):
    y_pred = model.predict(X_test)
    probs = model.predict_proba(X_test)
    accuracy, matrix, f1 = get_model_performance(X_test, y_true, y_pred, probs)


<mask token>


def add_to_df_algo_metrics(algo_metrics, model, fair_metrics, preds, probs,
    name):
    return algo_metrics.append(pd.DataFrame(data=[[model, fair_metrics,
        preds, probs]], columns=['model', 'fair_metrics', 'prediction',
        'probs'], index=[name]))


def custom_preprocessing(df):

    def group_race(x):
        if x == 'White':
            return 1.0
        else:
            return 0.0
    df['sex'] = df['sex'].replace({'Female': 0.0, 'Male': 1.0})
    df['race'] = df['race'].apply(lambda x: group_race(x))
    return df


<mask token>


@contextmanager
def timer(title):
    t0 = time.time()
    yield
    print('{} - done in {:.0f}s'.format(title, time.time() - t0))


def one_hot_encoder(df, nan_as_category=True):
    original_columns = list(df.columns)
    categorical_columns = [col for col in df.columns if df[col].dtype ==
        'object']
    df = pd.get_dummies(df, columns=categorical_columns, dummy_na=
        nan_as_category)
    new_columns = [c for c in df.columns if c not in original_columns]
    return df, new_columns


<mask token>


def format_probs(probs1):
    probs1 = np.array(probs1)
    probs0 = np.array(1 - probs1)
    return np.concatenate((probs0, probs1), axis=1)


<mask token>

<mask token>
sys.path.append('../utils/')
<mask token>
Path(dir).mkdir(parents=True, exist_ok=True)
<mask token>
with open(filename, 'a') as csvfile:
    csvwriter = csv.writer(csvfile)
    csvwriter.writerow(fields)


def fair_metrics(dataset, pred, pred_is_dataset=False):
    if pred_is_dataset:
        dataset_pred = pred
    else:
        dataset_pred = dataset.copy()
        dataset_pred.labels = pred
    cols = ['Accuracy', 'F1', 'DI', 'SPD', 'EOD', 'AOD', 'ERD', 'CNT', 'TI']
    obj_fairness = [[1, 1, 1, 0, 0, 0, 0, 1, 0]]
    fair_metrics = pd.DataFrame(data=obj_fairness, index=['objective'],
        columns=cols)
    for attr in dataset_pred.protected_attribute_names:
        idx = dataset_pred.protected_attribute_names.index(attr)
        classified_metric = ClassificationMetric(dataset, dataset_pred,
            unprivileged_groups=unprivileged_groups, privileged_groups=
            privileged_groups)
        metric_pred = BinaryLabelDatasetMetric(dataset_pred,
            unprivileged_groups=unprivileged_groups, privileged_groups=
            privileged_groups)
        distortion_metric = SampleDistortionMetric(dataset, dataset_pred,
            unprivileged_groups=unprivileged_groups, privileged_groups=
            privileged_groups)
        acc = classified_metric.accuracy()
        f1_sc = 2 * (classified_metric.precision() * classified_metric.recall()
            ) / (classified_metric.precision() + classified_metric.recall())
        mt = [acc, f1_sc, classified_metric.disparate_impact(),
            classified_metric.mean_difference(), classified_metric.
            equal_opportunity_difference(), classified_metric.
            average_odds_difference(), classified_metric.
            error_rate_difference(), metric_pred.consistency(),
            classified_metric.theil_index()]
        w_row = []
        for i in mt:
            print('%.8f' % i)
            w_row.append('%.8f' % i)
        with open(filename, 'a') as csvfile:
            csvwriter = csv.writer(csvfile)
            csvwriter.writerow(w_row)
        row = pd.DataFrame([mt], columns=cols, index=[attr])
        fair_metrics = fair_metrics.append(row)
    fair_metrics = fair_metrics.replace([-np.inf, np.inf], 2)
    return fair_metrics


def get_fair_metrics_and_plot(data, model, plot=False, model_aif=False):
    pred = model.predict(data).labels if model_aif else model.predict(data.
        features)
    fair = fair_metrics(data, pred)
    if plot:
        pass
    return fair


def get_model_performance(X_test, y_true, y_pred, probs):
    accuracy = accuracy_score(y_true, y_pred)
    matrix = confusion_matrix(y_true, y_pred)
    f1 = f1_score(y_true, y_pred)
    return accuracy, matrix, f1


def plot_model_performance(model, X_test, y_true):
    y_pred = model.predict(X_test)
    probs = model.predict_proba(X_test)
    accuracy, matrix, f1 = get_model_performance(X_test, y_true, y_pred, probs)


<mask token>


def add_to_df_algo_metrics(algo_metrics, model, fair_metrics, preds, probs,
    name):
    return algo_metrics.append(pd.DataFrame(data=[[model, fair_metrics,
        preds, probs]], columns=['model', 'fair_metrics', 'prediction',
        'probs'], index=[name]))


def custom_preprocessing(df):

    def group_race(x):
        if x == 'White':
            return 1.0
        else:
            return 0.0
    df['sex'] = df['sex'].replace({'Female': 0.0, 'Male': 1.0})
    df['race'] = df['race'].apply(lambda x: group_race(x))
    return df


<mask token>


@contextmanager
def timer(title):
    t0 = time.time()
    yield
    print('{} - done in {:.0f}s'.format(title, time.time() - t0))


def one_hot_encoder(df, nan_as_category=True):
    original_columns = list(df.columns)
    categorical_columns = [col for col in df.columns if df[col].dtype ==
        'object']
    df = pd.get_dummies(df, columns=categorical_columns, dummy_na=
        nan_as_category)
    new_columns = [c for c in df.columns if c not in original_columns]
    return df, new_columns


<mask token>
for col in features:
    if features[col].dtype == 'object':
        if len(list(features[col].unique())) <= 2 or col == 'CODE_GENDER':
            le.fit(features[col])
            features[col] = le.transform(features[col])
            le_count += 1
<mask token>
imputer.fit(features)
<mask token>
plot_model_performance(mdl, X_test, y_test)
<mask token>
debiased_model.fit(data_orig_train)
<mask token>
debiased_model.fit(data_orig_train)
<mask token>


def format_probs(probs1):
    probs1 = np.array(probs1)
    probs0 = np.array(1 - probs1)
    return np.concatenate((probs0, probs1), axis=1)


<mask token>
print('SUCCESS: completed 1 model.')

#!/usr/bin/env python
# coding: utf-8

import sys
sys.path.append('../utils/')
# sys.path.insert(1, '../utils/')
from packages import *
from ml_fairness import *

import csv
from pathlib import Path
dir = 'home/res/model6/'
Path(dir).mkdir(parents=True, exist_ok=True)
f_count = len([name for name in os.listdir(dir) if os.path.isfile(os.path.join(dir, name)) and not name.startswith('.')])

fields = ['Acc', 'F1', 'DI','SPD', 'EOD', 'AOD', 'ERD', 'CNT', 'TI']
filename = dir + str(f_count+1) + '.csv'
with open(filename, 'a') as csvfile:
    csvwriter = csv.writer(csvfile)
    csvwriter.writerow(fields)

def fair_metrics(dataset, pred, pred_is_dataset=False):
    if pred_is_dataset:
        dataset_pred = pred
    else:
        dataset_pred = dataset.copy()
        dataset_pred.labels = pred

    cols = ['Accuracy', 'F1', 'DI','SPD', 'EOD', 'AOD', 'ERD', 'CNT', 'TI']
    obj_fairness = [[1,1,1,0,0,0,0,1,0]]

    fair_metrics = pd.DataFrame(data=obj_fairness, index=['objective'], columns=cols)

    for attr in dataset_pred.protected_attribute_names:
        idx = dataset_pred.protected_attribute_names.index(attr)

        classified_metric = ClassificationMetric(dataset,
                                                     dataset_pred,
                                                     unprivileged_groups=unprivileged_groups,
                                                     privileged_groups=privileged_groups)

        metric_pred = BinaryLabelDatasetMetric(dataset_pred,
                                                     unprivileged_groups=unprivileged_groups,
                                                     privileged_groups=privileged_groups)

        distortion_metric = SampleDistortionMetric(dataset,
                                                     dataset_pred,
                                                     unprivileged_groups=unprivileged_groups,
                                                     privileged_groups=privileged_groups)

        acc = classified_metric.accuracy()
        f1_sc = 2 * (classified_metric.precision() * classified_metric.recall()) / (classified_metric.precision() + classified_metric.recall())

        mt = [acc, f1_sc,
                        classified_metric.disparate_impact(),
                        classified_metric.mean_difference(),
                        classified_metric.equal_opportunity_difference(),
                        classified_metric.average_odds_difference(),
                        classified_metric.error_rate_difference(),
                        metric_pred.consistency(),
                        classified_metric.theil_index()
                    ]
        w_row = []
        for i in mt:
            print("%.8f"%i)
            w_row.append("%.8f"%i)
        with open(filename, 'a') as csvfile:
            csvwriter = csv.writer(csvfile)
            csvwriter.writerow(w_row)
        row = pd.DataFrame([mt],
                           columns  = cols,
                           index = [attr]
                          )
        fair_metrics = fair_metrics.append(row)

    fair_metrics = fair_metrics.replace([-np.inf, np.inf], 2)
    return fair_metrics

def get_fair_metrics_and_plot(data, model, plot=False, model_aif=False):
    pred = model.predict(data).labels if model_aif else model.predict(data.features)
    fair = fair_metrics(data, pred)

    if plot:
        pass

    return fair


def get_model_performance(X_test, y_true, y_pred, probs):
    accuracy = accuracy_score(y_true, y_pred)
    matrix = confusion_matrix(y_true, y_pred)
    f1 = f1_score(y_true, y_pred)
    return accuracy, matrix, f1

def plot_model_performance(model, X_test, y_true):
    y_pred = model.predict(X_test)
    probs = model.predict_proba(X_test)
    accuracy, matrix, f1 = get_model_performance(X_test, y_true, y_pred, probs)


algo_metrics = pd.DataFrame(columns=['model', 'fair_metrics', 'prediction', 'probs'])

def add_to_df_algo_metrics(algo_metrics, model, fair_metrics, preds, probs, name):
    return algo_metrics.append(pd.DataFrame(data=[[model, fair_metrics, preds, probs]], columns=['model', 'fair_metrics', 'prediction', 'probs'], index=[name]))

def custom_preprocessing(df):
        def group_race(x):
            if x == "White":
                return 1.0
            else:
                return 0.0
        # Recode sex and race
        df['sex'] = df['sex'].replace({'Female': 0.0, 'Male': 1.0})
        df['race'] = df['race'].apply(lambda x: group_race(x))

        return df

import gc
import time
from contextlib import contextmanager
from lightgbm import LGBMClassifier

@contextmanager
def timer(title):
    t0 = time.time()
    yield
    print("{} - done in {:.0f}s".format(title, time.time() - t0))

def one_hot_encoder(df, nan_as_category = True):
    original_columns = list(df.columns)
    categorical_columns = [col for col in df.columns if df[col].dtype == 'object']
    df = pd.get_dummies(df, columns= categorical_columns, dummy_na= nan_as_category)
    new_columns = [c for c in df.columns if c not in original_columns]
    return df, new_columns


from sklearn.preprocessing import MinMaxScaler
from sklearn.impute import SimpleImputer
train_control = pd.read_csv('../../dataset/home-data/application_train.csv')

features = train_control

train_ids = features['SK_ID_CURR']

labels = features['TARGET']

# Remove the ids and target
features = features.drop(columns = ['SK_ID_CURR']) #, 'TARGET'

le = LabelEncoder()
le_count = 0
for col in features:
    if features[col].dtype == 'object':
        # If 2 or fewer unique categories
        if len(list(features[col].unique())) <= 2 or col == 'CODE_GENDER':
            # Train on the training data
            le.fit(features[col])
            # Transform both training and testing data
            features[col] = le.transform(features[col])
            # Keep track of how many columns were label encoded
            le_count += 1

features = pd.get_dummies(features)

# No categorical indices to record
cat_indices = 'auto'

# Extract feature names
feature_names = list(features.columns)

col = list(features.columns.values)
# Convert to np arrays
features = np.array(features)
imputer = SimpleImputer(strategy = 'median')
# Scale each feature to 0-1
scaler = MinMaxScaler(feature_range = (0, 1))
# Fit on the training data
imputer.fit(features)
# Transform both training and testing data
features = imputer.transform(features)
features = pd.DataFrame(features, columns=col)

dataset_orig = StandardDataset(features,
                               label_name='TARGET',
                               favorable_classes=[1],
                               protected_attribute_names=['CODE_GENDER'],
                               privileged_classes=[[0]])

privileged_groups = [{'CODE_GENDER': 0}]
unprivileged_groups = [{'CODE_GENDER': 1}]

data_orig_train, data_orig_test = dataset_orig.split([0.7], shuffle=True)

X_train = data_orig_train.features
y_train = data_orig_train.labels.ravel()

X_test = data_orig_test.features
y_test = data_orig_test.labels.ravel()

from catboost import CatBoostClassifier
seed_val = 42
model = CatBoostClassifier(iterations=2000,
                                      learning_rate=0.02,
                                      depth=6,
                                      l2_leaf_reg=40,
                                      bootstrap_type='Bernoulli',
                                      subsample=0.8715623,
                                      scale_pos_weight=5,
                                      eval_metric='AUC',
                                      metric_period=50,
                                      od_type='Iter',
                                      od_wait=45,
                                      random_seed=seed_val,
                                     allow_writing_files=False)

mdl = model.fit(X_train, y_train,
                     eval_set=(X_test, y_test),
                     use_best_model=True,
                     verbose=False)

plot_model_performance(mdl, X_test, y_test)

fair = get_fair_metrics_and_plot(data_orig_test, mdl)


### Reweighing
RW = Reweighing(unprivileged_groups=unprivileged_groups, privileged_groups=privileged_groups)

data_transf_train = RW.fit_transform(data_orig_train)

# Train and save the model
rf_transf = model.fit(data_transf_train.features,
                     data_transf_train.labels.ravel())

data_transf_test = RW.transform(data_orig_test)
fair = get_fair_metrics_and_plot(data_transf_test, rf_transf, plot=False)

### Disperate Impact
DIR = DisparateImpactRemover()
data_transf_train = DIR.fit_transform(data_orig_train)

# Train and save the model
rf_transf = model.fit(data_transf_train.features,
                     data_transf_train.labels.ravel())

fair = get_fair_metrics_and_plot(data_orig_test, rf_transf, plot=False)


# Adversarial Debiasing
sess = tf.compat.v1.Session()
debiased_model = AdversarialDebiasing(privileged_groups = privileged_groups,
                          unprivileged_groups = unprivileged_groups,
                          scope_name='debiased_classifier',
                          num_epochs=10,
                          debias=True,
                          sess=sess)

# Train and save the model
debiased_model.fit(data_orig_train)

fair = get_fair_metrics_and_plot(data_orig_test, debiased_model, plot=False, model_aif=True)


#  Prejudice Remover Regularizer
debiased_model = PrejudiceRemover()

# Train and save the model
debiased_model.fit(data_orig_train)

fair = get_fair_metrics_and_plot(data_orig_test, debiased_model, plot=False, model_aif=True)
y_pred = debiased_model.predict(data_orig_test)


data_orig_test_pred = data_orig_test.copy(deepcopy=True)

scores = np.zeros_like(data_orig_test.labels)
scores = mdl.predict(data_orig_test.features).ravel().reshape(-1,1)
data_orig_test_pred.scores = scores

preds = np.zeros_like(data_orig_test.labels)
preds = mdl.predict(data_orig_test.features)
preds = (preds >= 0.5)*1
preds = preds.reshape(-1,1)
data_orig_test_pred.labels = preds

def format_probs(probs1):
    probs1 = np.array(probs1)
    probs0 = np.array(1-probs1)
    return np.concatenate((probs0, probs1), axis=1)


# Equality of Odds

EOPP = EqOddsPostprocessing(privileged_groups = privileged_groups,
                             unprivileged_groups = unprivileged_groups,
                             seed=42)
EOPP = EOPP.fit(data_orig_test, data_orig_test_pred)
data_transf_test_pred = EOPP.predict(data_orig_test_pred)

fair = fair_metrics(data_orig_test, data_transf_test_pred, pred_is_dataset=True)


### Calibrated Equality of Odds
cost_constraint = "fnr"

CPP = CalibratedEqOddsPostprocessing(privileged_groups = privileged_groups,
                                     unprivileged_groups = unprivileged_groups,
                                     cost_constraint=cost_constraint,
                                     seed=42)

CPP = CPP.fit(data_orig_test, data_orig_test_pred)
data_transf_test_pred = CPP.predict(data_orig_test_pred)

fair = fair_metrics(data_orig_test, data_transf_test_pred, pred_is_dataset=True)

### Reject Option Classifier
ROC = RejectOptionClassification(privileged_groups = privileged_groups,
                             unprivileged_groups = unprivileged_groups)

ROC = ROC.fit(data_orig_test, data_orig_test_pred)
data_transf_test_pred = ROC.predict(data_orig_test_pred)

fair = fair_metrics(data_orig_test, data_transf_test_pred, pred_is_dataset=True)
print('SUCCESS: completed 1 model.')
