InkjetOOD β Pretrained Models & Dataset
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 Β· Industrial Partner: PROFACTOR GmbH
What Is This?
This HuggingFace repository stores all artifacts for the inkjet print quality control experiments from the above thesis:
- Trained model weights (CDM + YOLO feature detector)
- Inkjet print dataset (FTI_Zer0P format: images + labels)
- All experiment results (metrics, score CSVs, figures, tables)
The code lives on GitHub: https://github.com/ahmed-3m/InkjetOOD
Quick Start
Option A β Evaluate the pretrained model (fastest, ~5 min)
# 1. Clone the code repo
git clone https://github.com/ahmed-3m/InkjetOOD
cd InkjetOOD
pip install -r requirements.txt
# 2. Download weights from this HF repo
python download_weights.py
# 3. Set your dataset path
export INKJET_DATA_DIR=/path/to/FTI_Zer0P_dataset
# 4. Evaluate
python evaluate.py \
--checkpoint models/cdm_proposed.pt \
--num_trials 100 \
--out_dir results/eval_pretrained
Expected: AUROC β 0.860 (single-split, N=266 test samples, seed=42).
Option B β Train from scratch (single split)
export INKJET_DATA_DIR=/path/to/FTI_Zer0P_dataset
python download_weights.py # fetches YOLO weights
# Baseline (Ξ»=0)
python train.py --epochs 100 --batch_size 128 --sep_loss_weight 0.0 \
--eval_after --out_dir results/train_baseline
# Proposed (Ξ»=0.01)
python train.py --epochs 100 --batch_size 64 --sep_loss_weight 0.01 \
--eval_after --out_dir results/train_proposed
Option C β 5-Fold cross-validation (thesis main result)
export INKJET_DATA_DIR=/path/to/FTI_Zer0P_dataset
# Reproduces thesis Table 6.x: AUROC 0.8673 Β± 0.023
python run_cv.py \
--sep_loss_weight 0.0 \
--epochs 100 --batch_size 128 \
--num_trials 50 --n_folds 5 --seed 42 \
--out_dir results/cv_lambda0
Step-by-Step: Load and Use Pretrained Weights
Step 1 β Download weights
Using the helper script (recommended):
git clone https://github.com/ahmed-3m/InkjetOOD && cd InkjetOOD
python download_weights.py
Or download manually from this repo's models/ folder:
from huggingface_hub import hf_hub_download
import torch
# Download the proposed CDM (Ξ»=0.01, single-split AUROC 0.860)
path = hf_hub_download(repo_id="ahmed-3m/InkjetOOD", filename="models/cdm_v3_yolo_bbox.pt")
ckpt = torch.load(path, map_location="cpu", weights_only=False)
state_dict = ckpt["state_dict"] # or ckpt["model_state_dict"]
print(f"Loaded {sum(v.numel() for v in state_dict.values()):,} parameters")
Step 2 β Load the model
from src.model import NoisePredictorV3
from src.diffusion import DiffusionSchedule
device = "cuda"
model = NoisePredictorV3(base_channels=64).to(device)
schedule = DiffusionSchedule(schedule="cosine", device=device)
ckpt = torch.load("models/cdm_proposed.pt", map_location=device)
model.load_state_dict(ckpt["model_state_dict"])
model.eval()
print("Model loaded.")
Step 3 β Run evaluation
from src.evaluate import evaluate_cdm, save_results
# ... (set up test_loader with your data)
scores_df = evaluate_cdm(model, schedule, test_loader, num_trials=100, device=device)
save_results(scores_df, out_dir="results/my_eval")
For full data loading details, see evaluate.py in the GitHub repo.
Step 4 β Load the YOLO detector
from ultralytics import YOLO
yolo = YOLO("models/yolo_best.pt")
results = yolo("path/to/print_image.png", conf=0.3)
# Each detection is one print feature crop
Models
| File | Description | AUROC | Params |
|---|---|---|---|
models/cdm_v3_yolo_bbox.pt |
CDM Ξ»=0.01, base_ch=64 (proposed) | 0.8603 single-split | 9.33 M |
models/cdm_v3_baseline.pt |
CDM Ξ»=0, base_ch=128 (thesis CV result) | 0.8673 Β± 0.023 CV | 34.2 M |
models/cdm_v3_test.pt |
CDM Ξ»=0.01, base_ch=64 (dev checkpoint) | β0.85 | 9.33 M |
models/yolo_best.pt |
YOLOv8 feature detector (8 print features) | mAP@50=0.950 | 25.86 M |
models/semantic_mismatch_angle_model.pt |
Per-feature CDM: angle (~9.67:1 imbalance) | ~0.82 | 8.94 M |
models/semantic_mismatch_dist1_model.pt |
Per-feature CDM: dist1 | ~0.89 | 8.94 M |
models/semantic_mismatch_dots_model.pt |
Per-feature CDM: dots (best feature) | ~0.96 | 8.94 M |
Which model should I use?
- Quick evaluation:
cdm_v3_yolo_bbox.ptβ the thesis "proposed CDM", Ξ»=0.01, base_ch=64 (9.33 M params) - Reproducing the thesis CV result:
cdm_v3_baseline.ptβ Ξ»=0, base_ch=128 (34.2 M params); the 5-fold CV AUROC 0.8673 Β± 0.023 comes from this wider model - YOLO feature detection only:
yolo_best.pt(25.86 M params, YOLOv8-based) - Per-feature analysis:
semantic_mismatch_*.ptβ one model per feature, 8.94 M each, trained with a DiffGuard-style contrastive approach
Why does the baseline win on CV? On this small dataset (~1330 samples), the 5-fold CV shows Ξ»=0 and Ξ»=0.01 are statistically indistinguishable (0.8673 vs 0.8628). The single-split evaluation clearly favors Ξ»=0.01 (+2.8 pp AUROC, β19 pp FPR@95). The thesis reports the CV result as the primary finding since it is more reliable.
Results
5-Fold Cross-Validation (Thesis Main Result)
| Ξ» | Mean AUROC | Std | Mean FPR@95 |
|---|---|---|---|
| 0.0 (baseline) | 0.8673 | 0.023 | 0.563 |
| 0.01 | 0.8628 | 0.029 | 0.552 |
| 0.02 | 0.8510 | 0.033 | 0.624 |
| 0.05 | 0.8670 | 0.026 | 0.570 |
Protocol: 5-fold stratified CV, K=50 Monte Carlo trials, seed=42.
Single-Split Evaluation (N=266 test, seed=42)
| Ξ» | AUROC | FPR@95 | K |
|---|---|---|---|
| 0.0 | 0.8325 | 0.816 | 100 |
| 0.01 | 0.8603 | 0.626 | 100 |
| 0.02 | 0.8541 | 0.661 | 100 |
| 0.05 | 0.8553 | 0.529 | 100 |
Per-Feature AUROC (5-Fold CV, Ξ»=0)
| Feature | AUROC | Std |
|---|---|---|
| dots | 0.956 | 0.035 |
| dist6 | 0.936 | 0.067 |
| dist1 | 0.887 | 0.073 |
| angle | 0.817 | 0.138 |
| edge2 | 0.813 | 0.031 |
| edge1 | 0.796 | 0.138 |
| edge4 | 0.762 | 0.099 |
| edge3 | 0.744 | 0.076 |
YOLO Feature Detector
| Metric | Value |
|---|---|
| Precision | 94.1% |
| Recall | 89.1% |
| mAP@50 | 95.0% |
| mAP@50-95 | 84.7% |
Dataset
The FTI_Zer0P dataset contains inkjet print images with YOLO-format annotations and quality labels.
| Path | Contents |
|---|---|
data/yolo_format_v2/ |
Full YOLO dataset (train/val/test images + labels) |
data/metadata/feature_cls.csv |
Per-sample metadata (feature class, quality label, template type) |
data/crop_examples/ |
Sample 128Γ128 crops for 6 print features |
Contents of This Repository
ahmed-3m/InkjetOOD (HuggingFace)
βββ models/
β βββ cdm_v3_yolo_bbox.pt β CDM Ξ»=0.01 (thesis proposed)
β βββ cdm_v3_baseline.pt β CDM Ξ»=0 baseline (thesis CV result)
β βββ cdm_v3_test.pt β Development checkpoint
β βββ yolo_best.pt β YOLOv8 feature detector
β βββ semantic_mismatch_angle_model.pt
β βββ semantic_mismatch_dist1_model.pt
β βββ semantic_mismatch_dots_model.pt
β
βββ data/
β βββ yolo_format_v2/ β YOLO dataset (images + labels)
β βββ metadata/ β feature_cls.csv, yolo_dataset.yaml
β βββ crop_examples/ β sample crops for 6 features
β
βββ results/
βββ cv_lambda_ablation/ β 5-fold CV results for Ξ» β {0, 0.01, 0.02, 0.05}
βββ single_split_lambda_ablation/ β single-split ablation results
βββ figures/ β all thesis figures (PNG)
βββ tables/ β all thesis tables (LaTeX)
Citation
@mastersthesis{mohammed2026inkjet,
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}
}
License
Code (GitHub): MIT License. Dataset (FTI_Zer0P) and model weights: Creative Commons Attribution 4.0 International (CC BY 4.0).