ProCreations's picture
Publish validated ICML reproduction
4adaccc verified
|
Raw
History Blame Contribute Delete
6.11 kB

Optimal Regularization for Performative Learning

This repository contains code for the experiments in:

Optimal Regularization for Performative Learning
Edwige Cyffers, Alireza Mirrokni, Marco Mondelli
International Conference on Machine Learning (ICML), 2026

The main repository contains the original experiments for the paper. The folder neural_network_credit/ contains the additional neural-network experiment on the GiveMeSomeCredit strategic-classification environment used for the rebuttal-stage figure metric_vs_lambda_final_acc.pdf.

Citation

@inproceedings{cyffers2026optimal,
  title     = {Optimal Regularization for Performative Learning},
  author    = {Cyffers, Edwige and Mirrokni, Alireza and Mondelli, Marco},
  booktitle = {Proceedings of the 43rd International Conference on Machine Learning},
  year      = {2026}
}

Repository structure

.
β”œβ”€β”€ proportional/                 # Synthetic Proportional setting
β”œβ”€β”€ real/                         # Real-data experiments
β”œβ”€β”€ out/                          # Generated outputs, not tracked
β”œβ”€β”€ neural_network_credit/        # Neural-network experiment
β”‚   β”œβ”€β”€ sweep_l2_for_delta.py
β”‚   β”œβ”€β”€ plot_metric_vs_lambda.py
β”‚   β”œβ”€β”€ ppnn_experiments.py
β”‚   └── scripts/
β”‚       └── utils_torch.py
β”œβ”€β”€ requirements-nn-credit.txt    # Legacy dependencies for neural_network_credit only
β”œβ”€β”€ pyproject.toml                # Main repository environment
└── README.md

Generated results and figures should be written under out/ and should not be committed.

Main environment

The main experiments use the repository-level pyproject.toml and uv.lock. For the existing code, use the main environment, for example:

uv sync

The neural-network credit experiment should not be run in this environment. The reason is that the main environment uses a up-to-date Python stack, including NumPy 2, whereas whynot is an old package and depends on the old gym==0.21.0 stack.

Neural-network credit experiment

Description

The neural-network experiment follows the strategic-classification setting of Mofakhami, Mitliagkas, and Gidel, Performative Prediction with Neural Networks (AISTATS 2023). It uses the GiveMeSomeCredit environment through the whynot package. The performative shift is controlled by a parameter delta: after a negative classification under the previous model, an individual may strategically modify the manipulable features by copying the corresponding features of another data point, with probability depending on delta.

For each value of delta, the code sweeps over the L2 regularization parameter lambda, runs repeated risk minimization for a fixed number of deployments, and reports the final test accuracy. The qualitative behavior reported in the paper is that L2 regularization mitigates the accuracy drop caused by the performative shift, and that the best regularization level increases with the strength of the performative effect.

Files

neural_network_credit/
β”œβ”€β”€ sweep_l2_for_delta.py      # Runs one delta value across a grid of lambdas
β”œβ”€β”€ plot_metric_vs_lambda.py   # Builds the final lambda-sweep figure from .pkl outputs
β”œβ”€β”€ ppnn_experiments.py        # Experiment logic, strategic shift, plotting helpers
└── scripts/
    └── utils_torch.py         # Torch models and training/loss utilities

Legacy environment for whynot

The whynot dependency is the fragile part. Use a separate Python 3.9 environment and keep packaging tools old enough for gym==0.21.0.

Recommended setup:

python3.9 -m venv .venv-nn-credit
source .venv-nn-credit/bin/activate
python -m pip install --upgrade "pip==23.2.1" "setuptools==65.5.0" "wheel==0.38.4"
python -m pip install -r requirements-nn-credit.txt

Check that the credit environment imports correctly:

python - <<'PY'
import whynot.gym as gym
import torch

env = gym.make("Credit-v0")
data = env.initial_state.values()
print(data["features"].shape, data["labels"].shape)
print(torch.__version__)
PY

Run the sweeps

The paper figure used the following grid:

n_runs        = 2
num_iters     = 3
layers        = 2
learning_rate = 3e-4
test_frac     = 0.9
delta_grid    = [0.1, 0.3, 0.5, 0.7, 0.9]
l2_grid       = [0, 1e-5, 3e-5, 1e-4, 3e-4, 1e-3, 3e-3, 1e-2]
seeds         = 0, 1

Run all five sweeps from the repository root:

mkdir -p out/nn_credit

L2_GRID="0 1e-5 3e-5 1e-4 3e-4 1e-3 3e-3 1e-2"

for DELTA in 0.1 0.3 0.5 0.7 0.9; do
  python neural_network_credit/sweep_l2_for_delta.py \
    --out "out/nn_credit/delta_${DELTA}.pkl" \
    --delta "$DELTA" \
    --n-runs 2 \
    --num-iters 3 \
    --layers 2 \
    --learning-rate 3e-4 \
    --test-frac 0.9 \
    --l2-grid $L2_GRID
done

This creates:

out/nn_credit/delta_0.1.pkl
out/nn_credit/delta_0.3.pkl
out/nn_credit/delta_0.5.pkl
out/nn_credit/delta_0.7.pkl
out/nn_credit/delta_0.9.pkl

Plot the figure

From the repository root:

python neural_network_credit/plot_metric_vs_lambda.py \
  out/nn_credit/delta_0.1.pkl \
  out/nn_credit/delta_0.3.pkl \
  out/nn_credit/delta_0.5.pkl \
  out/nn_credit/delta_0.7.pkl \
  out/nn_credit/delta_0.9.pkl \
  --out-prefix out/nn_credit/metric_vs_lambda_final

This writes:

out/nn_credit/metric_vs_lambda_final_acc.pdf
out/nn_credit/metric_vs_lambda_final_loss.pdf

The paper uses only:

out/nn_credit/metric_vs_lambda_final_acc.pdf

Relationship with Mofakhami et al. (AISTATS 2023)

The implementation builds on the public code accompanying Mofakhami, Mitliagkas, and Gidel, Performative Prediction with Neural Networks. The retained files are only the parts needed for the L2-regularization sweep and the final neural-network figure. Exploratory notebooks, old result folders, local virtual environments, Python caches, copied simulator files that are not imported by these scripts, and all stored outputs were intentionally omitted.