Accepted at ML4H 2025 @ San Diego
This repository provides a framework for synthetic phonocardiogram (PCG) data generation and classification. The project implements multiple deep learning architectures for PCG signal classification across four cardiac conditions: Normal, Aortic Regurgitation (AR), Aortic Stenosis (AS), and Mitral Regurgitation (MR).
The framework supports:
- Synthetic data generation using function-based approaches
- Multiple model architectures: Transformers (Standard, Causal), ResNet, EfficientNet, LSTM, GRU
- Multi-seed experimental framework for reproducible results
- Hyperparameter optimization with Optuna
- Data augmentation techniques: masking, shifting, stretching, scaling
- Comprehensive evaluation with demographic analysis
SynPCGdev/
├── config.yaml # Main configuration file
├── Dockerfile # Docker container configuration
├── invoke_container.sh # Container management script
├── src/
│ ├── clf/ # Classification experiments
│ │ ├── train.py # Training entry point
│ │ ├── evaluate.py # Evaluation entry point
│ │ ├── codes/
│ │ │ ├── run_train.py # Training pipeline
│ │ │ ├── run_eval.py # Evaluation pipeline
│ │ │ ├── trainer.py # Trainer class
│ │ │ ├── evaluator.py # Evaluator class
│ │ │ └── data/ # Data loading modules
│ │ └── resources/ # Experiment configurations
│ └── common/ # Shared utilities
│ ├── model/ # Model architectures
│ ├── base_trainer.py # Base training infrastructure
│ └── utils.py # Utility functions
└── requirements.txt # Python dependencies
- Docker
- NVIDIA GPU with CUDA support
yqfor YAML parsing (install viabrew install yqorsnap install yq)
-
Configure paths in
config.yaml:path: base_dir: . # Repository root (default) dataset_dir: dataset # Dataset location
-
Build the Docker container:
./invoke_container.sh build
This creates a container based on
nvcr.io/nvidia/pytorch:24.01-py3with Python 3.8.6 installed via pyenv. -
Start the container:
./invoke_container.sh restart
The container will mount the data path specified in
config.yamland provide an interactive shell.
Navigate to the classification directory and run training:
cd src/clf
python train.py --exp <EXPERIMENT_ID> --device cuda:0 [--multirun] [--debug]Arguments:
--exp: Experiment ID (defines which config file to use fromresources/exp{XX}s/exp{XXXX}.yaml)--device: GPU device (default:cuda:0)--multirun: Enable multi-seed training (runs across all seeds defined in config)--debug: Enable debug mode (uses limited data and fast iterations)
Example:
python train.py --exp 1 --device cuda:0Training Pipeline:
- Random seed initialization for reproducibility
- Result directory preparation with timestamps
- Model initialization and optional pretrained weight loading
- Dataloader preparation with augmentation
- Loss function configuration (supports class weighting)
- Training execution with validation monitoring
- Model checkpointing based on validation performance
- Early stopping or Optuna pruning for hyperparameter search
Output: Results are saved to results/train/exp{XXXX}/multirun/train/seed{XXXX}/ containing:
net.pth: Best model checkpointparams.pkl: Training parameterslog.csv: Training and validation metrics per epoch
Run evaluation on trained models:
cd src/clf
python evaluate.py --exp <EXPERIMENT_ID> --device cuda:0 [--multirun] [--debug]Arguments: Same as training command
Example:
# Evaluate on single seed
python evaluate.py --exp 1 --device cuda:0
# Evaluate across all seeds
python evaluate.py --exp 1 --device cuda:0 --multirunEvaluation Pipeline:
- Locates trained models from training output directories
- Loads model weights and configuration
- Runs evaluation on validation and test sets
- Computes comprehensive metrics (F1, Precision, Recall, AUROC, AUPRC)
- Generates classification reports and confusion matrices
- Aggregates results across multiple seeds
Output: Results are saved to results/train/exp{XXXX}/multirun/eval/ containing:
ResultTableMultiSeed.csv: Aggregated metrics across all seedsreport.txt: Detailed classification reports for each seeddemo_result.csv: Per-sample results with demographics (if enabled)
Experiments are configured through YAML files. Before running experiments, configure the paths in config.yaml.
Important: Configure these paths in config.yaml before running experiments:
path:
# Base directory for all data and results (default: repository root)
# Modify this to your preferred location
base_dir: . # Current directory (repository root)
# Dataset directory (relative to base_dir)
# Place your processed datasets here
dataset_dir: datasetDirectory Structure:
SynPCGdev/ # Repository root (base_dir)
├── dataset/ # Datasets (dataset_dir)
│ ├── buet/ # BMD-HS processed data
│ └── ...
├── dataset_syn/ # Synthetic datasets
├── experiment_v01/ # Experiment results
└── ...
Notes:
- All paths can be absolute or relative to the repository root
base_dir: Location for datasets, experiments, and synthetic datadataset_dir: Subdirectory for processed datasets (relative to base_dir)- Results are saved to
{base_dir}/experiment_v01/exp{XX}s/exp{XXXX}/
experiment:
clf_exp01:
seed:
singleseed: 0
multiseed: [0, 1, 2, 3, 4] # Multiple seeds for reproducibility
result_cols: # Metrics columns in result CSV
- f1score
- Recall
- Precision
- AUROC
- AUPRC
dataset:
path: /path/to/data # Mounted in Docker containerExample configuration structure:
# Model architecture
modelname: transformer_base # Options: resnet18, effnet_b0, lstm, gru, transformer_base, etc.
# Data settings
dataset: pcg_dataset_name
data_lim: null # Limit training data (null = use all)
val_data_lim: null
# Training hyperparameters
epochs: 100
batch_size: 32
learning_rate: 0.0001
patience: 20 # Early stopping patience
eval_every: 1 # Validate every N epochs
# Class weighting for imbalance
class_weight: balanced # Options: balanced, auto, manual-{value}
# Data augmentation
augmentation:
masking: true
shifting: true
stretching: true
scaling: true
# Model-specific parameters
emb_dim: 128
depth: 4
num_heads: 8
mlp_dim: 512
# Pretrained weights (optional)
finetune_target: /path/to/pretrained/model
freeze: false # Freeze pretrained weightstransformer_base: Standard Transformer encodercausal_transformer: Causal Transformer for sequential modeling
resnet18,resnet34,resnet50: ResNet architectureseffnet_b0througheffnet_b7: EfficientNet models
lstm: Long Short-Term Memory networksgru: Gated Recurrent Units
All models support:
- Pretrained weight loading
- Weight freezing for transfer learning
- Custom embedding dimensions and depths
- Multi-GPU training with DataParallel
The framework supports multiple augmentation techniques for PCG signals:
- Masking: Random time-domain masking for robust feature learning
- Shifting: Temporal shifting to handle phase variations
- Stretching: Time-scale modification for tempo variations
- Scaling: Amplitude scaling for intensity variations
Enable/disable augmentations in experiment configuration files.
If you use this code in your research, please cite:
@inproceedings{synpcgdev2025,
title={Boosting Phonocardiogram Classification Performance with Function Generated Data},
author={[Authors]},
booktitle={Machine Learning for Health (ML4H) 2025},
year={2025},
address={San Diego, CA}
}(Full bibtex information will be updated after publication)
[License information to be added]
For questions or issues, please open an issue on GitHub or contact the authors.