ankitbelbase034 commited on
Commit
f4c5725
·
verified ·
1 Parent(s): 251c4c4

Endo_edge Qwen3-VL-8B LoRA + trained vision encoder, step 1250

Browse files

LoRA r=32 adapters plus the separately-exported trained vision tower (PEFT does not include it). Lowest-validation surviving checkpoint; step 750 had lower val loss but was rotated away.

endoedge_qwen3vl8b_lora_vis_r32/step-1250/README.md ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Endo_edge — Qwen3-VL-8B-Instruct, LoRA + trained vision encoder (step 1250)
2
+
3
+ Instruction fine-tune of `Qwen/Qwen3-VL-8B-Instruct` that reads a GI endoscopy frame
4
+ and emits a unified JSON report. Trained on GastroVision + HyperKvasir + LIMUC
5
+ (29,938 images; 20,836 train / 4,530 val).
6
+
7
+ ## ⚠️ Read this before loading
8
+
9
+ **The adapter alone is not the model.** The vision encoder was trained too, and PEFT
10
+ does not export it — `adapter_model.safetensors` contains 504 LoRA tensors and
11
+ **zero** vision tensors. The 351 trained vision tensors (576.4 M params) are in
12
+ `vision_tower.safetensors` and must be loaded separately, or you silently get the
13
+ stock Qwen vision encoder and lose most of what was trained.
14
+
15
+ Verified against the base checkpoint: every probed vision tensor differs
16
+ (e.g. `blocks.26.mlp.linear_fc2.weight`, max |Δ| 0.040).
17
+
18
+ ## Files
19
+
20
+ | file | contents |
21
+ |---|---|
22
+ | `adapter/` | LoRA r=32 α=64 on q/k/v/o/gate/up/down — 504 tensors, 87.3 M params |
23
+ | `vision_tower.safetensors` | trained vision encoder, bf16 — 351 tensors, 576.4 M params |
24
+ | `training_meta.json` | hyperparameters and the full train/val loss history |
25
+ | `checkpoint_meta.json` | step / epoch stamp from the trainer |
26
+
27
+ ## Loading
28
+
29
+ ```python
30
+ import torch
31
+ from transformers import AutoProcessor, AutoModelForImageTextToText
32
+ from safetensors.torch import load_file
33
+ from peft import PeftModel
34
+
35
+ BASE = "Qwen/Qwen3-VL-8B-Instruct"
36
+ HERE = "." # this folder
37
+
38
+ model = AutoModelForImageTextToText.from_pretrained(BASE, dtype=torch.bfloat16, device_map="auto")
39
+
40
+ # 1. trained vision encoder (keys are already HF-native: model.visual.*)
41
+ missing, unexpected = model.load_state_dict(load_file(f"{HERE}/vision_tower.safetensors"), strict=False)
42
+ assert not unexpected, unexpected # 351 keys must all land
43
+
44
+ # 2. LoRA adapters on the language tower
45
+ model = PeftModel.from_pretrained(model, f"{HERE}/adapter")
46
+ model.eval()
47
+
48
+ processor = AutoProcessor.from_pretrained(BASE, min_pixels=128*128, max_pixels=768*768)
49
+ ```
50
+
51
+ `max_pixels = 768*768` caps the image at ≤576 visual tokens and matches training.
52
+
53
+ ## Output format
54
+
55
+ The model emits **only the keys the image establishes** — absent keys are omitted,
56
+ never returned as `null`. Targets in training carried 2, 4, 5 or 6 of these nine keys:
57
+
58
+ `abnormality_present`, `abnormality_type`, `grade`, `instrument_present`,
59
+ `landmark`, `landmark_certain`, `prep_quality`, `procedure`, `tract`
60
+
61
+ ```json
62
+ {"instrument_present": true, "landmark_certain": false}
63
+ ```
64
+
65
+ `instrument_present` and `landmark_certain` are always present.
66
+ `landmark_certain: false` means the anatomy was **not annotated**, not that anatomy is absent.
67
+
68
+ ## Training
69
+
70
+ bf16, effective batch 44 (micro 22 × accum 2), 3 epochs, 1587 steps, `adamw_8bit`.
71
+ Two parameter groups: adapters at lr 1e-4, the full-rank vision tower at 2e-5.
72
+ Batches are balanced round-robin across the three corpora, and 75 % of each batch
73
+ uses a prompt that names the specific keys that sample supports.
74
+
75
+ | step | train | val |
76
+ |---|---|---|
77
+ | 250 | 0.0143 | 0.0101 |
78
+ | 500 | 0.0180 | 0.0104 |
79
+ | **750** | 0.0129 | **0.0072** |
80
+ | 1000 | 0.0076 | 0.0086 |
81
+ | **1250** | 0.0053 | **0.0092** ← this checkpoint |
82
+ | 1500 | 0.0059 | 0.0097 |
83
+
84
+ Validation bottoms out at step 750 and rises after, while train loss keeps falling —
85
+ the run overfits in the second half. **The step-750 checkpoint no longer exists**
86
+ (rotated away by `keep_last_checkpoints=3`); 1250 is the lowest-validation checkpoint
87
+ that survived.
88
+
89
+ ## Intended use
90
+
91
+ Research artifact. Not a medical device, not validated for clinical use, and not
92
+ evaluated on any external cohort — the three training corpora are the only data it
93
+ has seen, and the source annotations are single-label per image.
endoedge_qwen3vl8b_lora_vis_r32/step-1250/adapter/adapter_config.json ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "alora_invocation_tokens": null,
3
+ "alpha_pattern": {},
4
+ "arrow_config": null,
5
+ "auto_mapping": null,
6
+ "base_model_name_or_path": "Qwen/Qwen3-VL-8B-Instruct",
7
+ "bias": "none",
8
+ "corda_config": null,
9
+ "ensure_weight_tying": false,
10
+ "eva_config": null,
11
+ "exclude_modules": null,
12
+ "fan_in_fan_out": false,
13
+ "inference_mode": true,
14
+ "init_lora_weights": true,
15
+ "layer_replication": null,
16
+ "layers_pattern": null,
17
+ "layers_to_transform": null,
18
+ "loftq_config": {},
19
+ "lora_alpha": 64,
20
+ "lora_bias": false,
21
+ "lora_dropout": 0.05,
22
+ "lora_ga_config": null,
23
+ "megatron_config": null,
24
+ "megatron_core": "megatron.core",
25
+ "modules_to_save": null,
26
+ "monteclora_config": null,
27
+ "peft_type": "LORA",
28
+ "peft_version": "0.20.0",
29
+ "qalora_group_size": 16,
30
+ "r": 32,
31
+ "rank_pattern": {},
32
+ "revision": null,
33
+ "target_modules": [
34
+ "down_proj",
35
+ "gate_proj",
36
+ "k_proj",
37
+ "q_proj",
38
+ "v_proj",
39
+ "o_proj",
40
+ "up_proj"
41
+ ],
42
+ "target_parameters": null,
43
+ "task_type": "CAUSAL_LM",
44
+ "trainable_token_indices": null,
45
+ "use_bdlora": null,
46
+ "use_dora": false,
47
+ "use_qalora": false,
48
+ "use_rslora": false,
49
+ "velora_config": null
50
+ }
endoedge_qwen3vl8b_lora_vis_r32/step-1250/adapter/adapter_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:426758c27b645487074ed199afe56d4f779ee1c912efaaba37b89026528e71df
3
+ size 349251312
endoedge_qwen3vl8b_lora_vis_r32/step-1250/checkpoint_meta.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "step": 1250,
3
+ "epoch": 0,
4
+ "run": "lora_vis_r32",
5
+ "time": 1788112823.6126652
6
+ }
endoedge_qwen3vl8b_lora_vis_r32/step-1250/training_meta.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "run": "lora_vis_r32",
3
+ "base_model": "Qwen/Qwen3-VL-8B-Instruct",
4
+ "step": 1250,
5
+ "total_steps": 1587,
6
+ "epochs": 3,
7
+ "effective_batch": 44,
8
+ "micro_batch": 22,
9
+ "grad_accum": 2,
10
+ "precision": "bf16",
11
+ "optimizer": "adamw_8bit",
12
+ "lr_adapters": 1e-4,
13
+ "lr_vision": 2e-5,
14
+ "lora": {"r": 32, "alpha": 64, "dropout": 0.05,
15
+ "target_modules": ["q_proj","k_proj","v_proj","o_proj","gate_proj","up_proj","down_proj"]},
16
+ "trainable_params": {"adapters": 87293952, "vision_tower": 576400000, "total": 663693952},
17
+ "train_images": 20836,
18
+ "val_images": 4530,
19
+ "validation_loss_by_step": {
20
+ "250": 0.0101, "500": 0.0104, "750": 0.0072,
21
+ "1000": 0.0086, "1250": 0.0092, "1500": 0.0097
22
+ },
23
+ "train_loss_by_step": {
24
+ "250": 0.0143, "500": 0.0180, "750": 0.0129,
25
+ "1000": 0.0076, "1250": 0.0053, "1500": 0.0059
26
+ },
27
+ "note": "step 750 had the lowest validation loss but its checkpoint was rotated away by keep_last_checkpoints=3; 1250 is the lowest-validation checkpoint that still exists"
28
+ }
endoedge_qwen3vl8b_lora_vis_r32/step-1250/vision_tower.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a665bd3c70a58373f95f97823023fb4d0b00621a957eaa0b0ef44f172472ce5d
3
+ size 1152816104