| --- |
| library_name: pytorch |
| tags: |
| - conditional-diffusion |
| - out-of-distribution-detection |
| - cifar10 |
| - anomaly-detection |
| - thesis |
| license: mit |
| --- |
| |
| # DiffusionOOD β Pretrained Models & Results |
|
|
| [](https://github.com/ahmed-3m/DiffusionOOD) |
| [-blue)](https://huggingface.co/ahmed-3m/InkjetOOD) |
|
|
| **Thesis:** *Conditional Diffusion Models as Generative Classifiers for Out-of-Distribution Detection in Inkjet Print Quality Control* |
| **Author:** Ahmed Mohammed β MSc AI, Johannes Kepler University Linz (2026) |
| **Supervisor:** Univ.-Prof. Dr. Sepp Hochreiter |
|
|
| --- |
|
|
| ## What Is This? |
|
|
| This HuggingFace repository stores **all trained checkpoints and raw results** for the CIFAR-10 OOD detection experiments from the above thesis. |
|
|
| The **code** lives on GitHub: [https://github.com/ahmed-3m/DiffusionOOD](https://github.com/ahmed-3m/DiffusionOOD) |
|
|
| **Method summary:** A binary Conditional Diffusion Model (CDM) trained on one CIFAR-10 class detects out-of-distribution images by comparing reconstruction errors under two conditioning signals (ID vs OOD proxy). A separation loss pushes the two class embeddings apart during training. |
|
|
| OOD score = `E_t[ ||Ξ΅ β Ξ΅_ΞΈ(x_t, t, c=ID)||Β² ] β E_t[ ||Ξ΅ β Ξ΅_ΞΈ(x_t, t, c=OOD)||Β² ]` |
|
|
| Higher score β more likely OOD. This is **Algorithm 1** from the thesis. |
|
|
| --- |
|
|
| ## Quick Start |
|
|
| ### Option A β Evaluate with pretrained weights (~10 min) |
|
|
| ```bash |
| # 1. Clone the code repo |
| git clone https://github.com/ahmed-3m/DiffusionOOD |
| cd DiffusionOOD |
| pip install -r requirements.txt |
| |
| # 2. Download pretrained checkpoints from this HF repo |
| python download_weights.py |
| |
| # 3. Evaluate (CIFAR-10 auto-downloaded to ./data) |
| python scripts/evaluate.py \ |
| --checkpoint_path models/seed42_best.ckpt \ |
| --num_trials 10 \ |
| --data_dir ./data |
| ``` |
|
|
| Expected: AUROC β 0.989, FPR@95 β 0.047. |
|
|
| --- |
|
|
| ### Option B β Train from scratch (single seed) |
|
|
| ```bash |
| CUDA_VISIBLE_DEVICES=0 python scripts/train.py \ |
| --seed 42 \ |
| --separation_loss_weight 0.02 \ |
| --batch_size 64 \ |
| --max_epochs 200 \ |
| --eval_interval 10 \ |
| --scoring_method difference \ |
| --timestep_mode uniform \ |
| --experiment_tag thesis_seed42 \ |
| --wandb_mode disabled \ |
| --output_dir outputs/seed42 |
| ``` |
|
|
| Expected: AUROC β 0.987 at best validation checkpoint. |
|
|
| --- |
|
|
| ### Option C β Reproduce the 3-seed study |
|
|
| ```bash |
| bash scripts/run_three_seeds.sh |
| ``` |
|
|
| Expected: mean AUROC 0.9833 (seeds 42/123/456), individual: 0.9898 / 0.9914 / 0.9686. |
|
|
| --- |
|
|
| ## Step-by-Step: Load a Pretrained Checkpoint |
|
|
| **Step 1 β Download** |
|
|
| ```python |
| from huggingface_hub import hf_hub_download |
| import torch |
| |
| # Download the thesis headline model (seed=42, val AUROC 0.9873) |
| path = hf_hub_download( |
| repo_id="ahmed-3m/DiffusionOOD", |
| filename="models/main_training/seed42_best_auroc0.9873.ckpt" |
| ) |
| ckpt = torch.load(path, map_location="cpu", weights_only=False) |
| print(list(ckpt.keys())) # ['state_dict', 'hyper_parameters', ...] |
| ``` |
|
|
| **Step 2 β Load the model** |
|
|
| ```python |
| from src.model import DiffusionOODModel |
| |
| device = "cuda" |
| model = DiffusionOODModel.load_from_checkpoint(path, map_location=device) |
| model.eval() |
| print("Model loaded.") |
| ``` |
|
|
| **Step 3 β Run inference** |
|
|
| ```python |
| import torch |
| from src.scoring import compute_ood_score |
| |
| # x: (B, 3, 32, 32) float tensor in [-1, 1] |
| x = torch.randn(1, 3, 32, 32).to(device) |
| score = compute_ood_score(model, x, num_trials=10, device=device) |
| # score > 0 β likely OOD; score < 0 β likely ID |
| print(f"OOD score: {score.item():.4f}") |
| ``` |
|
|
| For full evaluation details, see [`scripts/evaluate.py`](https://github.com/ahmed-3m/DiffusionOOD/blob/main/scripts/evaluate.py). |
|
|
| --- |
|
|
| ## Models |
|
|
| | File | Description | Val AUROC | Test AUROC | Params | |
| |---|---|---|---|---| |
| | `models/main_training/seed42_best_auroc0.9873.ckpt` | **3-seed study, seed=42 (thesis headline)** | 0.9873 | **0.9898** | 68.79 M | |
| | `models/main_training/seed123_best_auroc0.9886.ckpt` | 3-seed study, seed=123 | 0.9886 | **0.9914** | 68.79 M | |
| | `models/main_training/seed456_best_auroc0.9887.ckpt` | 3-seed study, seed=456 | 0.9887 | **0.9686** | 68.79 M | |
| | `models/separation_loss_ablation/sep_loss_lambda_0p0_epoch79_auroc0.8025.ckpt` | Baseline Ξ»=0 | 0.8025 | β | 68.79 M | |
| | `models/separation_loss_ablation/sep_loss_lambda_0p02_epoch29_auroc0.9911.ckpt` | Ablation best Ξ»=0.02 | **0.9911** | β | 68.79 M | |
| | `models/separation_loss_ablation/sep_loss_lambda_0p1_epoch149_auroc0.9667.ckpt` | Ablation Ξ»=0.1 | 0.9667 | β | 68.79 M | |
|
|
| ### Raw Score Tensors |
|
|
| | File | Contents | |
| |---|---| |
| | `models/raw_scores/seed42_cifar10_id_scores.pt` | 1000 ID scores (seed=42, test split) | |
| | `models/raw_scores/seed42_cifar10_ood_scores.pt` | 9000 OOD scores (seed=42, test split) | |
|
|
| Load with `torch.load("seed42_cifar10_id_scores.pt")` β float tensor of shape `(1000,)`. |
|
|
| > **Which checkpoint for evaluation?** Use `seed42_best_auroc0.9873.ckpt` β it gives the thesis headline result of **98.98% test AUROC**. Use the raw scores to recompute AUROC instantly without running inference. |
|
|
| --- |
|
|
| ## Results |
|
|
| ### Main Results (3-Seed Evaluation) |
|
|
| | Seed | Val AUROC | Test AUROC | FPR@95 | |
| |---|---|---|---| |
| | seed=42 | 0.9873 | **0.9898** | 0.047 | |
| | seed=123 | 0.9886 | **0.9914** | 0.046 | |
| | seed=456 | 0.9887 | **0.9686** | 0.122 | |
| | **Mean** | 0.9882 | **0.9833** | 0.072 | |
|
|
| > Thesis headline result: **98.98% AUROC** (seed=42). Verified from stored score tensors. |
|
|
| ### Separation Loss Ablation (seed=42) |
|
|
| | Ξ» | Best Val AUROC | Epoch | Gain vs Ξ»=0 | |
| |---|---|---|---| |
| | 0.0 (baseline) | 0.8025 | 79 | β | |
| | 0.001 | 0.9732 | 19 | +17.1 pp | |
| | 0.01 | 0.9869 | β | +18.4 pp | |
| | **0.02** | **0.9911** | **29** | **+18.9 pp** | |
| | 0.05 | 0.9851 | 19 | +18.3 pp | |
| | 0.1 | 0.9667 | 149 | +16.4 pp | |
|
|
| > Thesis reports: **+18.8 pp** separation loss gain β
|
|
|
| ### K Ablation (Monte Carlo Trials, seed=42) |
|
|
| | K | AUROC | Time/sample | |
| |---|---|---| |
| | 1 | 0.9100 | 0.010 s | |
| | 5 | 0.9724 | 0.049 s | |
| | **10** | **0.9819** | **0.097 s** | |
| | 25 | 0.9852 | 0.243 s | |
| | 50 | 0.9864 | 0.486 s | |
| | 100 | 0.9869 | 0.972 s | |
|
|
| > K=10 is the thesis default β best accuracy-efficiency trade-off. |
|
|
| ### External OOD Generalization (seed=42) |
|
|
| | Dataset | AUROC | |
| |---|---| |
| | CIFAR-10 (within-split) | **0.9898** | |
| | Food101 | 0.9927 | |
| | CIFAR-100 | 0.9697 | |
| | STL-10 | 0.9521 | |
| | FashionMNIST | 0.9403 | |
| | Textures | 0.9284 | |
| | SVHN | 0.9050 | |
|
|
| --- |
|
|
| ## Architecture |
|
|
| ``` |
| CIFAR-10 image (32Γ32Γ3) + noisy version x_t |
| β |
| βββββββββΌβββββββββββββββββββββββββββββββββ |
| β UNet2DModel (HuggingFace Diffusers) β |
| β block_out_channels: (128, 256, 256, 256) β |
| β Attention: at 16Γ16 resolution β |
| β Class conditioning: 2 embeddings β |
| β (c=0: ID class, c=1: OOD proxy) β |
| βββββββββ¬βββββββββββββββββββββββββββββββββ |
| β predicted noise Ξ΅Μ |
| βββββββββΌβββββββββββββββββββββββββββββββββ |
| β Algorithm 1 Scoring (K=10 trials) β |
| β score = mean_t[e(x,t,c=0) β e(x,t,c=1)] β |
| β e(x,t,c) = ||Ξ΅ β Ξ΅Μ(x_t,t,c)||Β² β |
| ββββββββββββββββββββββββββββββββββββββββββ |
| ``` |
|
|
| - **Parameters:** 68.79 M |
| - **Diffusion schedule:** Cosine cap (`squaredcos_cap_v2`), T=1000 |
| - **Training:** 200 epochs, AdamW (lr=1e-4), batch=64, AMP 16-bit |
| - **Separation loss:** pushes ID/OOD class embeddings apart; Ξ»=0.02 is optimal |
|
|
| --- |
|
|
| ## Repository Contents |
|
|
| ``` |
| ahmed-3m/DiffusionOOD (HuggingFace) |
| βββ models/ |
| β βββ main_training/ |
| β β βββ seed42_best_auroc0.9873.ckpt β thesis headline model |
| β β βββ seed123_best_auroc0.9886.ckpt |
| β β βββ seed456_best_auroc0.9887.ckpt |
| β βββ separation_loss_ablation/ |
| β β βββ sep_loss_lambda_0p0_epoch79_auroc0.8025.ckpt |
| β β βββ sep_loss_lambda_0p02_epoch29_auroc0.9911.ckpt |
| β β βββ sep_loss_lambda_0p1_epoch149_auroc0.9667.ckpt |
| β βββ raw_scores/ |
| β βββ seed42_cifar10_id_scores.pt β 1000 ID scores |
| β βββ seed42_cifar10_ood_scores.pt β 9000 OOD scores |
| ``` |
|
|
| --- |
|
|
| ## Citation |
|
|
| ```bibtex |
| @mastersthesis{mohammed2026diffusionood, |
| title = {Conditional Diffusion Models as Generative Classifiers for |
| Out-of-Distribution Detection in Inkjet Print Quality Control}, |
| author = {Mohammed, Ahmed}, |
| school = {Johannes Kepler University Linz}, |
| year = {2026}, |
| type = {Master's Thesis} |
| } |
| ``` |
|
|
| --- |
|
|
| ## Companion Repository |
|
|
| The **InkjetOOD** companion applies the same CDM approach to industrial inkjet print quality control: |
| - GitHub: [https://github.com/ahmed-3m/InkjetOOD](https://github.com/ahmed-3m/InkjetOOD) |
| - HuggingFace: [https://huggingface.co/ahmed-3m/InkjetOOD](https://huggingface.co/ahmed-3m/InkjetOOD) |
|
|
| --- |
|
|
| ## License |
|
|
| MIT License β see the [GitHub repo](https://github.com/ahmed-3m/DiffusionOOD) for the LICENSE file. |
|
|