Skip to content

Commit 5113df7

Browse files
authored
Merge pull request #62 from pat-alt/original-paper
Original paper
2 parents a355d41 + dcd7181 commit 5113df7

132 files changed

Lines changed: 39593 additions & 22003 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/CI.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ jobs:
2020
version:
2121
- '1.6'
2222
- '1.7'
23+
- '1.8'
2324
- 'nightly'
2425
os:
2526
- ubuntu-latest

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,16 @@ docs/site/
2828
# committed for packages, but should be committed for applications that require a static
2929
# environment.
3030
Manifest.toml
31+
# ignore Artifacts.toml due to double-blind:
32+
Artifacts.toml
3133

3234
/.quarto/
3335

3436
/dev/artifacts/upload
3537
/dev/python
3638
.DS_Store
3739
.Rproj.user
40+
41+
.luarc.json
42+
43+
/.luarc.json

Artifacts.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
[".DS_Store"]
2-
git-tree-sha1 = "d2fe43d5d50dd19de3c047c6b8be8256c79b7f6d"
2+
git-tree-sha1 = "b700008b7e45ef6e33455876df46047d9db5080f"
33
lazy = true
44

55
[[".DS_Store".download]]
6-
sha256 = "80caa50f9515c0ede96213ccfaf91fe77bb92e9a509541265410515f180a59f3"
6+
sha256 = "adbcc22b0124d0f87d2f00d0af6c49f91c579cb00262605d46c64526c422b369"
77
url = "https://github.com/pat-alt/AlgorithmicRecourseDynamics.jl/releases/download/artifacts/.DS_Store.tar.gz"
88

99
[data]
1010
git-tree-sha1 = "19e4434c5cec37c302c4fb8a6058b1a685a436ba"
1111
lazy = true
1212

1313
[[data.download]]
14-
sha256 = "a707dbee173dfae97387a0ef0cdf628992987bcd65c47a7e9116f8de9909e869"
14+
sha256 = "eedef8395f29d70eb942f85e5ff4c8a3b2cfe9749aaec36c0c631666b1746b9b"
1515
url = "https://github.com/pat-alt/AlgorithmicRecourseDynamics.jl/releases/download/artifacts/data.tar.gz"
1616

1717
[output]
18-
git-tree-sha1 = "b7827b37cb256c6ed6a5168b235b814b934d91fd"
18+
git-tree-sha1 = "ac2d6dbcc081bc5b7a4c323c1a2176e7768a5080"
1919
lazy = true
2020

2121
[[output.download]]
22-
sha256 = "b000d10d55a9e6a83ca941a77c39e433ea1a77e688813dfb91d5eb0874cff31b"
22+
sha256 = "0c226b114a1f67a065332d16c224e488ec35149f169a278afac2355ba7dac87d"
2323
url = "https://github.com/pat-alt/AlgorithmicRecourseDynamics.jl/releases/download/artifacts/output.tar.gz"
2424

2525
[www]
26-
git-tree-sha1 = "9a77a16ed5ef3cc433f8ea914fd3b4272f0788ff"
26+
git-tree-sha1 = "a156f4aeffd1921c2ba088d6b3ebdbb9bc9cf2ec"
2727
lazy = true
2828

2929
[[www.download]]
30-
sha256 = "0b0eb2ab3c946b96b93f90d9e8c3104d3c6cf3d88f2ee344d4656fd693d4dced"
30+
sha256 = "8b2f9eb919fa7690fdc31c042419c9b04313edc0616444328b3dcf3243a767e3"
3131
url = "https://github.com/pat-alt/AlgorithmicRecourseDynamics.jl/releases/download/artifacts/www.tar.gz"

Project.toml

100755100644
Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,46 @@
11
name = "AlgorithmicRecourseDynamics"
22
uuid = "3d1ede72-abb8-4340-bf8e-2ae06849b5ec"
3-
authors = ["Anonymous"]
3+
authors = ["Patrick Altmeyer"]
44
version = "0.1.0"
55

66
[deps]
77
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
88
CounterfactualExplanations = "2f13d31b-18db-44c1-bc43-ebaf2cff0be0"
99
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
1010
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
11-
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
1211
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
1312
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
1413
KernelFunctions = "ec8451be-7e33-11e9-00cf-bbf324bd1392"
15-
LaplaceRedux = "c52c1a26-f7c5-402b-80be-ba1e638ad478"
14+
LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
1615
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1716
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
18-
MLJ = "add582a8-e3ab-11e8-2d5e-e98b27df1bc7"
17+
MLJBase = "a7f614a8-145f-11e9-1d2a-a57a1082229d"
1918
MLUtils = "f1d291b0-491e-4a28-83b9-f70985020b54"
2019
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
21-
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
22-
PlotThemes = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
2320
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
2421
ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca"
2522
RCall = "6f49c342-dc21-5d91-9882-a32aef131414"
2623
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
2724
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
2825
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
2926
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
30-
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
3127

3228
[compat]
29+
CounterfactualExplanations = "0.1.4"
3330
CSV = "0.10"
34-
CounterfactualExplanations = "0.1"
3531
DataFrames = "1"
3632
Distances = "0.10"
37-
FileIO = "1"
3833
Flux = "0.13"
3934
Images = "0.25"
4035
KernelFunctions = "0.10"
41-
LaplaceRedux = "0.1"
42-
MLJ = "0.18, 0.19"
43-
MLUtils = "0.2, 0.3"
36+
MLJBase = "0.21.3"
37+
MLUtils = "0.3.1"
4438
Parameters = "0.12"
45-
PlotThemes = "3"
46-
Plots = "1"
39+
Plots = "1.37.2"
4740
ProgressMeter = "1"
48-
RCall = "0.13"
41+
RCall = "0.13.14"
4942
StatsBase = "0.33"
50-
Zygote = "0.6"
51-
julia = "1.6"
43+
julia = "1.6, 1.7, 1.8"
5244

5345
[extras]
5446
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

README.md

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,63 @@
11

2+
[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://pat-alt.github.io/AlgorithmicRecourseDynamics.jl/stable) [![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://pat-alt.github.io/AlgorithmicRecourseDynamics.jl/dev) [![Build Status](https://github.com/pat-alt/AlgorithmicRecourseDynamics.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/pat-alt/AlgorithmicRecourseDynamics.jl/actions/workflows/CI.yml?query=branch%3Amain) [![Coverage](https://codecov.io/gh/pat-alt/AlgorithmicRecourseDynamics.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/pat-alt/AlgorithmicRecourseDynamics.jl) [![Code Style: Blue](https://img.shields.io/badge/code%20style-blue-4495d1.svg)](https://github.com/invenia/BlueStyle) [![ColPrac: Contributor’s Guide on Collaborative Practices for Community Packages](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet.png)](https://github.com/SciML/ColPrac) [![Twitter Badge](https://img.shields.io/twitter/url/https/twitter.com/paltmey.svg?style=social&label=Follow%20%40paltmey)](https://twitter.com/paltmey)
3+
24
# AlgorithmicRecourseDynamics
35

4-
<!-- [![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://pat-alt.github.io/CounterfactualExplanations.jl/stable) -->
5-
<!-- [![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://pat-alt.github.io/CounterfactualExplanations.jl/dev) -->
6+
`AlgorithmicRecourseDynamics.jl` is a small package for modeling Algorithmic Recourse Dynamics. It builds on `CounterfactualExplanations`, a package for generating counterfactual explanations.
7+
8+
## Basic Usage
9+
10+
### Data and Model
11+
12+
``` julia
13+
N = 1000
14+
xmax = 2
15+
X, ys = make_blobs(
16+
N, 2;
17+
centers=2, as_table=false, center_box=(-xmax => xmax), cluster_std=0.1
18+
)
19+
ys .= ys.==2
20+
X = X'
21+
counterfactual_data = CounterfactualData(X,ys')
22+
```
623

7-
[![Build Status](https://github.com/pat-alt/CounterfactualExplanations.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/pat-alt/CounterfactualExplanations.jl/actions/workflows/CI.yml?query=branch%3Amain) <!-- [![Coverage](https://codecov.io/gh/pat-alt/CounterfactualExplanations.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/pat-alt/CounterfactualExplanations.jl) -->
24+
``` julia
25+
n_epochs = 100
26+
model = Chain(Dense(2,1))
27+
mod = FluxModel(model)
828

9-
`AlgorithmicRecourseDynamics.jl` is a Julia package for modelling Algorithmic Recourse Dynamics.
29+
generator = GenericGenerator()
30+
```
1031

11-
## Research Paper 📝
32+
``` julia
33+
data_train, data_test = Data.train_test_split(counterfactual_data)
34+
Models.train(mod, data_train; n_epochs=n_epochs)
35+
plt_original = plot(mod, counterfactual_data; zoom=0, colorbar=false)
36+
display(plt_original)
37+
```
1238

13-
**Note** ⚠: You are on the `#original-paper` branch of `AlgorithmicRecourseDynamics.jl`. This branch is a static artifact corresponding to the state of the package at the time the paper was first published. It can be used to replicate the original findings of the paper. For an up-to-date version of the package, please switch to the [`#main`](https://github.com/pat-alt/AlgorithmicRecourseDynamics.jl) branch.
39+
![](README_files/figure-commonmark/cell-5-output-1.svg)
1440

15-
## At a Glance
41+
### Simulation
1642

17-
The paper titles **Endogenous Macrodynamics in Algorithmic Recourse** is currently under review and not yet published. You can find a preprint along with other resources right here on this branch of the repository:
43+
``` julia
44+
models = Dict(:mymodel => mod)
45+
generators = Dict(:wachter => generator)
46+
experiment = set_up_experiment(data_train, data_test, models, generators)
47+
```
1848

19-
- [Paper](paper/paper.pdf)
20-
- [Notebooks](dev/notebooks/)
21-
- [Supplementary Appendix](build/dev/notebooks/appendix.html) (download the HTML and view in browser)
22-
- [Artifacts](https://github.com/pat-alt/AlgorithmicRecourseDynamics.jl/releases/tag/artifacts) (including data and experimental results)
49+
``` julia
50+
run!(experiment)
51+
```
2352

24-
In this work we investigate what happens if Algorithmic Recourse is actually implemented by a large number of individuals. The chart below illustrates what we mean by Endogenous Macrodynamics in Algorithmic Recourse: (a) we have a simple linear classifier trained for binary classification where samples from the negative class ($y=0$) are marked in blue and samples of the positive class ($y=1$) are marked in orange; (b) the implementation of AR for a random subset of individuals leads to a noticable domain shift; (c) as the classifier is retrained we observe a corresponding model shift; (d) as this process is repeated, the decision boundary moves away from the target class.
53+
``` julia
54+
new_data = experiment.recourse_systems[1][1].data
55+
new_model = experiment.recourse_systems[1][1].model
56+
plt_original = plot(new_model, new_data; zoom=0, colorbar=false)
57+
```
2558

26-
![](paper/www/poc.png)
59+
![](README_files/figure-commonmark/cell-8-output-1.svg)
2760

28-
## Paper Abstract
61+
## Related Research Paper 📝
2962

30-
Existing work on Counterfactual Explanations (CE) and Algorithmic Recourse (AR) has largely been limited to the static setting and focused on single individuals: given some estimated model the goal is to find valid counterfactuals for individual instance that fulfill various desiderata. The ability of such counterfactuals to handle dynamics like data and model drift remains a largely unexplored research challenge at this point. There has also been surprisingly little work on the related question of how the actual implementation of recourse by one individual may affect other individuals. Through this work we aim to close that gap by systematizing and extending existing knowledge. We first show that many of the existing methodologies can be collectively described by a generalized framework. We then argue that the existing framework fails to account for a hidden external cost of recourse, that only reveals itself when studying the endogenous dynamics of recourse at the group level. Through simulation experiments involving various state-of-the-art counterfactual generators and several benchmark datasets, we generate large numbers of counterfactuals and study the resulting domain and model shifts. We find that the induced shifts are substantial enough to likely impede the applicability Algorithmic Recourse in situations that involve competition for scarce resources. Fortunately, we find various potential mitigation strategies that can be used in combination with existing approaches. Our simulation framework for studying recourse dynamics is fast and open-sourced.
63+
The package was developed for a research project that investigates the dynamics of various counterfactual generators.

README.qmd

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,28 @@
11
---
22
format:
3-
gfm:
4-
wrap: none
3+
commonmark:
4+
variant: -raw_html
5+
wrap: none
6+
execute:
7+
freeze: auto
8+
echo: true
9+
eval: true
10+
output: false
11+
crossref:
12+
fig-prefix: Figure
13+
tbl-prefix: Table
14+
bibliography: bib.bib
15+
jupyter: julia-1.8
516
---
617

7-
# AlgorithmicRecourseDynamics
8-
9-
<!-- [![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://pat-alt.github.io/CounterfactualExplanations.jl/stable) -->
10-
<!-- [![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://pat-alt.github.io/CounterfactualExplanations.jl/dev) -->
11-
[![Build Status](https://github.com/pat-alt/CounterfactualExplanations.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/pat-alt/CounterfactualExplanations.jl/actions/workflows/CI.yml?query=branch%3Amain)
12-
<!-- [![Coverage](https://codecov.io/gh/pat-alt/CounterfactualExplanations.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/pat-alt/CounterfactualExplanations.jl) -->
13-
14-
`AlgorithmicRecourseDynamics.jl` is a Julia package for modelling Algorithmic Recourse Dynamics.
15-
16-
## Research Paper 📝
17-
18-
**Note** ⚠: You are on the `#original-paper` branch of `AlgorithmicRecourseDynamics.jl`. This branch is a static artifact corresponding to the state of the package at the time the paper was first published. It can be used to replicate the original findings of the paper. For an up-to-date version of the package, please switch to the [`#main`](https://github.com/pat-alt/AlgorithmicRecourseDynamics.jl) branch.
19-
20-
## At a Glance
18+
[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://pat-alt.github.io/AlgorithmicRecourseDynamics.jl/stable)
19+
[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://pat-alt.github.io/AlgorithmicRecourseDynamics.jl/dev)
20+
[![Build Status](https://github.com/pat-alt/AlgorithmicRecourseDynamics.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/pat-alt/AlgorithmicRecourseDynamics.jl/actions/workflows/CI.yml?query=branch%3Amain)
21+
[![Coverage](https://codecov.io/gh/pat-alt/AlgorithmicRecourseDynamics.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/pat-alt/AlgorithmicRecourseDynamics.jl)
22+
[![Code Style: Blue](https://img.shields.io/badge/code%20style-blue-4495d1.svg)](https://github.com/invenia/BlueStyle)
23+
[![ColPrac: Contributor’s Guide on Collaborative Practices for Community Packages](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet.png)](https://github.com/SciML/ColPrac)
24+
[![Twitter Badge](https://img.shields.io/twitter/url/https/twitter.com/paltmey.svg?style=social&label=Follow%20%40paltmey)](https://twitter.com/paltmey)
2125

22-
The paper titles **Endogenous Macrodynamics in Algorithmic Recourse** is currently under review and not yet published. You can find
23-
a preprint along with other resources right here on this branch of the
24-
repository:
25-
26-
- [Paper](paper/paper.pdf)
27-
- [Notebooks](dev/notebooks/)
28-
- [Supplementary Appendix](build/dev/notebooks/appendix.html) (download the HTML and view in browser)
29-
- [Artifacts](https://github.com/pat-alt/AlgorithmicRecourseDynamics.jl/releases/tag/artifacts) (including data and experimental results)
30-
31-
In this work we investigate what happens if Algorithmic Recourse is actually implemented by a large number of individuals. The chart below illustrates what we mean by Endogenous Macrodynamics in Algorithmic Recourse: (a) we have a simple linear classifier trained for binary classification where samples from the negative class ($y=0$) are marked in blue and samples of the positive class ($y=1$) are marked in orange; (b) the implementation of AR for a random subset of individuals leads to a noticable domain shift; (c) as the classifier is retrained we observe a corresponding model shift; (d) as this process is repeated, the decision boundary moves away from the target class.
32-
33-
![](paper/www/poc.png)
34-
35-
## Paper Abstract
36-
37-
Existing work on Counterfactual Explanations (CE) and Algorithmic Recourse (AR) has largely been limited to the static setting and focused on single individuals: given some estimated model the goal is to find valid counterfactuals for individual instance that fulfill various desiderata. The ability of such counterfactuals to handle dynamics like data and model drift remains a largely unexplored research challenge at this point. There has also been surprisingly little work on the related question of how the actual implementation of recourse by one individual may affect other individuals. Through this work we aim to close that gap by systematizing and extending existing knowledge. We first show that many of the existing methodologies can be collectively described by a generalized framework. We then argue that the existing framework fails to account for a hidden external cost of recourse, that only reveals itself when studying the endogenous dynamics of recourse at the group level. Through simulation experiments involving various state-of-the-art counterfactual generators and several benchmark datasets, we generate large numbers of counterfactuals and study the resulting domain and model shifts. We find that the induced shifts are substantial enough to likely impede the applicability Algorithmic Recourse in situations that involve competition for scarce resources. Fortunately, we find various potential mitigation strategies that can be used in combination with existing approaches. Our simulation framework for studying recourse dynamics is fast and open-sourced.
26+
# AlgorithmicRecourseDynamics
3827

28+
{{< include docs/src/_intro.qmd >}}

0 commit comments

Comments
 (0)