ahmed-farhanur-rashid commited on
Commit
bf0ad7e
·
verified ·
1 Parent(s): 36cfa00

Upload GradeEye baseline-3ch-unbalanced checkpoints

Browse files
README.md CHANGED
@@ -1,3 +1,47 @@
1
  ---
2
  license: cc-by-nc-4.0
 
 
 
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  license: cc-by-nc-4.0
3
+ tags:
4
+ - medical-imaging
5
+ - diabetic-retinopathy
6
+ - domain-generalization
7
+ - pytorch
8
+ pipeline_tag: image-classification
9
+ library_name: pytorch
10
  ---
11
+
12
+ # GradeEye baseline-3ch-unbalanced
13
+
14
+ This repository contains GradeEye CORN ordinal diabetic-retinopathy classifiers using the `convnext_tiny` backbone at 384x384 resolution, with 3-channel input and a 4-threshold ordinal head. The `_ema.safetensors` file is the **primary** artifact: the paper's reported evaluation metrics were generated using the EMA state dict. The unsuffixed `.safetensors` file is the corresponding raw `model_state_dict` secondary artifact.
15
+
16
+ ## Checkpoints
17
+
18
+ | Primary EMA weights | Raw secondary weights | Architecture | Held-out fold | Best QWK | Epoch |
19
+ |---|---|---|---|---:|---:|
20
+ | `lodo_aptos_convnext_tiny_best_ema.safetensors` | `lodo_aptos_convnext_tiny_best.safetensors` | `convnext_tiny` | aptos | 0.7672 | 5 |
21
+ | `lodo_ddr_convnext_tiny_best_ema.safetensors` | `lodo_ddr_convnext_tiny_best.safetensors` | `convnext_tiny` | ddr | 0.7473 | 8 |
22
+ | `lodo_eyepacs_convnext_tiny_best_ema.safetensors` | `lodo_eyepacs_convnext_tiny_best.safetensors` | `convnext_tiny` | eyepacs | 0.8267 | 9 |
23
+ | `lodo_messidor2_convnext_tiny_best_ema.safetensors` | `lodo_messidor2_convnext_tiny_best.safetensors` | `convnext_tiny` | messidor2 | 0.7614 | 8 |
24
+
25
+ ## Preprocessing
26
+
27
+ 1. Resize the RGB fundus image to 384x384 using the same offline preprocessing pipeline.
28
+ 2. Convert RGB to float in [0,1] and apply ImageNet normalization: mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225).
29
+
30
+ ## Loading
31
+
32
+ ```python
33
+ import json
34
+ from modeling import load_model
35
+
36
+ config = json.load(open('config.json'))
37
+ model = load_model('lodo_eyepacs_convnext_tiny_best_ema.safetensors', config)
38
+ # model(x) returns CORN logits with shape (batch, 4)
39
+ ```
40
+
41
+ Install `torch`, `timm`, and `safetensors`, and make the GradeEye source repository available on `PYTHONPATH`.
42
+
43
+ ## Intended use and limitations
44
+
45
+ These weights are released for research and reproducibility only. They are not validated for clinical diagnosis or treatment decisions. Performance varies substantially by held-out dataset and should not be interpreted as clinical-grade generalization.
46
+
47
+ Source code and paper materials: [https://github.com/ahmed-farhanur-rashid/gradeeye](https://github.com/ahmed-farhanur-rashid/gradeeye).
aptos/convnext_tiny/config.json ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "DRGradingModel",
3
+ "task": "diabetic-retinopathy-grading",
4
+ "architecture": "convnext_tiny",
5
+ "backbone_timm_name": "convnext_tiny",
6
+ "in_channels": 3,
7
+ "image_size": 384,
8
+ "num_classes": 5,
9
+ "ordinal_head": "CORN",
10
+ "num_thresholds": 4,
11
+ "use_cbam": true,
12
+ "cbam_num_stages": 2,
13
+ "head_hidden_dim": 512,
14
+ "dropout": 0.4,
15
+ "channels_last": true,
16
+ "ema_decay": 0.999,
17
+ "loss_type": "corn",
18
+ "use_class_weighting": true,
19
+ "use_mixup": true,
20
+ "primary_weights": "lodo_aptos_convnext_tiny_best_ema.safetensors",
21
+ "secondary_weights": "lodo_aptos_convnext_tiny_best.safetensors",
22
+ "normalization": {
23
+ "rgb": {
24
+ "mean": [
25
+ 0.485,
26
+ 0.456,
27
+ 0.406
28
+ ],
29
+ "std": [
30
+ 0.229,
31
+ 0.224,
32
+ 0.225
33
+ ]
34
+ },
35
+ "extra_channel": "Already in [0,1]; appended after RGB normalization; not ImageNet-normalized."
36
+ },
37
+ "class_names": [
38
+ "No DR",
39
+ "Mild",
40
+ "Moderate",
41
+ "Severe",
42
+ "Proliferative DR"
43
+ ],
44
+ "held_out_fold": "aptos"
45
+ }
aptos/convnext_tiny/lodo_aptos_convnext_tiny_best.meta.json ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "best_metric": 0.7672482679140789,
3
+ "checkpoint_source": "saved/checkpoints/baseline_3ch_unbalanced/aptos/convnext_tiny/lodo_aptos_convnext_tiny_best.pt",
4
+ "class_names": [
5
+ "No DR",
6
+ "Mild",
7
+ "Moderate",
8
+ "Severe",
9
+ "Proliferative DR"
10
+ ],
11
+ "ema_state_dict_present": true,
12
+ "epoch": 5,
13
+ "global_step": 30401,
14
+ "phase_name": "phase2_full_training",
15
+ "primary_weights": "lodo_aptos_convnext_tiny_best_ema.safetensors",
16
+ "primary_weights_kind": "ema",
17
+ "secondary_weights": "lodo_aptos_convnext_tiny_best.safetensors",
18
+ "secondary_weights_kind": "raw_model_state_dict",
19
+ "training_config": {
20
+ "arch": "convnext_tiny",
21
+ "cbam_num_stages": 2,
22
+ "channels_last": true,
23
+ "dropout": 0.4,
24
+ "ema_decay": 0.999,
25
+ "head_hidden_dim": 512,
26
+ "img_size": 384,
27
+ "in_chans": 3,
28
+ "loss_type": "corn",
29
+ "num_thresholds": 4,
30
+ "phase_batches": {
31
+ "phase1_frozen": 64,
32
+ "phase2_full_training": 24
33
+ },
34
+ "use_cbam": true,
35
+ "use_class_weighting": true,
36
+ "use_mixup": true
37
+ }
38
+ }
aptos/convnext_tiny/lodo_aptos_convnext_tiny_best.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:39357b2e7109b81e7b71e86f1414e426189f4a051077c400231b411249b38275
3
+ size 113269368
aptos/convnext_tiny/lodo_aptos_convnext_tiny_best_ema.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b9316ac4d4e9c65c411535b8bf04ebac837ee69425a736ae0852b1e015803aab
3
+ size 113269368
ddr/convnext_tiny/config.json ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "DRGradingModel",
3
+ "task": "diabetic-retinopathy-grading",
4
+ "architecture": "convnext_tiny",
5
+ "backbone_timm_name": "convnext_tiny",
6
+ "in_channels": 3,
7
+ "image_size": 384,
8
+ "num_classes": 5,
9
+ "ordinal_head": "CORN",
10
+ "num_thresholds": 4,
11
+ "use_cbam": true,
12
+ "cbam_num_stages": 2,
13
+ "head_hidden_dim": 512,
14
+ "dropout": 0.4,
15
+ "channels_last": true,
16
+ "ema_decay": 0.999,
17
+ "loss_type": "corn",
18
+ "use_class_weighting": true,
19
+ "use_mixup": true,
20
+ "primary_weights": "lodo_ddr_convnext_tiny_best_ema.safetensors",
21
+ "secondary_weights": "lodo_ddr_convnext_tiny_best.safetensors",
22
+ "normalization": {
23
+ "rgb": {
24
+ "mean": [
25
+ 0.485,
26
+ 0.456,
27
+ 0.406
28
+ ],
29
+ "std": [
30
+ 0.229,
31
+ 0.224,
32
+ 0.225
33
+ ]
34
+ },
35
+ "extra_channel": "Already in [0,1]; appended after RGB normalization; not ImageNet-normalized."
36
+ },
37
+ "class_names": [
38
+ "No DR",
39
+ "Mild",
40
+ "Moderate",
41
+ "Severe",
42
+ "Proliferative DR"
43
+ ],
44
+ "held_out_fold": "ddr"
45
+ }
ddr/convnext_tiny/lodo_ddr_convnext_tiny_best.meta.json ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "best_metric": 0.7473319600612535,
3
+ "checkpoint_source": "saved/checkpoints/baseline_3ch_unbalanced/ddr/convnext_tiny/lodo_ddr_convnext_tiny_best.pt",
4
+ "class_names": [
5
+ "No DR",
6
+ "Mild",
7
+ "Moderate",
8
+ "Severe",
9
+ "Proliferative DR"
10
+ ],
11
+ "ema_state_dict_present": true,
12
+ "epoch": 8,
13
+ "global_step": 38376,
14
+ "phase_name": "phase2_full_training",
15
+ "primary_weights": "lodo_ddr_convnext_tiny_best_ema.safetensors",
16
+ "primary_weights_kind": "ema",
17
+ "secondary_weights": "lodo_ddr_convnext_tiny_best.safetensors",
18
+ "secondary_weights_kind": "raw_model_state_dict",
19
+ "training_config": {
20
+ "arch": "convnext_tiny",
21
+ "cbam_num_stages": 2,
22
+ "channels_last": true,
23
+ "dropout": 0.4,
24
+ "ema_decay": 0.999,
25
+ "head_hidden_dim": 512,
26
+ "img_size": 384,
27
+ "in_chans": 3,
28
+ "loss_type": "corn",
29
+ "num_thresholds": 4,
30
+ "phase_batches": {
31
+ "phase1_frozen": 64,
32
+ "phase2_full_training": 24
33
+ },
34
+ "use_cbam": true,
35
+ "use_class_weighting": true,
36
+ "use_mixup": true
37
+ }
38
+ }
ddr/convnext_tiny/lodo_ddr_convnext_tiny_best.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6a17214b79a0ccd5220b8fce1c35cd4d7975d7e9d509c8a0c58848a11f4dd356
3
+ size 113269368
ddr/convnext_tiny/lodo_ddr_convnext_tiny_best_ema.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f1a3a5f3e320599d1f874b87f3f12fd497f33316b4a11d73d463075eb83936a6
3
+ size 113269368
eyepacs/convnext_tiny/config.json ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "DRGradingModel",
3
+ "task": "diabetic-retinopathy-grading",
4
+ "architecture": "convnext_tiny",
5
+ "backbone_timm_name": "convnext_tiny",
6
+ "in_channels": 3,
7
+ "image_size": 384,
8
+ "num_classes": 5,
9
+ "ordinal_head": "CORN",
10
+ "num_thresholds": 4,
11
+ "use_cbam": true,
12
+ "cbam_num_stages": 2,
13
+ "head_hidden_dim": 512,
14
+ "dropout": 0.4,
15
+ "channels_last": true,
16
+ "ema_decay": 0.999,
17
+ "loss_type": "corn",
18
+ "use_class_weighting": true,
19
+ "use_mixup": true,
20
+ "primary_weights": "lodo_eyepacs_convnext_tiny_best_ema.safetensors",
21
+ "secondary_weights": "lodo_eyepacs_convnext_tiny_best.safetensors",
22
+ "normalization": {
23
+ "rgb": {
24
+ "mean": [
25
+ 0.485,
26
+ 0.456,
27
+ 0.406
28
+ ],
29
+ "std": [
30
+ 0.229,
31
+ 0.224,
32
+ 0.225
33
+ ]
34
+ },
35
+ "extra_channel": "Already in [0,1]; appended after RGB normalization; not ImageNet-normalized."
36
+ },
37
+ "class_names": [
38
+ "No DR",
39
+ "Mild",
40
+ "Moderate",
41
+ "Severe",
42
+ "Proliferative DR"
43
+ ],
44
+ "held_out_fold": "eyepacs"
45
+ }
eyepacs/convnext_tiny/lodo_eyepacs_convnext_tiny_best.meta.json ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "best_metric": 0.8266749999777263,
3
+ "checkpoint_source": "saved/checkpoints/baseline_3ch_unbalanced/eyepacs/convnext_tiny/lodo_eyepacs_convnext_tiny_best.pt",
4
+ "class_names": [
5
+ "No DR",
6
+ "Mild",
7
+ "Moderate",
8
+ "Severe",
9
+ "Proliferative DR"
10
+ ],
11
+ "ema_state_dict_present": true,
12
+ "epoch": 9,
13
+ "global_step": 7980,
14
+ "phase_name": "phase2_full_training",
15
+ "primary_weights": "lodo_eyepacs_convnext_tiny_best_ema.safetensors",
16
+ "primary_weights_kind": "ema",
17
+ "secondary_weights": "lodo_eyepacs_convnext_tiny_best.safetensors",
18
+ "secondary_weights_kind": "raw_model_state_dict",
19
+ "training_config": {
20
+ "arch": "convnext_tiny",
21
+ "cbam_num_stages": 2,
22
+ "channels_last": true,
23
+ "dropout": 0.4,
24
+ "ema_decay": 0.999,
25
+ "head_hidden_dim": 512,
26
+ "img_size": 384,
27
+ "in_chans": 3,
28
+ "loss_type": "corn",
29
+ "num_thresholds": 4,
30
+ "phase_batches": {
31
+ "phase1_frozen": 64,
32
+ "phase2_full_training": 24
33
+ },
34
+ "use_cbam": true,
35
+ "use_class_weighting": true,
36
+ "use_mixup": true
37
+ }
38
+ }
eyepacs/convnext_tiny/lodo_eyepacs_convnext_tiny_best.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cf33c29fd1fa7133951086f77d4c739f64b53c3db64e4849d104d5a4da13249d
3
+ size 113269368
eyepacs/convnext_tiny/lodo_eyepacs_convnext_tiny_best_ema.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d03e5f0882bdeddf293992f7ce4589feb867f8e27671ed6537ac175442ca17ba
3
+ size 113269368
messidor2/convnext_tiny/config.json ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "DRGradingModel",
3
+ "task": "diabetic-retinopathy-grading",
4
+ "architecture": "convnext_tiny",
5
+ "backbone_timm_name": "convnext_tiny",
6
+ "in_channels": 3,
7
+ "image_size": 384,
8
+ "num_classes": 5,
9
+ "ordinal_head": "CORN",
10
+ "num_thresholds": 4,
11
+ "use_cbam": true,
12
+ "cbam_num_stages": 2,
13
+ "head_hidden_dim": 512,
14
+ "dropout": 0.4,
15
+ "channels_last": true,
16
+ "ema_decay": 0.999,
17
+ "loss_type": "corn",
18
+ "use_class_weighting": true,
19
+ "use_mixup": true,
20
+ "primary_weights": "lodo_messidor2_convnext_tiny_best_ema.safetensors",
21
+ "secondary_weights": "lodo_messidor2_convnext_tiny_best.safetensors",
22
+ "normalization": {
23
+ "rgb": {
24
+ "mean": [
25
+ 0.485,
26
+ 0.456,
27
+ 0.406
28
+ ],
29
+ "std": [
30
+ 0.229,
31
+ 0.224,
32
+ 0.225
33
+ ]
34
+ },
35
+ "extra_channel": "Already in [0,1]; appended after RGB normalization; not ImageNet-normalized."
36
+ },
37
+ "class_names": [
38
+ "No DR",
39
+ "Mild",
40
+ "Moderate",
41
+ "Severe",
42
+ "Proliferative DR"
43
+ ],
44
+ "held_out_fold": "messidor2"
45
+ }
messidor2/convnext_tiny/lodo_messidor2_convnext_tiny_best.meta.json ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "best_metric": 0.7614299089140587,
3
+ "checkpoint_source": "saved/checkpoints/baseline_3ch_unbalanced/messidor2/convnext_tiny/lodo_messidor2_convnext_tiny_best.pt",
4
+ "class_names": [
5
+ "No DR",
6
+ "Mild",
7
+ "Moderate",
8
+ "Severe",
9
+ "Proliferative DR"
10
+ ],
11
+ "ema_state_dict_present": true,
12
+ "epoch": 8,
13
+ "global_step": 42767,
14
+ "phase_name": "phase2_full_training",
15
+ "primary_weights": "lodo_messidor2_convnext_tiny_best_ema.safetensors",
16
+ "primary_weights_kind": "ema",
17
+ "secondary_weights": "lodo_messidor2_convnext_tiny_best.safetensors",
18
+ "secondary_weights_kind": "raw_model_state_dict",
19
+ "training_config": {
20
+ "arch": "convnext_tiny",
21
+ "cbam_num_stages": 2,
22
+ "channels_last": true,
23
+ "dropout": 0.4,
24
+ "ema_decay": 0.999,
25
+ "head_hidden_dim": 512,
26
+ "img_size": 384,
27
+ "in_chans": 3,
28
+ "loss_type": "corn",
29
+ "num_thresholds": 4,
30
+ "phase_batches": {
31
+ "phase1_frozen": 64,
32
+ "phase2_full_training": 24
33
+ },
34
+ "use_cbam": true,
35
+ "use_class_weighting": true,
36
+ "use_mixup": true
37
+ }
38
+ }
messidor2/convnext_tiny/lodo_messidor2_convnext_tiny_best.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d640a2da066f443b49633089bcb40f92472c5bb86378f9f05151fe43468cb767
3
+ size 113269368
messidor2/convnext_tiny/lodo_messidor2_convnext_tiny_best_ema.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:13c802babb4ac10af955eade70f1e6d0991c1cbbc2929f7074bfedb99bd1b296
3
+ size 113269368
modeling.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Minimal GradeEye classifier loader for Hugging Face Hub.
2
+
3
+ Requires the GradeEye source package on PYTHONPATH plus torch, timm, and
4
+ safetensors. The architecture is the same DRGradingModel used during training.
5
+ EMA files are the primary weights and reproduce the paper evaluation protocol.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ from pathlib import Path
10
+ import sys
11
+ import torch
12
+
13
+ # For local source checkout usage. Users may instead install the GradeEye package.
14
+ try:
15
+ from src.models.dr_model import DRGradingModel
16
+ except ImportError as exc:
17
+ raise ImportError(
18
+ "Install/clone GradeEye and make its repository root available on PYTHONPATH."
19
+ ) from exc
20
+ from safetensors.torch import load_file
21
+
22
+
23
+ def load_model(weights_path: str | Path, config: dict, device: str = "cpu") -> DRGradingModel:
24
+ """Instantiate DRGradingModel and strictly load a .safetensors state dict."""
25
+ model = DRGradingModel(
26
+ pretrained=False,
27
+ use_cbam=config["use_cbam"],
28
+ cbam_num_stages=config["cbam_num_stages"],
29
+ num_thresholds=config["num_thresholds"],
30
+ head_hidden_dim=config["head_hidden_dim"],
31
+ dropout=config["dropout"],
32
+ output_mode="corn",
33
+ arch=config["architecture"],
34
+ in_chans=config["in_channels"],
35
+ img_size=config["image_size"],
36
+ )
37
+ state_dict = load_file(str(weights_path), device="cpu")
38
+ result = model.load_state_dict(state_dict, strict=True)
39
+ if result.missing_keys or result.unexpected_keys:
40
+ raise RuntimeError(
41
+ f"State-dict mismatch: missing={result.missing_keys}, "
42
+ f"unexpected={result.unexpected_keys}"
43
+ )
44
+ return model.to(device).eval()