← 返回首页
GitHub - Fabian-Mor/partial_fusion_nn: Code for the paper Partial Fusion of Neural Networks: Efficient Tradeoffs Between Ensembles and Weight Aggregation · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus

Fabian-Mor/partial_fusion_nn

Go to file
Code

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
View all files

Repository files navigation

More items

Partial Fusion of Neural Networks

Reference implementation accompanying the paper Partial Fusion of Neural Networks: Efficient Tradeoffs Between Ensembles and Weight Aggregation (Morelli & Eckstein, ICML 2026). The repository implements partial fusion, a method for merging trained neural networks using partial optimal transport with a sink option.

Installation

Using conda (recommended):

conda env create -f environment.yml conda activate partial_fusion

Or with pip:

python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txt

Requirements: Python 3.11, PyTorch 2.2.1 + torchvision 0.17.1 (pinned in requirements.txt), CUDA-capable GPU recommended for the CNN/ResNet experiments. The environment.yml only provisions Python + pip and then defers to requirements.txt, so the conda and venv installs are identical.

Datasets

MNIST and CIFAR-10 are downloaded automatically by torchvision the first time you run any experiment. No manual data setup is required.

Pretrained checkpoints

The fusion and pruning experiments load pre-trained source models. Re-training all of them from scratch takes a long time on a single GPU, so we host the full set of checkpoints (~1.1 GB) on Zenodo:

Download: https://zenodo.org/records/20486343 (partial_fusion_checkpoints.tar.gz, ~1.1 GB) SHA-256: 134fda6a4d98afd58a24d91aec8d62dbbc4400c8a376cf45aebbbb339eb05e1a

After downloading partial_fusion_checkpoints.tar.gz, extract it inside the experiments/ directory so that its contents end up at experiments/saved/ and experiments/saved_models/:

cd experiments tar -xzvf /path/to/partial_fusion_checkpoints.tar.gz

The archive is laid out so that the file paths inside it match exactly what the experiment scripts expect to load:

  • saved/resnet18_a_{0..10}.checkpoint / resnet18_b_{0..10}.checkpoint — 11 independently-seeded ResNet18 pairs on CIFAR-10 used by cifar_resnet18_partial_fusion.py.
  • saved/resnet18_evenodd_{a,b}.checkpoint — class-split specialists for the two cifar_resnet18_class_split_*.py scripts.
  • saved/mlp_capacity_{a,b}_h{25,50,100,200,400}_s{0..4}.checkpoint — 50 Deep_MLPs across the full capacity sweep used by mnist_mlp_capacity_sweep.py (and seed 0 / hidden 100 is also used by mnist_mlp_git_rebasin_baseline.py).
  • saved/{0..9}deepmlpmnist_[100, 100, 100]_2.checkpoint — 10 independently-seeded Deep_MLPs (GELU, hidden [100,100,100]) on MNIST. Used by partial_fusion_sweep.py (non-specialist mode), mnist_mlp_ensemble_pruning.py (non-specialist mode), and single_model_pruning_sweep.py (MLP mode).
  • saved/{0..9}deepmlpmnist_[100, 100, 100]_0.checkpoint — same as above but with ReLU activation. Used by mnist_mlp_seed_pruning.py.
  • saved/{0..4}deepmlpmnist_general_[100, 100, 100]_2.checkpoint / saved/{0..4}deepmlpmnist_specific_[100, 100, 100]_2.checkpoint — specialist MLP pairs (general = full MNIST, specific = digit-4 biased) used by partial_fusion_sweep.py (specialist mode, default) and mnist_mlp_ensemble_pruning.py (specialist mode, default).
  • saved/{0,1}VGG11_[64, 128, 256, 256, 512, 512, 512, 512]_best.checkpoint — 2 independently-seeded VGG11 baselines on CIFAR-10. Used by partial_fusion_sweep.py (CNN mode), single_model_pruning_sweep.py (CNN mode), cifar_vgg11_seed_pruning.py, and cifar_vgg11_ensemble_pruning.py. Seed counts in those scripts have been set to match the shipped baselines; bump them and re-train if you want larger error bars on the VGG11 ablations.
  • saved_models/best_{a,b}.checkpoint — VGG11 checkpoints used by the appendix channel-similarity analysis.

If you'd rather train everything yourself, skip the download and run the pretraining utilities in experiments/ (see the section below); the experiment scripts also train missing source models on demand.

Project layout

src/ base_model.py # BaseModel: training/eval/save/load helpers shared by all architectures data_loader.py # MNIST / CIFAR-10 loaders, including the specialist (digit-biased) split CNN/ # ResNet18, VGG11 MLP/ # MLP, Deep_MLP FusionModel/ fusion_model.py # FusionModel: assembles a forward network from aligned weights fusion_methods/ base_fusion.py # Abstract fusion-method interface naive_fusion.py # Lambda-weighted weight averaging (baseline) partial_fusion.py # Partial OT alignment with sink option (this paper's method) git_rebasin.py # Git Re-Basin baseline generalized_pruning/ # Structured, weight-hierarchical, and stochastic-hierarchical pruning experiments/ # --- Pretraining utilities (produce checkpoints used by downstream experiments) --- mnist_mlp_train_baselines.py cifar_vgg11_train_baselines.py mnist_mlp_train_specialists.py # --- Main partial fusion experiments --- partial_fusion_sweep.py cifar_resnet18_partial_fusion.py # --- Class-split fusion ablations (ResNet18 + CIFAR-10) --- cifar_resnet18_class_split_cosine_bn.py cifar_resnet18_class_split_random_widen.py # --- MLP capacity ablation --- mnist_mlp_capacity_sweep.py # --- Baseline method comparison --- mnist_mlp_git_rebasin_baseline.py # --- Pruning experiments --- single_model_pruning_sweep.py mnist_mlp_seed_pruning.py cifar_vgg11_seed_pruning.py mnist_mlp_ensemble_pruning.py cifar_vgg11_ensemble_pruning.py # --- Paper appendix (neuron / channel similarity analysis) --- appendix_experiments/

All experiment scripts are designed to be run from inside experiments/:

cd experiments python <script_name>.py

Experiments

Pretraining utilities

These scripts produce the model checkpoints that the downstream fusion and pruning experiments load. They write to experiments/saved/.

  • mnist_mlp_train_baselines.py — Trains Deep_MLP models on a 10% subset of MNIST across uniform hidden widths (100, 120, …, 200), producing single-model baselines and characterising the MLP capacity–accuracy curve.
  • cifar_vgg11_train_baselines.py — Trains VGG11 models on CIFAR-10 with channel-width multipliers from 0.9× down to 0.1×, producing the single-model VGG11 reference checkpoints used by the pruning experiments.
  • mnist_mlp_train_specialists.py — Trains pairs of Deep_MLP models per seed and activation: one on the full MNIST training set (the general model) and one biased toward digit 4 (the specific model). These pairs feed the specialist-fusion and ensemble-pruning experiments.

Main partial fusion experiments

  • partial_fusion_sweep.py — The core experiment. Loads two pre-trained models (either a specialist pair or two independently-seeded models) and sweeps over lambda (mixing weight) and alpha (sink mass). Reports accuracy and effective parameter counts for naive averaging, partial OT fusion, and several pruning-based variants. Toggle CNN = True for VGG11+CIFAR-10 or False for MLP+MNIST.
  • cifar_resnet18_partial_fusion.py — ResNet18 + CIFAR-10 instance of the same sweep, run over num_seeds independently-trained model pairs (checkpoints at saved/resnet18_a_{i}.checkpoint / saved/resnet18_b_{i}.checkpoint). Setting save=True trains the pairs from scratch (standard SGD recipe: lr=0.1, momentum=0.9, weight_decay=5e-4, cosine annealing, 200 epochs); otherwise existing checkpoints are loaded and any missing pair is trained on demand.

Class-split fusion ablations (ResNet18 + CIFAR-10)

Both scripts use the same data split: model A is trained primarily on even classes ({0,2,4,6,8}) and model B on odd classes ({1,3,5,7,9}), with a small fraction of cross-class data for fine-tuning. If saved/resnet18_evenodd_{a,b}.checkpoint does not exist, the scripts train the source models from scratch.

  • cifar_resnet18_class_split_cosine_bn.py — Tests cosine-similarity initialization of batch-norm running statistics during fusion (as opposed to recalibration on a held-out batch), then masked-fine-tunes each fused configuration across alpha values.
  • cifar_resnet18_class_split_random_widen.py — Sanity check: widens model A with random extra channels to match the parameter count of the partially fused model, fine-tunes it, and compares against partial fusion. Isolates whether the fusion gains come from genuine cross-model knowledge transfer or simply from added capacity.

MLP capacity ablation

  • mnist_mlp_capacity_sweep.py — Outer axis is the uniform MLP hidden width (e.g., [200, 400]). For each capacity, trains five seed pairs and runs a full (lambda, alpha) fusion sweep. Reports mean ± standard deviation across seeds, isolating how the partial-fusion benefit scales with model size.

Baseline method comparison

  • mnist_mlp_git_rebasin_baseline.py — Sanity check + comparison against the Git Re-Basin baseline. Verifies the identity-recovery property (lambda=[1,0] reproduces model A, lambda=[0,1] reproduces model B), then reports test accuracy at lambda=[0.5,0.5] for NaiveFusion, PartialFusion across alphas, and GitRebasin.

Pruning experiments

  • single_model_pruning_sweep.py — Configurable single-model pruning experiment (MLP+MNIST or VGG11+CIFAR-10). Compares structured pruning, optimal-transport pruning, and stochastic hierarchical pruning across width multipliers, with optional post-pruning fine-tuning.
  • mnist_mlp_seed_pruning.py — Pruning comparison on independently-seeded MLPs (10 seeds, width multipliers from 1.0× down to 0.1×). Compares simple structured pruning, post-processed pruning, and activation-based clustering, reporting mean ± std test accuracy per ratio.
  • cifar_vgg11_seed_pruning.py — VGG11 + CIFAR-10 counterpart of the above. Compares simple incoming-importance pruning, OT-based pruning ("ot paper"), and stochastic-hierarchical clustering on independently-seeded models.
  • mnist_mlp_ensemble_pruning.py — Combines partial fusion with pruning on the specialist split: fuses general + specific MLPs across alpha, then prunes the fused model and compares the resulting accuracy across pruning methods.
  • cifar_vgg11_ensemble_pruning.py — Same idea on VGG11 + CIFAR-10 using different-seed ensemble pairs.

Paper appendix — neuron / channel similarity analysis

See experiments/appendix_experiments/README.txt for the appendix reproduction notes.

  • train_homogeneous_models.py — Trains two MLPs on the full MNIST training set with the GELU activation, producing the homogeneous baseline checkpoints used by mlp_neuron_similarity_analysis.py.
  • mlp_neuron_similarity_analysis.py — Computes pairwise neuron-level activation distances between the two homogeneously-trained MLPs and produces the figures and LaTeX tables included in the appendix.
  • vgg11_channel_similarity_analysis.py — Computes per-channel activation distances between two VGG11 checkpoints (any two from the VGG11 experiments) and produces the corresponding appendix figures.

Reproduction order

A typical end-to-end reproduction proceeds in three phases:

cd experiments # 1. Pretrain the source models. python mnist_mlp_train_baselines.py python cifar_vgg11_train_baselines.py python mnist_mlp_train_specialists.py # 2. Run the main fusion experiments and ablations. python partial_fusion_sweep.py python cifar_resnet18_partial_fusion.py python cifar_resnet18_class_split_cosine_bn.py python cifar_resnet18_class_split_random_widen.py python mnist_mlp_capacity_sweep.py python mnist_mlp_git_rebasin_baseline.py # 3. Run the pruning experiments. python single_model_pruning_sweep.py python mnist_mlp_seed_pruning.py python cifar_vgg11_seed_pruning.py python mnist_mlp_ensemble_pruning.py python cifar_vgg11_ensemble_pruning.py

The appendix can be reproduced separately:

cd experiments/appendix_experiments python train_homogeneous_models.py python mlp_neuron_similarity_analysis.py python vgg11_channel_similarity_analysis.py

cifar_resnet18_partial_fusion.py and the cifar_resnet18_class_split_* scripts do not depend on the pretraining utilities: they either train their own ResNet18 checkpoints on first run or load existing ones from saved/.

License

This project is released under the MIT License.

About

Code for the paper Partial Fusion of Neural Networks: Efficient Tradeoffs Between Ensembles and Weight Aggregation

Resources

License

Stars

3 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

Footer

© 2026 GitHub, Inc.