Falcon is a Python framework for simulation-based inference (SBI) that enables adaptive learning of complex conditional distributions. Built on top of PyTorch, Ray, and sbi, Falcon provides a declarative approach to building probabilistic models with automatic parallelization and experiment tracking.
- Declarative Model Definition: Define complex probabilistic models using simple YAML configuration files
- Adaptive Sampling: Automatically adjusts simulation parameters based on training progress
- Distributed Computing: Built-in support for parallel execution using Ray
- Neural Density Estimation: Multiple neural network architectures for posterior estimation (NSF, MAF, NAF, etc.)
- Experiment Tracking: Integrated Weights & Biases (WandB) logging for monitoring training
- Flexible Architecture: Modular design supporting various SBI algorithms including SNPE-A
- Python 3.8 or higher
- PyTorch 2.0 or higher
- CUDA (optional, for GPU acceleration)
# Clone the repository
git clone https://github.com/cweniger/falcon.git
cd falcon
# Install
pip install .Falcon requires the following packages (automatically installed):
torch>=2.0.0- Deep learning frameworknumpy- Numerical computingray- Distributed computingsbi- Simulation-based inference toolboxhydra-core- Configuration managementomegaconf- Configuration utilitieswandb>=0.15.0- Experiment tracking
falcon/
├── falcon/ # Core library
│ ├── core/ # Core components
│ │ ├── graph.py # Graph-based model definition
│ │ ├── deployed_graph.py # Runtime graph execution
│ │ ├── raystore.py # Distributed data management
│ │ └── logging.py # Logging utilities
│ ├── contrib/ # Built-in components
│ │ ├── SNPE_A.py # SNPE-A implementation
│ │ ├── torch_embedding.py # Neural embeddings
│ │ └── hypercubemappingprior.py # Prior distributions
│ └── cli.py # Command-line interface
├── examples/ # Example configurations
│ ├── 01_minimal/ # Basic SBI example
│ └── 02_bimodal/ # Advanced bimodal example
└── setup.py # Package configuration
Falcon uses Hydra/OmegaConf for configuration management. Each experiment is defined by a config.yaml file:
# Experiment tracking with Weights & Biases
logging:
project: falcon_examples # WandB project name
group: experiment_01 # Experiment group
dir: ${hydra:run.dir} # Output directory
# Directory paths
paths:
import: "./src" # User code location
buffer: ${hydra:run.dir}/sim_dir # Simulation data
graph: ${hydra:run.dir}/graph_dir # Trained models
# Training buffer configuration
buffer:
min_training_samples: 4096 # Min samples before training
max_training_samples: 32768 # Max buffer size
validation_window_size: 256 # Validation split size
resample_batch_size: 128 # New samples per iteration
keep_resampling: true # Continue after max reached
resample_interval: 10 # Epochs between resampling
# Graph definition (model architecture)
graph:
# Define nodes and their relationships
parameter_node:
evidence: [observation_node] # Inference target
simulator: # Prior distribution
_target_: falcon.contrib.HypercubeMappingPrior
priors: [['uniform', -10, 10], ...]
estimator: # Posterior estimator
_target_: falcon.contrib.SNPE_A
net_type: nsf # Neural network type
num_epochs: 300
batch_size: 128
lr: 0.01
ray:
num_gpus: 0 # GPU allocation
observation_node:
parents: [parameter_node] # Dependencies
simulator: # Forward model
_target_: model.YourSimulator
observed: "./data/obs.npy" # Observed data
# Sampling configuration
sample:
posterior:
n: 1000 # Number of samples
path: samples_posterior.joblibmin_training_samples: Minimum samples required before training beginsmax_training_samples: Maximum number of samples retained in memorykeep_resampling: Whether to continue generating samples after reaching maximumresample_interval: How often (in epochs) to generate new samples
net_type: Neural network architecture (nsf,maf,naf,gf,zuko_gf)gamma: SNPE-A mixing coefficient for amortizationtheta_norm: Enable parameter space normalizationearly_stop_patience: Epochs without improvement before stopping
num_gpus: GPU count per worker (0 for CPU-only)init: Additional Ray initialization parameters
Falcon provides a simple command-line interface for running experiments:
# Run training with default configuration
falcon launch
# Run with specific output directory
falcon launch hydra.run.dir=outputs/my_experiment
# Override configuration parameters
falcon launch buffer.num_epochs=500 graph.z.estimator.lr=0.001# Sample from prior distribution
falcon sample prior
# Sample from trained posterior (after training)
falcon sample posterior
# Sample from proposal distribution
falcon sample proposalcd examples/01_minimal
falcon launch hydra.run.dir=outputs/run_01
falcon sample posterior hydra.run.dir=outputs/run_01This example demonstrates:
- Basic 3-parameter inference problem
- Simple forward model
- Neural spline flow (NSF) posterior estimation
cd examples/02_bimodal
# Regular training
falcon launch --config-name config_regular
# Amortized inference
falcon launch --config-name config_amortized
# Round-based training with renewal
falcon launch --config-name config_rounds_renewThis example showcases:
- Complex 10-dimensional parameter space
- Bimodal posterior distributions
- Different training strategies (regular, amortized, round-based)
- GPU acceleration
Create a Python module in your src/ directory:
# src/model.py
import torch
class MySimulator:
def __init__(self, param1=1.0):
self.param1 = param1
def __call__(self, z):
# z: input parameters [batch_size, n_params]
# return: simulated data [batch_size, n_observables]
return torch.sin(z * self.param1)
class MyEmbedding(torch.nn.Module):
def __init__(self, input_dim, output_dim=32):
super().__init__()
self.net = torch.nn.Sequential(
torch.nn.Linear(input_dim, 64),
torch.nn.ReLU(),
torch.nn.Linear(64, output_dim)
)
def forward(self, x):
return self.net(x)# config.yaml
logging:
project: my_project
group: experiment_01
paths:
import: "./src"
buffer: ${hydra:run.dir}/sim_dir
graph: ${hydra:run.dir}/graph_dir
buffer:
min_training_samples: 1024
max_training_samples: 8192
graph:
theta:
evidence: [x]
simulator:
_target_: falcon.contrib.HypercubeMappingPrior
priors: [['uniform', -5, 5], ['uniform', -5, 5]]
estimator:
_target_: falcon.contrib.SNPE_A
embedding:
_target_: model.MyEmbedding
_input_: [x]
input_dim: 10
output_dim: 32
net_type: nsf
num_epochs: 200
x:
parents: [theta]
simulator:
_target_: model.MySimulator
param1: 2.0
observed: "./data/observations.npy"# Generate or load your observed data
import numpy as np
observations = np.random.randn(10) # Your actual data
np.save("data/observations.npy", observations)falcon launchFalcon supports complex dependency graphs with multiple nodes:
graph:
# Latent parameters
z:
evidence: [x]
simulator: ...
estimator: ...
# Intermediate signal
signal:
parents: [z]
simulator: model.SignalGenerator
# Noise component
noise:
simulator: model.NoiseGenerator
# Final observation
x:
parents: [signal, noise]
simulator: model.Combiner
observed: "./data/obs.npy"Implement custom embedding networks for complex data:
class ConvolutionalEmbedding(torch.nn.Module):
"""For image data"""
def __init__(self):
super().__init__()
self.conv = torch.nn.Sequential(
torch.nn.Conv2d(1, 32, 3),
torch.nn.ReLU(),
torch.nn.MaxPool2d(2),
torch.nn.Flatten()
)
def forward(self, x):
return self.conv(x)Configure Ray for distributed execution:
ray:
init:
num_cpus: 8
num_gpus: 2
dashboard_host: "0.0.0.0"
graph:
z:
ray:
num_gpus: 1 # Per-worker GPU allocationFalcon automatically logs training metrics to WandB:
- Set up WandB account: https://wandb.ai
- Configure project in
config.yaml - Monitor training at https://wandb.ai/your-username/your-project
Logged metrics include:
- Training/validation loss
- Learning rate schedules
- Sample generation statistics
- Model architecture details
After training, Falcon creates:
outputs/run_name/
├── sim_dir/ # Generated simulation data
│ └── samples_*.pt # Training samples
├── graph_dir/ # Trained models
│ ├── graph.pkl # Graph structure
│ └── estimators/ # Neural network weights
├── samples_posterior.joblib # Posterior samples
└── .hydra/ # Configuration logs
- Out of Memory: Reduce
buffer.max_training_samplesorbatch_size - Slow Training: Enable GPU with
ray.num_gpus: 1 - Poor Convergence: Adjust
lr,num_epochs, or try differentnet_type - Import Errors: Ensure
paths.importpoints to your model code
- Use GPU acceleration for large models
- Enable
theta_normfor high-dimensional parameter spaces - Adjust
resample_intervalbased on simulation cost - Use
early_stop_patienceto prevent overfitting
If you use Falcon in your research, please cite:
@software{falcon2024,
title = {Falcon: Federated Adaptive Learning of CONditional distributions},
year = {2024},
url = {https://github.com/yourusername/falcon}
}This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
For questions and support, please open an issue on GitHub or contact the maintainers.