1 UCI Performance
Contents
1 UCI Performance¶
This notebook summarizes the performance and analysis on the UCI Datasets.
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
from sciplotlib import style
import seaborn as sns
from myst_nb import glue
from leakconfound.plotting import custom_bar_rope_plot, mm_to_inch
from leakconfound.plotting.settings import red, blue
from leakconfound.analyses.load import (
prepare_performance_data,
gather_data,
data_to_long,
data_renamer,
models_renamer,
)
import warnings
warnings.filterwarnings("ignore", category=UserWarning)
warnings.filterwarnings("ignore", category=FutureWarning)
Set MPL Settings¶
mpl.style.use(style.get_style("nature-reviews"))
mpl.rc("xtick", labelsize=11)
mpl.rc("ytick", labelsize=11)
mpl.rc("axes", labelsize=12, titlesize=12)
mpl.rc("figure", dpi=300)
mpl.rc("figure.subplot", wspace=mm_to_inch(4), hspace=mm_to_inch(7))
mpl.rc("lines", linewidth=1)
Load Datasets¶
results_base = "../../results/"
raw_TaCo_folder = f"{results_base}basic_TaCo/uci_datasets/"
shuffled_TaCo_folder = results_base + "shuffled_features_TaCo/uci_datasets/"
# ### Load Raw TaCo Dataset
arguments_TaCo = ["data", "model_name", "is_deconfounded", "random_seed"]
score_names = [
"test_r2",
"test_roc_auc",
"test_X_hat_r2",
"test_X_hat_roc_auc",
]
def correct_fold_repeat(df):
df.repeat = df.fold // 5
df.fold = df.fold % 5
return df
def convert_hat_scores(df):
_df = df.copy()
return (
_df.assign(is_X_hat=lambda df: df.score_name.str.contains("X_hat"))
.assign(
confound=lambda df: df.apply(
lambda row: "X hat" if row["is_X_hat"] else row["confound"], axis=1
)
)
.assign(score_name=lambda df: df.score_name.str.replace("X_hat_", ""))
)
def correct_columns(df):
return correct_fold_repeat(convert_hat_scores(df)).dropna()
Load Raw Data¶
df_TaCo = prepare_performance_data(
raw_TaCo_folder, analysis_arguments=arguments_TaCo, score_names=score_names
)
# load performance TaCo shuffled
df_TaCo_shuffled = prepare_performance_data(
shuffled_TaCo_folder, analysis_arguments=arguments_TaCo, score_names=score_names
).dropna()
arguments_TaCo.pop(2)
arguments_TaCo.extend(["confound"])
Subset TaCo Data¶
order = [
"Linear/Logistic",
"Decision Tree",
"Random Forest",
"Neural Network",
"Linear SVM",
"RBF SVM",
"Gaussian Model",
]
datasets_selected = ["Abalone", "Heart", "Real Estate", "Blood"]
df_plot_TaCo_selected = (
df_TaCo.dropna()
.query("data in @datasets_selected")
.query(f"model_name in {order}")
.query(f"score_name in {score_names}")
)
df_plot_TaCo_shuffled_selected = (
df_TaCo_shuffled.query("data in @datasets_selected")
.query(f"model_name in {order}")
.query(f"score_name in {score_names}")
)
Data Retrieval non TaCo -> Simulated Confounds¶
def prepare_non_TaCo(shuffled):
used_model = "Random Forest"
non_TaCo_folder = results_base + (
"/shuffled_features_non_TaCo/uci_sim_conf_datasets/"
if shuffled
else "/basic_non_TaCo/uci_sim_conf_datasets/"
)
non_TaCo_arguments = ["data", "model_name", "is_deconfounded", "random_seed"]
df_non_TaCo = gather_data(
non_TaCo_folder,
non_TaCo_arguments,
)
non_TaCo_arguments.append("conf_corr")
# adding how much correlation was used for the confounds
df_settings = (
df_non_TaCo.data.apply(lambda col: col.replace("real_estate", "realestate"))
.apply(lambda col: pd.Series(col.split("_")))
.apply(lambda col: col.replace("realestate", "real_estate"))
.rename(columns={0: "data", 2: "conf_corr"})
.drop(columns=[1])
)
df_non_TaCo = pd.concat(
[df_non_TaCo.drop(columns="data"), df_settings], axis=1
).assign(
data=lambda df: df.data.map(data_renamer),
model_name=lambda df: df.model_name.map(models_renamer),
conf_corr=lambda df: df.conf_corr.apply(lambda x: "0." + str(x)),
)
df_plot_non_TaCo = (
data_to_long(df_non_TaCo, non_TaCo_arguments, score_names)
.query(f'(model_name == "{used_model}") & ' f"(score_name in {score_names})")
.dropna()
)
return df_plot_non_TaCo
df_plot_non_TaCo = prepare_non_TaCo(False)
df_plot_non_TaCo_shuffled = prepare_non_TaCo(True)
df_plot_non_TaCo_selected = (
df_plot_non_TaCo.dropna()
.query("data in @datasets_selected")
.query(f"model_name in {order}")
.query(f"score_name in {score_names}")
)
df_plot_non_TaCo_shuffled_selected = (
df_plot_non_TaCo_shuffled.query("data in @datasets_selected")
.query(f"model_name in {order}")
.query(f"score_name in {score_names}")
)
Clean & Correct Repeat and Fold & Scoring¶
df_plot_TaCo = correct_columns(df_TaCo)
df_plot_TaCo_shuffled = correct_columns(df_TaCo_shuffled)
df_plot_non_TaCo = correct_columns(df_plot_non_TaCo)
df_plot_non_TaCo_shuffled = correct_columns(df_plot_non_TaCo_shuffled)
df_plot_TaCo_selected = correct_columns(df_plot_TaCo_selected)
df_plot_TaCo_shuffled_selected = correct_columns(df_plot_TaCo_shuffled_selected)
df_plot_non_TaCo_selected = correct_columns(df_plot_non_TaCo_selected)
df_plot_non_TaCo_shuffled_selected = correct_columns(df_plot_non_TaCo_shuffled_selected)
Create Plotting Function¶
def plot_performance(
df_TaCo,
df_non_TaCo,
figsize=None,
model_label_dict=None,
hue_order=None,
):
row = "data"
x = "model_name"
y = "score"
hue = "confound"
hue_order = ["not removed", "removed"] if hue_order is None else hue_order
row_vals = df_TaCo[row].unique()
n_rows = len(row_vals)
rope_sign_fontsize = 9
used_model_dict = (
{
"Linear/Logistic": "LR",
"Decision Tree": "DT",
"Random Forest": "RF",
"Neural Network": "MLP",
}
if model_label_dict is None
else model_label_dict
)
ylabel_dict = {"test_roc_auc": "AUROC", "test_r2": "R²"}
fig, axes = plt.subplots(nrows=n_rows, ncols=2, figsize=figsize)
for i_row, row_val in enumerate(row_vals):
ax = axes[i_row, 0]
data = df_TaCo.query(
'(score_name in ["test_r2", "test_roc_auc"] ) & ' f"({row} == @row_val)"
).query("confound in ['not removed', 'removed']")
score_names = data.score_name.unique()
score_name = score_names[0]
custom_bar_rope_plot(
x,
y,
hue,
comparisons=(("not removed", "removed"),),
comparisons_sing_y=[1.15],
cv_repeats="repeat",
data=data,
hue_order=hue_order,
order=list(used_model_dict.keys()),
palette=sns.color_palette([blue, red]),
ax=ax,
show_legend=False,
rope_sign_fontsize=rope_sign_fontsize,
rope_line_width=0.5,
rope=0.05,
)
if i_row == 0:
ax.set_title(
"TaCo CR",
)
if i_row < len(row_vals) - 1:
ax.set_xticklabels("", rotation=0)
ax.set_xlabel("")
else:
ax.set_xticklabels(
[used_model_dict[tick.get_text()] for tick in ax.get_xticklabels()],
rotation=0,
)
ax.set_xlabel(
"Model Used",
)
ax.set_ylabel(
ylabel_dict[score_name],
)
ax.set_yticks(np.arange(0, 1.25, 0.25))
ax.set_ylim([-0.05, 1.2])
ax.yaxis.set_major_locator(MultipleLocator(0.5))
for i_row, row_val in enumerate(row_vals):
ax = axes[i_row, 1]
data = df_non_TaCo.query(
f'(model_name == "Random Forest") & ({row} == @row_val)'
)
custom_bar_rope_plot(
"conf_corr",
y,
hue,
comparisons=(("not removed", "removed"),),
comparisons_sing_y=[1.15],
cv_repeats="repeat",
data=data,
hue_order=hue_order,
order=["0.2", "0.4", "0.6", "0.8"],
palette=sns.color_palette([blue, red]),
rope_sign_fontsize=rope_sign_fontsize,
rope_line_width=0.5,
ax=ax,
show_legend=False,
rope=0.05,
)
if i_row == 0:
ax.set_title(
"CR Simulated Confounds",
)
if i_row < len(row_vals) - 1:
ax.set_xticklabels("")
ax.set_xlabel("")
else:
ax.set_xticklabels(ax.get_xticklabels(), rotation=0)
ax.set_xlabel(
"Confound Target \nCorrelation",
)
ax.set_ylim([-0.05, 1.2])
axR = ax.twinx()
axR.set_yticks([])
axR.set_ylabel(
row_val,
rotation=270,
labelpad=8,
horizontalalignment="center",
verticalalignment="center",
)
handles = [
mpl.patches.Patch(color=blue, label="$X$"),
mpl.patches.Patch(color=red, label="$X_{CR}$"),
]
fig.legend(
handles=handles,
title="Features:",
loc="upper center",
ncol=3,
)
return fig, axes
Plotting Performance for Selected Datapoints¶
df_plot_TaCo_selected = df_plot_TaCo_selected.query(
"confound in ['not removed', 'removed']"
)
df_plot_non_TaCo_selected = df_plot_non_TaCo_selected.query(
"confound in ['not removed', 'removed']"
)
fig_selected, axes = plot_performance(
df_plot_TaCo_selected,
df_plot_non_TaCo_selected,
hue_order=["not removed", "removed"],
figsize=[mm_to_inch(183), mm_to_inch(140)],
)
fig_selected.savefig("./saved_figures/uci_performance.svg")
fig_selected.savefig("./saved_figures/uci_performance.png")
glue("uci_selected", fig_selected, display=False)
df_plot_TaCo_shuffled_selected = df_plot_TaCo_shuffled_selected.query(
"confound in ['not removed', 'removed']"
)
df_plot_non_TaCo_shuffled_selected = df_plot_non_TaCo_shuffled_selected.query(
"confound in ['not removed', 'removed']"
)
fig_shuffled_selected, axes = plot_performance(
df_plot_TaCo_shuffled_selected,
df_plot_non_TaCo_shuffled_selected,
hue_order=["not removed", "removed"],
figsize=[mm_to_inch(183), mm_to_inch(140)],
)
fig_shuffled_selected.savefig("./saved_figures/uci_performance_shuffled.svg")
fig_shuffled_selected.savefig("./saved_figures/uci_performance_shuffled.png")
glue("uci_selected_shuffled", fig_shuffled_selected, display=False)
Plotting Performance for all Datapoints¶
all_model_dict = {
"Linear/Logistic": "LR",
"Decision Tree": "DT",
"Random Forest": "RF",
"Neural Network": "MLP",
"Linear SVM": "Lin SVM",
"RBF SVM": "RBF SVM",
"Baseline Model": "Chance",
}
df_plot_TaCo = df_plot_TaCo.query("confound in ['not removed', 'removed']")
df_plot_non_TaCo = df_plot_non_TaCo.query("confound in ['not removed', 'removed']")
with mpl.rc_context(
{"figure.subplot.wspace": mm_to_inch(4), "figure.subplot.hspace": mm_to_inch(2)}
):
fig_all, axes = plot_performance(
df_plot_TaCo,
df_plot_non_TaCo,
figsize=[mm_to_inch(183), mm_to_inch(280)],
model_label_dict=all_model_dict,
hue_order=["not removed", "removed"],
)
axes[-1, 0].set_xticklabels(axes[-1, 0].get_xticklabels(), rotation=90)
axes[-1, 1].set_xticklabels(axes[-1, 1].get_xticklabels(), rotation=90)
glue("uci_all", fig_all, display=False)
fig_all.savefig("./saved_figures/uci_performance_all.svg")
fig_all.savefig("./saved_figures/uci_performance_all.png")
df_plot_TaCo_shuffled = df_plot_TaCo_shuffled.query(
"confound in ['not removed', 'removed']"
)
df_plot_non_TaCo_shuffled = df_plot_non_TaCo_shuffled.query(
"confound in ['not removed', 'removed']"
)
with mpl.rc_context(
{"figure.subplot.wspace": mm_to_inch(4), "figure.subplot.hspace": mm_to_inch(2)}
):
fig_all_shuffled, axes = plot_performance(
df_plot_TaCo_shuffled,
df_plot_non_TaCo_shuffled,
figsize=[mm_to_inch(183), mm_to_inch(280)],
model_label_dict=all_model_dict,
hue_order=["not removed", "removed"],
)
axes[-1, 0].set_xticklabels(axes[-1, 0].get_xticklabels(), rotation=90)
axes[-1, 1].set_xticklabels(axes[-1, 1].get_xticklabels(), rotation=90)
glue("uci_all_shuffled", fig_all_shuffled, display=False)
fig_all_shuffled.savefig("./saved_figures/uci_performance_all_shuffled.svg")
fig_all_shuffled.savefig("./saved_figures/uci_performance_all_shuffled.png")