Code
= splitpath(pwd()) |>
projectdir -> joinpath(ss[1:findall([s == "endogenous-macrodynamics-in-algorithmic-recourse" for s in ss])[1]]...)
ss cd(projectdir)
= splitpath(pwd()) |>
projectdir -> joinpath(ss[1:findall([s == "endogenous-macrodynamics-in-algorithmic-recourse" for s in ss])[1]]...)
ss cd(projectdir)
This notebook was used to run the experiments for the synthetic datasets and can be used to reproduce the results in the paper. In the following we first run the experiments and then generate visualizations and tables.
= [
models :LogisticRegression,
:FluxModel,
:FluxEnsemble,
]= Flux.Descent(0.01)
opt = Dict(
generators :Greedy=>GreedyGenerator(),
:Generic=>GenericGenerator(opt = opt),
:REVISE=>REVISEGenerator(opt = opt),
:DICE=>DiCEGenerator(opt = opt),
)
= 1000
max_obs = load_synthetic(max_obs)
catalogue = [
choices :linearly_separable,
:overlapping,
:circles,
:moons,
]= filter(p -> p[1] in choices, catalogue) data_sets
= set_up_experiments(data_sets,models,generators) experiments
= []
plts for (exp_name, exp_) in experiments
for (M_name, M) in exp_.models
= round(model_evaluation(M, exp_.test_data),digits=2)
score = plot(M, exp_.test_data, title="$exp_name;\n $M_name ($score)")
plt # Errors:
= findall(vec(round.(probs(M, exp_.test_data.X)) .!= exp_.test_data.y))
ids = exp_.test_data.X[:,ids]
x_wrongly_labelled scatter!(plt, x_wrongly_labelled[1,:], x_wrongly_labelled[2,:], ms=7.5, color=:red, label="")
= vcat(plts..., plt)
plts end
end
= plot(plts..., layout=(length(choices),length(models)),size=(length(choices)*300,length(models)*300))
plt savefig(plt, joinpath(www_path,"models_test_before.png"))
using AlgorithmicRecourseDynamics.Models: model_evaluation
= []
plts for (exp_name, exp_) in experiments
for (M_name, M) in exp_.models
= round(model_evaluation(M, exp_.train_data),digits=2)
score = plot(M, exp_.train_data, title="$exp_name;\n $M_name ($score)")
plt # Errors:
= findall(vec(round.(probs(M, exp_.train_data.X)) .!= exp_.train_data.y))
ids = exp_.train_data.X[:,ids]
x_wrongly_labelled scatter!(plt, x_wrongly_labelled[1,:], x_wrongly_labelled[2,:], ms=7.5, color=:red, label="")
= vcat(plts..., plt)
plts end
end
= plot(plts..., layout=(length(choices),length(models)),size=(length(choices)*300,length(models)*300))
plt savefig(plt, joinpath(www_path,"models_train_before.png"))
= 5
n_evals = 50
n_rounds = Int(round(n_rounds/n_evals))
evaluate_every = 5
n_folds = 100
T = run_experiments(
results
experiments;=output_path,evaluate_every=evaluate_every,n_rounds=n_rounds, n_folds=n_folds, T=T
save_path
)Serialization.serialize(joinpath(output_path,"results.jls"),results)
= Dict(key => Dict() for (key,val) in results)
plot_dict = 1
fold for (name, res) in results
= res.experiment
exp_ = Dict(key => [] for (key,val) in exp_.generators)
plot_dict[name] = exp_.recourse_systems[fold]
rec_sys = collect(exp_.system_identifiers)
sys_ids = length(rec_sys)
M for m in 1:M
= sys_ids[m]
model_name, generator_name = rec_sys[m].model
M = round(model_evaluation(M, exp_.test_data),digits=2)
score = plot(M, exp_.test_data, title="$name;\n $model_name ($score)")
plt # Errors:
= findall(vec(round.(probs(M, exp_.test_data.X)) .!= exp_.test_data.y))
ids = exp_.test_data.X[:,ids]
x_wrongly_labelled scatter!(plt, x_wrongly_labelled[1,:], x_wrongly_labelled[2,:], ms=7.5, color=:red, label="")
= vcat(plot_dict[name][generator_name], plt)
plot_dict[name][generator_name] end
end
= Dict(key => reduce(vcat, [plots[key] for plots in values(plot_dict)]) for (key, value) in generators)
plot_dict for (name, plts) in plot_dict
= plot(plts..., layout=(length(choices),length(models)),size=(length(choices)*300,length(models)*300))
plt savefig(plt, joinpath(www_path,"models_test_after_$(name).png"))
end
using AlgorithmicRecourseDynamics.Models: model_evaluation
= Dict(key => Dict() for (key,val) in results)
plot_dict = 1
fold for (name, res) in results
= res.experiment
exp_ = Dict(key => [] for (key,val) in exp_.generators)
plot_dict[name] = exp_.recourse_systems[fold]
rec_sys = collect(exp_.system_identifiers)
sys_ids = length(rec_sys)
M for m in 1:M
= sys_ids[m]
model_name, generator_name = rec_sys[m].model
M = rec_sys[m].data
data = round(model_evaluation(M, data),digits=2)
score = plot(M, data, title="$name;\n $model_name ($score)")
plt # Errors:
= findall(vec(round.(probs(M, data.X)) .!= data.y))
ids = data.X[:,ids]
x_wrongly_labelled scatter!(plt, x_wrongly_labelled[1,:], x_wrongly_labelled[2,:], ms=7.5, color=:red, label="")
= vcat(plot_dict[name][generator_name], plt)
plot_dict[name][generator_name] end
end
= Dict(key => reduce(vcat, [plots[key] for plots in values(plot_dict)]) for (key, value) in generators)
plot_dict for (name, plts) in plot_dict
= plot(plts..., layout=(length(choices),length(models)),size=(length(choices)*300,length(models)*300))
plt savefig(plt, joinpath(www_path,"models_train_after_$(name).png"))
end
= load_synthetic_results() results
= DataFrame(group=["A", "B", "C"], total=[7.7, 4.6, 5.1], std_error = [0.04, 0.05, 0.06])
df bar(df.group, df.total, c=:blues, lw=0, widen=false)
plot!(1/2:(ncol(df)-1/2), df.total, lw=0, yerror=20*df.std_error, ms=10)
using Images
= Dict()
line_charts = Dict()
errorbar_charts for (data_name, res) in results
= plot_res(res)
plt save(joinpath(www_path, "line_chart_$(data_name).png"), plt)
Images.save(joinpath(www_paper_path, "line_chart_$(data_name).png"), plt)
Images.= plt
line_charts[data_name] = plot_res(res,maximum(res.output.n))
plt save(joinpath(www_path, "errorbar_chart_$(data_name).png"), plt)
Images.save(joinpath(www_paper_path, "errorbar_chart_$(data_name).png"), plt)
Images.= plt
errorbar_charts[data_name] end
The evolution of the evaluation metrics over the course of the experiment is shown for different datasets in Figure 3.1 to Figure 3.4.
The evaluation metrics at the end of the experiment are shown for different datasets in Figure 3.5 to Figure 3.8.
= 100
n_bootstrap = run_bootstrap(results, n_bootstrap; filename=joinpath(output_path,"bootstrap.csv")) df
Table 3.1 presents the tests for statistical significance of the estimated MMD metrics.
= EMAR.aggregate_bs_synthetic()
df write(joinpath(www_path, "bootstrap.csv"), df)
CSV.write(joinpath(www_paper_path, "bootstrap.csv"), df)
CSV.tabulate_bs(df, Val(:html)) EMAR.
Metric | Data | Generator | Model | p-value |
---|---|---|---|---|
MMD | Circles | DICE | Deep Ensemble | 0.988 |
MMD | Circles | DICE | Linear | 1.0 |
MMD | Circles | DICE | MLP | 0.99 |
MMD | Circles | Generic (γ=0.5) | Deep Ensemble | 0.996 |
MMD | Circles | Generic (γ=0.5) | Linear | 0.996 |
MMD | Circles | Generic (γ=0.5) | MLP | 0.99 |
MMD | Circles | Greedy | Deep Ensemble | 0.992 |
MMD | Circles | Greedy | Linear | 1.0 |
MMD | Circles | Greedy | MLP | 0.994 |
MMD | Circles | Latent | Deep Ensemble | 0.9975 |
MMD | Circles | Latent | Linear | 0.9925 |
MMD | Circles | Latent | MLP | 1.0 |
MMD | Linearly Separable | DICE | Deep Ensemble | 0.0 |
MMD | Linearly Separable | DICE | Linear | 0.0 |
MMD | Linearly Separable | DICE | MLP | 0.0 |
MMD | Linearly Separable | Generic (γ=0.5) | Deep Ensemble | 0.0 |
MMD | Linearly Separable | Generic (γ=0.5) | Linear | 0.0 |
MMD | Linearly Separable | Generic (γ=0.5) | MLP | 0.0 |
MMD | Linearly Separable | Greedy | Deep Ensemble | 0.0 |
MMD | Linearly Separable | Greedy | Linear | 0.0 |
MMD | Linearly Separable | Greedy | MLP | 0.0 |
MMD | Linearly Separable | Latent | Deep Ensemble | 0.748 |
MMD | Linearly Separable | Latent | Linear | 0.768 |
MMD | Linearly Separable | Latent | MLP | 0.69 |
MMD | Moons | DICE | Deep Ensemble | 0.0 |
MMD | Moons | DICE | Linear | 0.0 |
MMD | Moons | DICE | MLP | 0.0 |
MMD | Moons | Generic (γ=0.5) | Deep Ensemble | 0.0 |
MMD | Moons | Generic (γ=0.5) | Linear | 0.0 |
MMD | Moons | Generic (γ=0.5) | MLP | 0.0 |
MMD | Moons | Greedy | Deep Ensemble | 0.0 |
MMD | Moons | Greedy | Linear | 0.0 |
MMD | Moons | Greedy | MLP | 0.0 |
MMD | Moons | Latent | Deep Ensemble | 0.0 |
MMD | Moons | Latent | Linear | 0.0 |
MMD | Moons | Latent | MLP | 0.0 |
MMD | Overlapping | DICE | Deep Ensemble | 0.0 |
MMD | Overlapping | DICE | Linear | 0.0 |
MMD | Overlapping | DICE | MLP | 0.0 |
MMD | Overlapping | Generic (γ=0.5) | Deep Ensemble | 0.0 |
MMD | Overlapping | Generic (γ=0.5) | Linear | 0.0 |
MMD | Overlapping | Generic (γ=0.5) | MLP | 0.0 |
MMD | Overlapping | Greedy | Deep Ensemble | 0.0 |
MMD | Overlapping | Greedy | Linear | 0.0 |
MMD | Overlapping | Greedy | MLP | 0.0 |
MMD | Overlapping | Latent | Deep Ensemble | 0.0 |
MMD | Overlapping | Latent | Linear | 0.0 |
MMD | Overlapping | Latent | MLP | 0.0 |
PP MMD | Circles | DICE | Deep Ensemble | 0.996 |
PP MMD | Circles | DICE | Linear | 0.796 |
PP MMD | Circles | DICE | MLP | 0.9975 |
PP MMD | Circles | Generic (γ=0.5) | Deep Ensemble | 1.0 |
PP MMD | Circles | Generic (γ=0.5) | Linear | 0.996 |
PP MMD | Circles | Generic (γ=0.5) | MLP | 0.992 |
PP MMD | Circles | Greedy | Deep Ensemble | 1.0 |
PP MMD | Circles | Greedy | Linear | 0.0 |
PP MMD | Circles | Greedy | MLP | 0.996 |
PP MMD | Circles | Latent | Deep Ensemble | 0.9975 |
PP MMD | Circles | Latent | Linear | 0.0 |
PP MMD | Circles | Latent | MLP | 0.994 |
PP MMD | Linearly Separable | DICE | Deep Ensemble | 0.9525 |
PP MMD | Linearly Separable | DICE | Linear | 0.0 |
PP MMD | Linearly Separable | DICE | MLP | 0.964 |
PP MMD | Linearly Separable | Generic (γ=0.5) | Deep Ensemble | 0.958 |
PP MMD | Linearly Separable | Generic (γ=0.5) | Linear | 0.0 |
PP MMD | Linearly Separable | Generic (γ=0.5) | MLP | 0.944 |
PP MMD | Linearly Separable | Greedy | Deep Ensemble | 0.716 |
PP MMD | Linearly Separable | Greedy | Linear | 0.0 |
PP MMD | Linearly Separable | Greedy | MLP | 0.684 |
PP MMD | Linearly Separable | Latent | Deep Ensemble | 0.856 |
PP MMD | Linearly Separable | Latent | Linear | 0.46 |
PP MMD | Linearly Separable | Latent | MLP | 0.852 |
PP MMD | Moons | DICE | Deep Ensemble | 0.865 |
PP MMD | Moons | DICE | Linear | 0.0 |
PP MMD | Moons | DICE | MLP | 0.87 |
PP MMD | Moons | Generic (γ=0.5) | Deep Ensemble | 0.678 |
PP MMD | Moons | Generic (γ=0.5) | Linear | 0.0 |
PP MMD | Moons | Generic (γ=0.5) | MLP | 0.84 |
PP MMD | Moons | Greedy | Deep Ensemble | 0.388 |
PP MMD | Moons | Greedy | Linear | 0.0 |
PP MMD | Moons | Greedy | MLP | 0.346 |
PP MMD | Moons | Latent | Deep Ensemble | 0.902 |
PP MMD | Moons | Latent | Linear | 0.004 |
PP MMD | Moons | Latent | MLP | 0.91 |
PP MMD | Overlapping | DICE | Deep Ensemble | 0.0 |
PP MMD | Overlapping | DICE | Linear | 0.0 |
PP MMD | Overlapping | DICE | MLP | 0.002 |
PP MMD | Overlapping | Generic (γ=0.5) | Deep Ensemble | 0.004 |
PP MMD | Overlapping | Generic (γ=0.5) | Linear | 0.0 |
PP MMD | Overlapping | Generic (γ=0.5) | MLP | 0.002 |
PP MMD | Overlapping | Greedy | Deep Ensemble | 0.002 |
PP MMD | Overlapping | Greedy | Linear | 0.0 |
PP MMD | Overlapping | Greedy | MLP | 0.004 |
PP MMD | Overlapping | Latent | Deep Ensemble | 0.034 |
PP MMD | Overlapping | Latent | Linear | 0.012 |
PP MMD | Overlapping | Latent | MLP | 0.034 |
PP MMD (grid) | Circles | DICE | Deep Ensemble | 0.762 |
PP MMD (grid) | Circles | DICE | Linear | 0.814 |
PP MMD (grid) | Circles | DICE | MLP | 0.7375 |
PP MMD (grid) | Circles | Generic (γ=0.5) | Deep Ensemble | 0.89 |
PP MMD (grid) | Circles | Generic (γ=0.5) | Linear | 0.994 |
PP MMD (grid) | Circles | Generic (γ=0.5) | MLP | 0.688 |
PP MMD (grid) | Circles | Greedy | Deep Ensemble | 0.568 |
PP MMD (grid) | Circles | Greedy | Linear | 0.0 |
PP MMD (grid) | Circles | Greedy | MLP | 0.776 |
PP MMD (grid) | Circles | Latent | Deep Ensemble | 1.0 |
PP MMD (grid) | Circles | Latent | Linear | 0.0 |
PP MMD (grid) | Circles | Latent | MLP | 0.996 |
PP MMD (grid) | Linearly Separable | DICE | Deep Ensemble | 0.0 |
PP MMD (grid) | Linearly Separable | DICE | Linear | 0.0 |
PP MMD (grid) | Linearly Separable | DICE | MLP | 0.0 |
PP MMD (grid) | Linearly Separable | Generic (γ=0.5) | Deep Ensemble | 0.0 |
PP MMD (grid) | Linearly Separable | Generic (γ=0.5) | Linear | 0.0 |
PP MMD (grid) | Linearly Separable | Generic (γ=0.5) | MLP | 0.0 |
PP MMD (grid) | Linearly Separable | Greedy | Deep Ensemble | 0.0 |
PP MMD (grid) | Linearly Separable | Greedy | Linear | 0.0 |
PP MMD (grid) | Linearly Separable | Greedy | MLP | 0.0 |
PP MMD (grid) | Linearly Separable | Latent | Deep Ensemble | 0.0 |
PP MMD (grid) | Linearly Separable | Latent | Linear | 0.0 |
PP MMD (grid) | Linearly Separable | Latent | MLP | 0.0 |
PP MMD (grid) | Moons | DICE | Deep Ensemble | 0.1225 |
PP MMD (grid) | Moons | DICE | Linear | 0.0 |
PP MMD (grid) | Moons | DICE | MLP | 0.01 |
PP MMD (grid) | Moons | Generic (γ=0.5) | Deep Ensemble | 0.016 |
PP MMD (grid) | Moons | Generic (γ=0.5) | Linear | 0.0 |
PP MMD (grid) | Moons | Generic (γ=0.5) | MLP | 0.02 |
PP MMD (grid) | Moons | Greedy | Deep Ensemble | 0.006 |
PP MMD (grid) | Moons | Greedy | Linear | 0.0 |
PP MMD (grid) | Moons | Greedy | MLP | 0.0 |
PP MMD (grid) | Moons | Latent | Deep Ensemble | 0.114 |
PP MMD (grid) | Moons | Latent | Linear | 0.004 |
PP MMD (grid) | Moons | Latent | MLP | 0.174 |
PP MMD (grid) | Overlapping | DICE | Deep Ensemble | 0.002 |
PP MMD (grid) | Overlapping | DICE | Linear | 0.0 |
PP MMD (grid) | Overlapping | DICE | MLP | 0.0 |
PP MMD (grid) | Overlapping | Generic (γ=0.5) | Deep Ensemble | 0.0 |
PP MMD (grid) | Overlapping | Generic (γ=0.5) | Linear | 0.0 |
PP MMD (grid) | Overlapping | Generic (γ=0.5) | MLP | 0.0 |
PP MMD (grid) | Overlapping | Greedy | Deep Ensemble | 0.0 |
PP MMD (grid) | Overlapping | Greedy | Linear | 0.0 |
PP MMD (grid) | Overlapping | Greedy | MLP | 0.002 |
PP MMD (grid) | Overlapping | Latent | Deep Ensemble | 0.208 |
PP MMD (grid) | Overlapping | Latent | Linear | 0.02 |
PP MMD (grid) | Overlapping | Latent | MLP | 0.342 |
Figure 3.9 shows the chart that went into the paper.
load(joinpath(www_artifact_path,"paper_synthetic_results.png")) Images.
# echo: false
generate_artifacts(output_path)
generate_artifacts(www_path)