Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
67b25cd
Update CN sampling and use of `pytest`
Niccolo-Rocchi Nov 5, 2025
b4db6c4
Minor fixes
Niccolo-Rocchi Nov 6, 2025
2739a65
Update tests: less heavy
Niccolo-Rocchi Nov 6, 2025
871421d
Minor fixes
Niccolo-Rocchi Nov 6, 2025
9ab12f1
Merge pull request #6 from Niccolo-Rocchi/5-privacy-vs-accuracy
Niccolo-Rocchi Nov 6, 2025
ff2befa
Update: call def and atk mechanisms from `config.yaml` files
Niccolo-Rocchi Nov 7, 2025
bd22241
Update: now `cn_sampler` returns a bunch of BNs
Niccolo-Rocchi Nov 7, 2025
5ce3fac
Minor fixes
Niccolo-Rocchi Nov 7, 2025
b9c4011
Merge pull request #8 from Niccolo-Rocchi/5-privacy-vs-accuracy
Niccolo-Rocchi Nov 7, 2025
4fa2c4f
Merge pull request #9 from Niccolo-Rocchi/dev
Niccolo-Rocchi Nov 7, 2025
9fe0c15
Change: data generation and running of exps are now independend and m…
Niccolo-Rocchi Nov 10, 2025
072a651
Update `Dockerfile`, revert some previous changes
Niccolo-Rocchi Nov 10, 2025
d365427
Fix `README.md`
Niccolo-Rocchi Nov 10, 2025
4193c51
Change `cn_privacy` exps: update code modularity
Niccolo-Rocchi Nov 11, 2025
de6304f
Fix `cn_privacy` test
Niccolo-Rocchi Nov 12, 2025
afebc0e
Update `cn_vs_noisybn` accordingly to the `cn_privacy` exp structure
Niccolo-Rocchi Nov 12, 2025
664bacd
Minor fixes
Niccolo-Rocchi Nov 12, 2025
df79a51
Update: simplify how results are saved
Niccolo-Rocchi Nov 13, 2025
a5014f1
Change how (intermediate) results and metadata files are saved
Niccolo-Rocchi Nov 14, 2025
1cce2b6
Update: consider only one `ESS` hyperparameter for each exp, and upda…
Niccolo-Rocchi Nov 14, 2025
a221817
Fix plots for `cn_privacy`
Niccolo-Rocchi Nov 14, 2025
39f91bc
Add `def-ran` as defense mechanism
Niccolo-Rocchi Nov 14, 2025
c308982
Code refactoring
Niccolo-Rocchi Nov 14, 2025
b336f0e
Update: separate models and data generation from main exps
Niccolo-Rocchi Nov 15, 2025
289c1af
Update: def and atk parameters are now passed to command-line instead…
Niccolo-Rocchi Nov 15, 2025
f016f0c
Add `docker compose` support
Niccolo-Rocchi Nov 15, 2025
b3a6826
Add `generate_compose.py` to automate the creation of Docker compose …
Niccolo-Rocchi Nov 17, 2025
b548562
Get `eps` for each data sample instead of mean
Niccolo-Rocchi Nov 17, 2025
100d657
Fix plot notebooks, and other fixes
Niccolo-Rocchi Nov 18, 2025
57b04e6
Fix the way CN uncertainty is computed in plots
Niccolo-Rocchi Nov 18, 2025
5927431
Fix `create_clean_dir` function
Niccolo-Rocchi Nov 18, 2025
30674c0
Minor fixes
Niccolo-Rocchi Nov 18, 2025
356ac97
Add `atk_cen`, taking the centroid of a CN
Niccolo-Rocchi Nov 18, 2025
93f7434
Add `atk_ran`
Niccolo-Rocchi Nov 19, 2025
d61444a
Minor fixes
Niccolo-Rocchi Nov 19, 2025
77d23ba
Fix cdd numerical stability with `Fraction` and `cdd.gmp` module
Niccolo-Rocchi Nov 19, 2025
9985c1f
Fix inferences: skip numerically unstable experiments
Niccolo-Rocchi Nov 20, 2025
3241453
Add `atk_ent`
Niccolo-Rocchi Dec 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
venv
output
bin
__pycache__
.pytest_cache
**/output
**/__pycache__
**/.pytest_cache
4 changes: 2 additions & 2 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
pip install flake8 pytest pytest-cov
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
Expand All @@ -28,4 +28,4 @@ jobs:
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest
pytest --cov=src --cov-report=term-missing --capture=no
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
venv
output
output*
bns
data
plots
*meta.txt
bin
__pycache__
.pytest_cache
14 changes: 13 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
FROM python:bookworm
FROM python:3.12-slim

# Install system dependencies
RUN apt-get update && apt-get install -y \
build-essential \
swig \
libglpk-dev \
python3-dev \
libcdd-dev \
libgmp-dev \
&& rm -rf /var/lib/apt/lists/*

# Set working directory
WORKDIR /workspace
COPY . .

# Install python packages
RUN pip install --upgrade pip
RUN if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

Expand Down
110 changes: 68 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,82 +2,112 @@

Code for paper ["Towards Privacy-Aware Bayesian Networks: A Credal Approach"](https://doi.org/10.3233/FAIA251419) presented at [ECAI 2025](https://ecai2025.org/).

## Set up Python environment
## Preliminaries

Create and activate a Python virtual environment with:
### Experiments

```bash
python3 -m venv venv
source venv/bin/activate[.fish] # use `.fish` suffix if using fish shell
```
`<name>` is the name of the experiment to run. Each `<name>` has its own directory, which is named the same way. Each of these contains the experiment logic, configuration file (`config.yaml`), eventually generated models and data, output directory, and a `Plot_results.ipynb` notebook to plot results.

`<name>` can be one of the following:

1. `cn_privacy`: run membership inference attack against a Bayesian network (BN), its related credal network (CN), and compute the theoretical privacy estimate of BN.

2. `cn_vs_noisybn`: compare two privacy techniques, namely the CN and a noisy version of BN. All models are naive Bayes with target variable T. First, the CN and noisy BN hyperparameters are fine-tuned so that they achieve the same privacy level; then, their accuracy is computed in terms of most probable explanation (MPE) on variable T.

For additional details, we refer to the paper.

### Attacks and defenses

Install all dependencies with:
Each experiment requires the user to specify one defense and one attack mechanisms, plus additional related hyperparameters. Below, the mechanisms and hyperparameters names are reported.

Implemented defenses:
- `def_idm`. Requires: `ess`.
- `def_ran`. Requires: `delta`.

Implemented attacks:
- `atk_mle`. Requires: `n_bns`.
- `atk_cen`.
- `atk_ran`.
- `atk_ent`.

## Running code

### Using Docker (recommended)

The `compose.yaml` file contains a set of pre-set experiments. Additional ones can also be specified. The `generate_compose.py` file helps in generating them automatically.

Generate models and data for all experiments (controlled by `config.yaml`):

```bash
pip install -r requirements.txt
python -m experiments.cn_privacy.generate
python -m experiments.cn_vs_noisybn.generate
```

Upgrade all Python packages with:
Run one or more experiments with:

```bash
pip install --upgrade $(pip freeze | cut -d '=' -f 1)
pip freeze > requirements.txt
docker compose up [service name]
```

This updates the requirements file with the upgraded packages.
Results will be available under `experiments/<name>/output_*`.

## Experiments
To check the status, run one or more of the following:

`<name>` is the name of the experiment to run. It can be one of the following.

1. `cn_privacy`: run membership inference attack against a Bayesian network (BN), its related credal network (CN), and compute the theoretical privacy estimate of BN. The pipeline and results are described in the paper.
```bash
docker compose ps
docker compose logs [service name]
docker stats
```

2. `cn_vs_noisybn`: additional experiment, not reported in the paper. It compares two privacy techniques, namely the CN and a noisy version of BN. All models are naive Bayes with target variable T. First, the CN and noisy BN hyperparameters are fine-tuned so that they achieve the same privacy level; then, their accuracy is computed in terms of most probable explanation (MPE) on variable T.
### Local computation

## Run code
Create and activate a Python virtual environment:

### With Docker (recommended)
```bash
python3 -m venv venv
source venv/bin/activate[.fish] # use `.fish` suffix if using fish shell
```

1. Build the Docker image:
Install dependencies:

```bash
docker build . -t bnp:2025
pip install -r requirements.txt
```

2. Run the experiment:
*Notice*: if some package is missing locally, see the `Dockerfile` for additional packages to be installed (names refer to Ubuntu/Debian).

Upgrade dependencies:

```bash
docker run [-d] [--rm] -v bnp:/workspace bnp:2025 python -m experiments.<name>.main
pip install --upgrade $(pip freeze | cut -d '=' -f 1)
pip freeze > requirements.txt
```

3. Results available at:
*Notice:* each of the following command will overwrite any related output.

`/var/lib/docker/volumes/bnp/_data/experiments/<name>/output/`.
Generate models and data (controlled by `config.yaml`):

### Without Docker
```bash
python -m experiments.<name>.generate
```

1. Run the experiment:
Run an experiment:

```bash
python -m experiments.<name>.main
python -m experiments.<name>.exp def_mec=<def_name> [param=value] atk_mec=<def_name> [param=value]
```

2. Results available at:
Results will be available under `experiments/<name>/output`.

`experiments/<name>/output/`.

## Test code
## Testing code

Run tests with:
Run integration tests:

```bash
pytest
pytest [--cov=src] [--cov-report=term-missing] [--capture=no]
```

Test results are available at:

`test/<name>/output/`.

## Formatting and linting

Format code by running:
Expand All @@ -91,15 +121,11 @@ Lint code by running:

```bash
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude=venv
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --exclude=venv
flake8 . --count --exit-zero --max-complexity=10 --ignore=E203 --max-line-length=140 --statistics --exclude=venv
```

Analyze code by running:

```bash
pylint $(git ls-files '*.py')
```

## Plot results

Use the `Plot_results.ipynb` notebook available for each experiment. Plots will be saved at: `experiments/<name>/output/plots`.
86 changes: 86 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
version: '3.9'
services:
cn_vs_noisybn_def_idm_atk_ran_ess1:
build: .
command:
- python
- -m
- experiments.cn_vs_noisybn.exp
- def_mec=def_idm
- atk_mec=atk_ran
- ess=1
image: bnp:2025
volumes:
- ./experiments/cn_vs_noisybn/bns:/workspace/experiments/cn_vs_noisybn/bns
- ./experiments/cn_vs_noisybn/data:/workspace/experiments/cn_vs_noisybn/data
- ./experiments/cn_vs_noisybn/output_def_idm_atk_ran_ess1:/workspace/experiments/cn_vs_noisybn/output
cn_vs_noisybn_def_idm_atk_ran_ess100:
build: .
command:
- python
- -m
- experiments.cn_vs_noisybn.exp
- def_mec=def_idm
- atk_mec=atk_ran
- ess=100
image: bnp:2025
volumes:
- ./experiments/cn_vs_noisybn/bns:/workspace/experiments/cn_vs_noisybn/bns
- ./experiments/cn_vs_noisybn/data:/workspace/experiments/cn_vs_noisybn/data
- ./experiments/cn_vs_noisybn/output_def_idm_atk_ran_ess100:/workspace/experiments/cn_vs_noisybn/output
cn_vs_noisybn_def_idm_atk_ran_ess50:
build: .
command:
- python
- -m
- experiments.cn_vs_noisybn.exp
- def_mec=def_idm
- atk_mec=atk_ran
- ess=50
image: bnp:2025
volumes:
- ./experiments/cn_vs_noisybn/bns:/workspace/experiments/cn_vs_noisybn/bns
- ./experiments/cn_vs_noisybn/data:/workspace/experiments/cn_vs_noisybn/data
- ./experiments/cn_vs_noisybn/output_def_idm_atk_ran_ess50:/workspace/experiments/cn_vs_noisybn/output
cn_vs_noisybn_def_ran_atk_ran_delta0.001:
build: .
command:
- python
- -m
- experiments.cn_vs_noisybn.exp
- def_mec=def_ran
- atk_mec=atk_ran
- delta=0.001
image: bnp:2025
volumes:
- ./experiments/cn_vs_noisybn/bns:/workspace/experiments/cn_vs_noisybn/bns
- ./experiments/cn_vs_noisybn/data:/workspace/experiments/cn_vs_noisybn/data
- ./experiments/cn_vs_noisybn/output_def_ran_atk_ran_delta0.001:/workspace/experiments/cn_vs_noisybn/output
cn_vs_noisybn_def_ran_atk_ran_delta0.05:
build: .
command:
- python
- -m
- experiments.cn_vs_noisybn.exp
- def_mec=def_ran
- atk_mec=atk_ran
- delta=0.05
image: bnp:2025
volumes:
- ./experiments/cn_vs_noisybn/bns:/workspace/experiments/cn_vs_noisybn/bns
- ./experiments/cn_vs_noisybn/data:/workspace/experiments/cn_vs_noisybn/data
- ./experiments/cn_vs_noisybn/output_def_ran_atk_ran_delta0.05:/workspace/experiments/cn_vs_noisybn/output
cn_vs_noisybn_def_ran_atk_ran_delta0.1:
build: .
command:
- python
- -m
- experiments.cn_vs_noisybn.exp
- def_mec=def_ran
- atk_mec=atk_ran
- delta=0.1
image: bnp:2025
volumes:
- ./experiments/cn_vs_noisybn/bns:/workspace/experiments/cn_vs_noisybn/bns
- ./experiments/cn_vs_noisybn/data:/workspace/experiments/cn_vs_noisybn/data
- ./experiments/cn_vs_noisybn/output_def_ran_atk_ran_delta0.1:/workspace/experiments/cn_vs_noisybn/output
Empty file added experiments/__init__.py
Empty file.
Loading
Loading