|
Download experiments/README.md from Angione-Lab/Shape2Force: direct link, hf CLI and curl.
- Browser
- Download file 7.26 kB
-
https://huggingface.co/Angione-Lab/Shape2Force/resolve/main/experiments/README.md
- Command line
-
hf download hf://Angione-Lab/Shape2Force/experiments/README.md
-
curl -L -o README.md https://huggingface.co/Angione-Lab/Shape2Force/resolve/main/experiments/README.md
7.26 kB
| # S2F experiments: data audit, evaluation, baselines and ablations | |
| This folder holds the code for every number reported in the paper beyond the training of the released checkpoints: | |
| - the dataset audit and split manifests; | |
| - the evaluation of the released models; | |
| - the baselines and ablation study. | |
| Run every command from the repository root (`Shape2Force/`); a GPU is used automatically when available. | |
| ``` | |
| experiments/ | |
| layout.py dataset layout, per-set metadata (Young's modulus, TFM settings), manifest helpers | |
| prepare_dataset.py audit legacy data vs dataset/, copy missing images, write splits/*.csv | |
| manifest_data.py data loader driven by a split manifest (same preprocessing as data/cell_dataset.py) | |
| ablation_models.py plain U-Net and S2F generator variants | |
| losses.py per-image WFM-RME and weighted MSE + soft Dice losses (both used for the released model) | |
| configs.py shared training protocol + one entry per variant | |
| train.py train one variant | |
| evaluate.py evaluate released checkpoints / baselines / trained runs on all manifests | |
| run_all.py run the steps above in order | |
| splits/ split manifests (tracked in git) | |
| runs/ training outputs (git-ignored) | |
| results/ audit and evaluation tables | |
| ``` | |
| ## Data | |
| `dataset/` (git-ignored, Zenodo record 10.5281/zenodo.18457879) contains: | |
| - `singlecell/train` (236), `singlecell/test` (46); | |
| - `spheroid/train` (129), `spheroid/test` (28). | |
| The released single-cell model was trained on a larger split (`all_tune`: 280 training / 81 validation pairs, 1, 6 and 10 kPa). The paper also reports independent test sets. `prepare_dataset.py` reconstructs all of this from the original data tree and adds the missing images to `dataset/`: | |
| ``` | |
| dataset/singlecell_extra/<set>/<sample>/ all_tune images that are not in singlecell/ (1 and 10 kPa) | |
| dataset/singlecell_external/<set>/<sample>/ independent test sets (DMSO, Y-27632, TGF-beta, fibronectin, ...) | |
| ``` | |
| Each manifest in `splits/` lists one sample per row: | |
| - the sample folder relative to `dataset/`; | |
| - condition, Young's modulus and TFM settings: colour limit of the heatmap (`ythreshold_Pa`, 500 Pa for single cells and 200 Pa for spheroids) and pixel-size setting; | |
| - the substrate setting the original code fed to the network (`substrate_legacy`) and the nominal one (`substrate_nominal`); | |
| - the MD5 of the bright-field image. | |
| ## Steps | |
| ```bash | |
| # 1. audit only: what is in dataset/ vs the original tree, all_tune composition, leakage check | |
| python -m experiments.run_all --legacy-root <path>/cellforce/dataset --steps audit | |
| # 2. complete dataset/ and write splits/*.csv (then commit experiments/splits/) | |
| python -m experiments.run_all --legacy-root <path>/cellforce/dataset --steps prepare | |
| # 3. released checkpoints, substrate sweep, input-free baseline, image-only stage-1 model | |
| python -m experiments.run_all --steps eval_released --stage1 <path>/outputs/checkpoints/last/last_checkpoint_final.pth | |
| # 4. baselines / ablations (S2F about 7 h, U-Net about 2.5 h each on an RTX A6000; resumable), then their evaluation | |
| python -m experiments.run_all --steps train,eval_runs --variants s2f_full,unet,unet_gan,s2f_no_gan,s2f_no_substrate,s2f_no_force | |
| ``` | |
| A single run: `python -m experiments.train --variant unet --seed 0`. | |
| ### GPUs and run time | |
| - `--steps train` runs one job per GPU in parallel (default `--gpus 0,1`). Each job sees only its own GPU (`CUDA_VISIBLE_DEVICES`), and the next variant starts as soon as a GPU is free. | |
| - A model is never split across GPUs: with batch size 2, that would harm batch-norm/GAN training. | |
| - `train.py` refuses to run without CUDA unless `--allow-cpu` is given. | |
| - Augmentation runs in `--num-workers` DataLoader processes (default 2 per job; use 0 if RAM is short). | |
| - Finished runs (and finished phases) are skipped and interrupted runs resume from the phase's `last_checkpoint.pth`, so the command can simply be re-run. | |
| - Run time on an RTX A6000: S2F about 3 min per epoch, i.e. about 7 h per variant (100 + 40 epochs); U-Net about 2.5 h. On two GPUs the 6 core variants take about 15 h (`s2f_no_force` reuses phase 1 of `s2f_full`). | |
| - Progress is logged to `experiments/runs/<variant>_seed<seed>/train.log` (validation pixel r and WFM-RME every epoch) and `phase*/history.json`. | |
| For a quick check that everything runs, add `--epochs 1 --max-batches 2` (1 epoch per phase; add `--allow-cpu` without a GPU). | |
| ## Training protocol (all variants) | |
| Every variant is trained from scratch on `alltune_train` (280 pairs), batch size 2, 1024 × 1024 px, the augmentations of `data/augmentations.py`, Adam (β = 0.5/0.999) with cosine decay after 10 % linear warm-up, in two phases that mirror the staged training of the released model: | |
| | phase | epochs | reconstruction loss | other terms | lr | starts from | | |
| |---|---|---|---|---|---| | |
| | 1 localisation | 100 | 100 × weighted MSE + soft Dice (pos_weight 3, threshold 0.2, Dice 0.5) | 1 × adversarial | 1e-4 | random weights | | |
| | 2 magnitude | 40 | 10 × per-image WFM-RME | 1 × adversarial + 100 × MSE of mean intensity | 1e-5 | best phase-1 generator | | |
| Each phase uses a new discriminator and optimiser and keeps the checkpoint with the lowest validation loss of that phase on `alltune_val` (81 pairs); the final model is the best phase-2 checkpoint. WFM-RME alone does not learn to localise the forces from random weights (a first protocol that used it from the start gave pixel r ≈ 0), which is also why the released model was first trained with the weighted MSE + Dice loss. Variants change one component each (`configs.py`): | |
| | variant | change | | |
| |---|---| | |
| | `s2f_full` | none (from-scratch counterpart of the released model) | | |
| | `unet` | plain U-Net (Ronneberger et al. 2015), no attention modules, no discriminator | | |
| | `unet_gan` | plain U-Net + PatchGAN (pix2pix-style) | | |
| | `mask_only` | binary cell mask instead of bright field (needs `cell_mask.tif` in each sample folder) | | |
| | `s2f_no_gan` | no discriminator (λ_GAN = 0) | | |
| | `s2f_no_force` | no stress-consistency term (λ_force = 0 in phase 2; phase 1 is identical to `s2f_full` and reused) | | |
| | `s2f_gan_0.1`, `s2f_gan_5` | λ_GAN = 0.1 / 5 | | |
| | `s2f_no_substrate` | bright field only (no substrate channels) | | |
| | `s2f_nominal_substrate` | substrate channels from the nominal Young's modulus of each image | | |
| | `s2f_no_multiscale` | no multi-scale input module | | |
| | `s2f_bridge_no_cbam` | bottleneck without CBAM | | |
| | `s2f_bridge_plain` | bottleneck without CBAM, Global Context Module and hierarchical attention | | |
| | `s2f_no_attention_gates` | skip connections without attention gates | | |
| The released checkpoint was obtained by staged fine-tuning from earlier checkpoints, with substrate channels added only in its last two stages (see Methods). `evaluate.py` reports it alongside the from-scratch variants. | |
| ## Metrics | |
| `evaluate.py` computes every metric per image and reports the mean and SD across images: | |
| - MSE, MS-SSIM and pixel-wise Pearson r; | |
| - per-image WFM-RME; | |
| - mean traction stress in Pa (heatmap value × colour limit); | |
| - the fraction of saturated ground-truth pixels; | |
| - inference time. | |
| Its outputs are `results/eval/per_image.csv`, `summary.csv` and `model_params.csv`. | |