Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ff2befa
Update: call def and atk mechanisms from `config.yaml` files
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
792bf06
Fix GitHub actions
Niccolo-Rocchi Dec 2, 2025
2770d6f
Fix GitHub actions by using `sudo`
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
3 changes: 1 addition & 2 deletions .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install pylint
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Analysing the code with pylint
- name: Analyzing code with pylint
run: |
pylint $(git ls-files '*.py')
2 changes: 2 additions & 0 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential swig libglpk-dev python3-dev libcdd-dev libgmp-dev
python -m pip install --upgrade pip
pip install flake8 pytest pytest-cov
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
Expand Down
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
136 changes: 88 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,104 +2,144 @@

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.

Install all dependencies with:
`<name>` can be one of the following:

```bash
pip install -r requirements.txt
```
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.

Upgrade all Python packages with:
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.

```bash
pip install --upgrade $(pip freeze | cut -d '=' -f 1)
pip freeze > requirements.txt
```
For additional details, we refer to the paper.

This updates the requirements file with the upgraded packages.
### Attacks and defenses

## Experiments
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.

`<name>` is the name of the experiment to run. It can be one of the following.
Implemented defenses:
- `def_idm`. Requires: `ess`.
- `def_ran`. Requires: `delta`.

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.
Implemented attacks:
- `atk_mle`. Requires: `n_bns`.
- `atk_cen`.
- `atk_ran`.
- `atk_ent`.

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.
## Running code

## Run code
### Using Docker (recommended)

### With 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.

1. Build the Docker image:
Generate models and data for all experiments (controlled by `config.yaml`):

```bash
docker build . -t bnp:2025
```sh
python -m experiments.cn_privacy.generate
python -m experiments.cn_vs_noisybn.generate
```

2. Run the experiment:
Run one or more experiments with:

```bash
docker run [-d] [--rm] -v bnp:/workspace bnp:2025 python -m experiments.<name>.main
```sh
docker compose up [service name]
```

3. Results available at:
Results will be available under `experiments/<name>/output_*`.

`/var/lib/docker/volumes/bnp/_data/experiments/<name>/output/`.
To check the status, run one or more of the following:

### Without Docker
```sh
docker compose ps
docker compose logs [service name]
docker stats
```

1. Run the experiment:
### Local computation

```bash
python -m experiments.<name>.main
Create and activate a Python virtual environment:

```sh
python3 -m venv venv
source venv/bin/activate[.fish] # use `.fish` suffix if using fish shell
```

2. Results available at:
Install dependencies:

`experiments/<name>/output/`.
```sh
pip install -r requirements.txt
```

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

Run tests with:
Upgrade dependencies:

```bash
pytest [--cov=src] [--cov-report=term-missing] [--capture=no]
```sh
pip install --upgrade $(pip freeze | cut -d '=' -f 1)
pip freeze > requirements.txt
```

Test results are available at:
*Notice:* each of the following command will overwrite any related output.

`test/<name>/output/`.
Generate models and data (controlled by `config.yaml`):

```sh
python -m experiments.<name>.generate
```

Run an experiment:

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

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


## Testing code

Run integration tests:

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

## Formatting and linting

Format code by running:

```bash
```sh
black .
isort .
```

Lint code by running:

```bash
```sh
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
```sh
pylint $(git ls-files '*.py')
```

## Plot results
## Running actions locally

Install `act`:

```sh
curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash
```

Run `act` with:

Use the `Plot_results.ipynb` notebook available for each experiment. Plots will be saved at: `experiments/<name>/output/plots`.
```sh
sudo ./bin/act [-W <path_to_file>]
```
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