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.