Skip to content

Commit 321e317

Browse files
committed
bleh
1 parent 3ef0eac commit 321e317

24 files changed

Lines changed: 26910 additions & 4934 deletions
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"hash": "6255089458dd9adc1ef9096613618d20",
3+
"result": {
4+
"markdown": "---\ntitle: Endogenous Macrodynamics in Algorithmic Recourse\nsubtitle: Research Paper\n--- \n\n```@meta\nCurrentModule = ConformalPrediction\n```\n\nThis part of the documentation is specific to the research paper \"Endogenous Macrodynamics in Algorithmic Recourse\". To allow for reproducibility of the results at the time of publication, there is a specific package environment linked to this part of the documentation that **will not be updated**. It can be activated as follows:\n\n::: {.cell execution_count=1}\n``` {.julia .cell-code}\nusing Pkg; Pkg.activate(\"docs/src/paper\")\n```\n:::\n\n\nThe status of this package environment is shown below:\n\n::: {.cell execution_count=2}\n``` {.julia .cell-code}\nPkg.status()\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nStatus `~/code/AlgorithmicRecourseDynamics.jl/docs/src/paper/Project.toml`\n [3d1ede72] AlgorithmicRecourseDynamics v0.1.0 `../../..`\n [2f13d31b] CounterfactualExplanations v0.1.4 `../../../../CounterfactualExplanations.jl`\n [587475ba] Flux v0.13.9\n [c52c1a26] LaplaceRedux v0.1.2\n [a7f614a8] MLJBase v0.21.3\n⌃ [91a5bcdd] Plots v1.37.2\n [9a3f8284] Random\nInfo Packages marked with ⌃ have new versions available\n```\n:::\n:::\n\n\n",
5+
"supporting": [
6+
"index_files"
7+
],
8+
"filters": []
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"hash": "c3200f1d0ba6b217054a06220d9683c3",
3+
"result": {
4+
"markdown": "---\ntitle: Proof of concept\n---\n\n\n\nTo start with, we will look at a proof-of-concept that demonstrates the main observation underlying that paper is framed around. In particular, we will use synthetic data to see how endogenous domain shifts and the resulting model shifts can have implications on the validity and cost of algorithmic recourse.\n\n## Data\n\nWe begin by generating the synthetic data for a simple binary classification problem. For illustrative purposes we will use data that is linearly separable. The chart below shows the data $\\mathcal{D}$ at time zero, before any implementation of recourse.\n\n::: {.cell execution_count=2}\n``` {.julia .cell-code}\nN = 1000\nxmax = 2\nX, ys = make_blobs(\n N, 2; \n centers=2, as_table=false, center_box=(-xmax => xmax), cluster_std=0.1\n)\nys .= ys.==2\nX = X'\nxs = Flux.unstack(X,2)\ndata = zip(xs,ys)\ncounterfactual_data = CounterfactualData(X,ys')\nplot()\nscatter!(counterfactual_data)\n```\n\n::: {.cell-output .cell-output-display execution_count=3}\n![Linearly separable synthetic data](proof_of_concept_files/figure-commonmark/fig-data-output-1.svg){#fig-data}\n:::\n:::\n\n\n## Classifier \n\nTo model this data $\\mathcal{D}$ we will use a linear classifier. In particular, as in the paper, we will build a logistic regression model in `Flux.jl`: a single layer with sigmoid activation. \n\n::: {.cell execution_count=3}\n``` {.julia .cell-code}\nn_epochs = 100\nmodel = Chain(Dense(2,1))\nmod = FluxModel(model)\nModels.train(mod, counterfactual_data; n_epochs=n_epochs)\n```\n:::\n\n\nThe chart (a) below shows the linear separation of the two classes.\n\n::: {.cell execution_count=4}\n``` {.julia .cell-code}\nplt_original = plot(mod, counterfactual_data; zoom=0, colorbar=false, title=\"(a)\")\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n![The baseline model: contours indicate the predicted label; dots indicate observed data points.](proof_of_concept_files/figure-commonmark/fig-model-output-1.svg){#fig-model}\n:::\n:::\n\n\n## Implementation of Recourse\n\n### Generate counterfactual\n\n::: {.cell execution_count=5}\n``` {.julia .cell-code}\nγ = 0.50\nμ = 0.10\nMarkdown.parse(\n \"\"\"\n To generate counterfactual explanations we will rely on the most generic approach. As our decision threshold we will use $(γ*100)% here. In other words, the counterfactual is considered as valid, as soon as the classifier is more convinced that it belongs to the target class (blue) than the non-target class (orange). In each round we will implement recourse for $(μ * 100)% of the individuals in the non-target class. \n \"\"\"\n)\n```\n:::\n\n\n::: {.cell execution_count=6}\n``` {.julia .cell-code}\nopt = Flux.Adam(0.01)\ngen = GenericGenerator(;decision_threshold=γ, opt=opt)\n```\n:::\n\n\nThe chart (b) below shows the recourse outcome, which we denote here as $\\mathcal{D}^{\\prime}$. The obvious observation at this point is that the resulting counterfactuals, while valid, are clearly distinguishable from the factuals that were always in the target class. This is not a new observation and nor is it entirely surprising. In fact, a lot of recent work in this field has tried to address this issue. In this work we wonder what happens when we let these sorts of dynamics play out further in practice. While the outcome in (b) is not surprising, it may be much harder to observe so clearly it in practice (when the data is more complex).\n\n::: {.cell execution_count=7}\n``` {.julia .cell-code}\ncandidates = findall(ys.==0)\nchosen_individuals = rand(candidates, Int(round(μ*length(candidates))))\nX′ = copy(X)\ny′ = copy(ys)\nusing CounterfactualExplanations.Counterfactuals: counterfactual, counterfactual_label\nfactuals = select_factual(counterfactual_data,chosen_individuals)\noutcome = generate_counterfactual(factuals, 1, counterfactual_data, mod, gen; initialization=:identity)\nX′[:,chosen_individuals] = reduce(hcat, @.(selectdim(counterfactual(outcome), 3, 1)))\ny′[chosen_individuals] = reduce(vcat,@.(selectdim(counterfactual_label(outcome),3,1)))\ncounterfactual_data′ = CounterfactualData(X′,y′')\nplt_single = plot(mod,counterfactual_data′;zoom=0,colorbar=false,title=\"(b)\")\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n![The recourse outcome after one round.](proof_of_concept_files/figure-commonmark/fig-round-1-output-1.svg){#fig-round-1}\n:::\n:::\n\n\n### Retrain\n\nSuppose the agent in charge of the black-box system has provided recourse to a share of individuals leading to the outcome in chart (b). In practice, models are regularly updated through retraining to account for concept drift, for example. For our experiments, we assume that the agent accepts $\\mathcal{D}^{\\prime}$ as its new ground truth. To isolate the endogenous effects we are interested in here from any other effect, we further assume away any exogenous changes to the data that we might expect to occur in practice. Retraining the model on $\\mathcal{D}^{\\prime}$ leads to a shift of the decision boundary **in the direction of the non-target class**. \n\n::: {.cell execution_count=8}\n``` {.julia .cell-code}\nmod = Models.train(mod, counterfactual_data′)\nplt_single_retrained = plot(mod,counterfactual_data′;zoom=0,colorbar=false,title=\"(c)\")\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n![The retrained model.](proof_of_concept_files/figure-commonmark/fig-retrain-output-1.svg){#fig-retrain}\n:::\n:::\n\n\n### Repeat\n\nWe finally go on to repeat this process of recourse followed by model updates for multiple round. The chart below presents the different stages of the experiment side-by-side, where panel (d) represents the outcome after ten rounds. \n\nAt first glance it seems that costs to individuals seeking recourse are gradually reduced as the decision boundary moves into the direction of the non-target class: they need to exert less effort to move to valid counterfactual states. The problem with this idea is, of course, that there is no free lunch. This reduction inflicts a burden on the agent in charge of the black-box: the group of individuals that is now classified as target class individuals looks entirely different from the original group. \n\nWhy is this a problem? Let's, for example, that the two synthetic features accurately describe the credit worthiness of individual seeking loans, where credit-worthiness increases in the South-West direction. Non-target class individuals (orange) are denied credit, while target class individuals (blue) receive a loan. Then the population of borrowers in (d) is much more risky than in (a). Clearly, any lender (bank) aware of such dynamics would avoid them in practice. They might choose not to offer recourse in the first place, generating a cost to all individuals seeking recourse. Alternatively, they may reward first movers, but stop offering recourse after a few rounds. \n\nThis last point makes it clear that the implementation of recourse by one individual may generate external costs for other individuals. This notion motivates the ideas set out in the paper.\n\n::: {.cell execution_count=9}\n``` {.julia .cell-code}\ni = 2\nwhile i <= 10\n counterfactual_data′ = CounterfactualData(X′,y′')\n candidates = findall(y′.==0)\n chosen_individuals = rand(candidates, Int(round(μ*length(candidates))))\n Models.train(mod, counterfactual_data′)\n factuals = select_factual(counterfactual_data′,chosen_individuals)\n outcome = generate_counterfactual(factuals, 1, counterfactual_data′, mod, gen; initialization=:identity)\n X′[:,chosen_individuals] = reduce(hcat, @.(selectdim(counterfactual(outcome), 3, 1)))\n y′[chosen_individuals] = reduce(vcat,@.(selectdim(counterfactual_label(outcome),3,1)))\n i += 1\nend\nplt_single_repeat = plot(mod,counterfactual_data′;zoom=0,colorbar=false,title=\"(d)\")\n```\n:::\n\n\n::: {.cell execution_count=10}\n``` {.julia .cell-code}\nplt = plot(plt_original, plt_single, plt_single_retrained, plt_single_repeat, layout=(1,4), legend=false, axis=nothing, size=(600,165))\nsavefig(plt, joinpath(www_path, \"poc.png\"))\nplt\n```\n\n::: {.cell-output .cell-output-display execution_count=11}\n![The different stages of the experiment.](proof_of_concept_files/figure-commonmark/fig-final-output-1.svg){#fig-final}\n:::\n:::\n\n\n",
5+
"supporting": [
6+
"proof_of_concept_files"
7+
],
8+
"filters": []
9+
}
10+
}

_freeze/docs/src/paper/proof_of_concept/figure-commonmark/fig-data-output-1.svg

Lines changed: 1122 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)