AI & ML interests
AI models
Recent Activity
Aspaklarya — Qwen3-VL-8B for remote-sensing VQA + captioning
LoRA finetunes of Qwen3-VL-8B-Instruct, trained jointly on visual question answering and image captioning over overhead imagery. 17 experiments, 17 evaluated recipes. All model repos are private.
Setup
| Item | Value |
|---|---|
| Base | Qwen3-VL-8B-Instruct |
| Method | LoRA (Unsloth), 4-bit base, bf16 compute |
| Targets | all linear layers, vision + language towers |
| Data | ~6.3k images, 1 caption + 2 QA each (~18.9k samples) |
| Caption prompts | sampled from a 30-prompt pool, so the model learns the task not one phrasing |
| Eval | fixed 1000-image draw = 2000 graded items, same seed for every model |
| Scoring | LLM-as-judge, 0-100 per item |
| References | stock Qwen3-VL-8B, plus an in-house finetuned model |
Winners are merged into the bf16 base and re-validated: adapters are evaluated on a 4-bit base, merged weights are not.
Configurations
| Model | r / alpha | Dropout | LR | Sched | Vision | Per image | Items | Change |
|---|---|---|---|---|---|---|---|---|
| Aspaklarya-001 | 16 / 16 | 0.0 | 2e-4 | linear | trained | 1c + 2q | 18,864 | reference recipe |
| Aspaklarya-002 | 32 / 64 | 0.05 | 1e-4 | cosine | trained | 1c + 2q | 18,864 | higher rank, lower LR |
| Aspaklarya-003 | 16 / 16 | 0.0 | 2e-4 | linear | trained | 2c + 4q | 37,728 | 2x resampled data |
| Aspaklarya-004 | 16 / 16 | 0.0 | 2e-4 | linear | frozen | 1c + 2q | 18,864 | language-only |
| Aspaklarya-005 | 16 / 16 | 0.0 | 2e-4 | cosine | trained | 1c + 6q | 43,864 | VQA-heavy |
| Aspaklarya-006 | 16 / 16 | 0.0 | 2e-4 | linear | trained | 1c + 2q | 18,864 | batch 4 x accum 8 |
| Aspaklarya-007 | 8 / 8 | 0.0 | 2e-4 | linear | trained | 1c + 2q | 18,864 | low rank |
| Aspaklarya-008 | 16 / 16 | 0.0 | 1e-4 | linear | trained | 1c + 4q | 31,440 | more QA, lower LR |
| Aspaklarya-009 | 32 / 32 | 0.0 | 2e-4 | linear | trained | 1c + 2q | 18,864 | high rank |
| Aspaklarya-010 | 16 / 16 | 0.0 | 2e-4 | linear | trained | 1c + 2q | 18,864 | wider prompt pool |
| Aspaklarya-011 | 16 / 16 | 0.05 | 2e-4 | linear | trained | 1c + 2q | 18,864 | dropout, wd 0.05, clip 1.0 |
| Aspaklarya-012 | 16 / 16 | 0.0 | 2e-4 | linear | trained | 1c + 2q | 18,864 | as 011, no dropout |
| Aspaklarya-013 | 16 / 16 | 0.0 | 1e-4 | linear | trained | 1c + 2q | 18,864 | low LR, long schedule |
| Aspaklarya-014 | 16 / 16 | 0.0 | 2e-4 | linear | trained | 1c + 2q | 18,864 | effective batch 16 |
| Aspaklarya-015 | 16 / 16 | 0.0 | 2e-4 | linear | trained | 1c + 2q | 18,864 | effective batch 64 |
| Aspaklarya-016 | 16 / 16 | 0.0 | 4e-4 | linear | trained | 1c + 2q | 18,864 | batch 64 + linear LR scaling |
| Aspaklarya-017 | 16 / 16 | 0.0 | 3e-4 | linear | trained | 1c + 2q | 18,864 | batch 64 + sqrt LR scaling |
| Aspaklarya-018 | 16 / 16 | 0.0 | 2e-4 | linear | trained | 1c + 2q | 18,864 | bf16 base (no 4-bit) |
| Aspaklarya-019 | 16 / 16 | 0.05 | 2e-4 | linear | trained | 1c + 2q | 18,864 | bf16 base + 011 recipe |
| Aspaklarya-020 | 16 / 16 | 0.0 | 2e-4 | linear | trained | 1c + 2q | 35,981 | bf16 base + +91% data |
Constant everywhere: effective batch 32 (except 014 at 16, 015-017 at 64), warmup 0.03, grad clip 0.3 (1.0 for 011/012), seed 3407.
Results
Best checkpoint per run on a fixed 1000-image draw (2000 graded items), with bootstrap standard error. Overall = mean of caption and VQA. In-dom. = the target overhead-imagery subset (491 images); RSICD = the public RSICD remote-sensing benchmark subset (509 images). Sorted by in-domain overall; bold marks the best value in each column.
| Model | In-dom. cap | In-dom. vqa | In-dom. overall | All cap | All vqa | All overall | RSICD cap | RSICD vqa | RSICD overall |
|---|---|---|---|---|---|---|---|---|---|
| Aspaklarya-011 | 81.85 ±0.66 | 83.51 ±1.48 | 82.68 ±0.84 | 79.92 ±0.49 | 75.78 ±1.13 | 77.85 ±0.64 | 78.06 ±0.67 | 68.33 ±1.64 | 73.20 ±0.92 |
| Aspaklarya-019 | 82.39 ±0.65 | 82.82 ±1.48 | 82.61 ±0.85 | 80.33 ±0.48 | 75.91 ±1.13 | 78.12 ±0.63 | 78.34 ±0.70 | 69.24 ±1.62 | 73.79 ±0.89 |
| Aspaklarya-020 | 82.74 ±0.67 | 82.10 ±1.50 | 82.42 ±0.85 | 81.31 ±0.47 | 76.08 ±1.13 | 78.70 ±0.63 | 79.93 ±0.63 | 70.28 ±1.63 | 75.10 ±0.91 |
| Aspaklarya-001 | 81.84 ±0.66 | 83.23 ±1.44 | 82.54 ±0.81 | 79.97 ±0.48 | 75.94 ±1.12 | 77.95 ±0.63 | 78.17 ±0.69 | 68.89 ±1.66 | 73.53 ±0.93 |
| Aspaklarya-018 | 82.28 ±0.69 | 82.70 ±1.51 | 82.49 ±0.86 | 80.46 ±0.49 | 75.80 ±1.11 | 78.13 ±0.63 | 78.70 ±0.67 | 69.15 ±1.61 | 73.92 ±0.90 |
| Aspaklarya-015 | 82.14 ±0.64 | 82.76 ±1.46 | 82.45 ±0.82 | 80.07 ±0.49 | 74.73 ±1.13 | 77.40 ±0.63 | 78.07 ±0.72 | 66.98 ±1.65 | 72.52 ±0.92 |
| Aspaklarya-006 | 81.40 ±0.71 | 82.95 ±1.50 | 82.18 ±0.90 | 79.81 ±0.50 | 75.79 ±1.12 | 77.80 ±0.65 | 78.26 ±0.68 | 68.88 ±1.63 | 73.57 ±0.91 |
| Aspaklarya-005 | 81.37 ±0.67 | 82.37 ±1.50 | 81.87 ±0.85 | 79.55 ±0.49 | 75.74 ±1.11 | 77.64 ±0.62 | 77.79 ±0.71 | 69.35 ±1.65 | 73.57 ±0.93 |
| Aspaklarya-012 | 81.68 ±0.66 | 82.05 ±1.53 | 81.86 ±0.86 | 79.73 ±0.48 | 75.02 ±1.13 | 77.37 ±0.64 | 77.85 ±0.71 | 68.23 ±1.63 | 73.04 ±0.90 |
| Aspaklarya-014 | 81.51 ±0.67 | 81.93 ±1.48 | 81.72 ±0.83 | 79.95 ±0.49 | 74.77 ±1.13 | 77.36 ±0.63 | 78.45 ±0.71 | 67.87 ±1.66 | 73.16 ±0.92 |
| Aspaklarya-003 | 81.23 ±0.71 | 82.18 ±1.47 | 81.71 ±0.85 | 79.55 ±0.49 | 75.52 ±1.12 | 77.53 ±0.63 | 77.92 ±0.66 | 69.10 ±1.66 | 73.51 ±0.91 |
| Aspaklarya-017 | 81.49 ±0.67 | 81.86 ±1.48 | 81.67 ±0.85 | 79.50 ±0.50 | 75.73 ±1.10 | 77.62 ±0.63 | 77.59 ±0.70 | 69.83 ±1.60 | 73.71 ±0.89 |
| Aspaklarya-001 (ep5) | 80.60 ±0.72 | 82.25 ±1.49 | 81.42 ±0.84 | 79.30 ±0.50 | 76.17 ±1.12 | 77.73 ±0.63 | 78.05 ±0.69 | 70.31 ±1.64 | 74.18 ±0.91 |
| Aspaklarya-013 | 80.58 ±0.69 | 82.20 ±1.48 | 81.39 ±0.84 | 79.11 ±0.49 | 75.35 ±1.10 | 77.23 ±0.61 | 77.70 ±0.69 | 68.74 ±1.60 | 73.22 ±0.90 |
| Aspaklarya-009 | 80.01 ±0.71 | 82.34 ±1.46 | 81.18 ±0.84 | 78.53 ±0.52 | 75.85 ±1.11 | 77.19 ±0.63 | 77.09 ±0.73 | 69.59 ±1.63 | 73.34 ±0.91 |
| Aspaklarya-008 | 80.62 ±0.74 | 81.42 ±1.51 | 81.02 ±0.86 | 79.82 ±0.50 | 75.40 ±1.12 | 77.61 ±0.63 | 79.05 ±0.65 | 69.60 ±1.62 | 74.33 ±0.89 |
| Aspaklarya-007 | 81.13 ±0.71 | 80.82 ±1.51 | 80.97 ±0.86 | 79.33 ±0.51 | 75.33 ±1.12 | 77.33 ±0.64 | 77.60 ±0.70 | 70.03 ±1.62 | 73.81 ±0.90 |
| Aspaklarya-004 | 80.31 ±0.72 | 81.47 ±1.48 | 80.89 ±0.84 | 78.76 ±0.51 | 75.33 ±1.11 | 77.04 ±0.64 | 77.26 ±0.74 | 69.40 ±1.61 | 73.33 ±0.92 |
| Aspaklarya-002 | 80.70 ±0.72 | 80.63 ±1.51 | 80.67 ±0.85 | 79.36 ±0.50 | 74.33 ±1.13 | 76.85 ±0.64 | 78.07 ±0.71 | 68.25 ±1.63 | 73.16 ±0.92 |
| Aspaklarya-010 | 80.50 ±0.74 | 80.66 ±1.58 | 80.58 ±0.90 | 78.88 ±0.52 | 74.28 ±1.13 | 76.58 ±0.64 | 77.32 ±0.72 | 68.12 ±1.65 | 72.72 ±0.91 |
| in-house reference | 71.88 ±1.23 | 83.62 ±1.49 | 77.75 ±1.02 | 65.18 ±0.83 | 73.34 ±1.13 | 69.26 ±0.74 | 58.72 ±1.09 | 63.44 ±1.62 | 61.08 ±1.02 |
| Qwen3-VL-8B (base) | 68.37 ±0.89 | 58.94 ±1.50 | 63.66 ±0.92 | 65.68 ±0.66 | 56.01 ±1.01 | 60.84 ±0.62 | 63.07 ±0.94 | 53.18 ±1.46 | 58.13 ±0.91 |
Every finetune beats both references overall: +17.1 over the base model and +8.7 over the in-house reference on the full set.
Learning rate at large batch
Aspaklarya-015 gave the best captioning in the table at effective batch 64, but it was trained at 2e-4 — the rate tuned for batch 32. Two follow-ups tested whether the batch-64 recipe was simply under-stepped. Scores below come from a separate 500-image draw used for live checkpoint selection, so they compare only with each other.
| LR at batch 64 | ep 1 | ep 2 | ep 3 | ep 4 | ep 5 | Outcome |
|---|---|---|---|---|---|---|
| 2e-4 (015) | 76.92 | 77.03 | 77.25 | 77.64 | 77.92 | peak at epoch 5 |
| 4e-4 (016) | 77.67 | 76.93 | 76.42 | 76.89 | — | stopped at epoch 4, declining |
| 3e-4 (017) | 77.00 | 76.56 | 77.16 | 77.68 | 77.86 | peak at epoch 5, stopped at epoch 6 |
Linear LR scaling is wrong for LoRA here: 4e-4 peaked at epoch 1 and then lost ground at every later checkpoint, ending below where 2e-4 started. The adapter's effective step size does not follow the full-finetune scaling rule, so raising LR with batch size overshoots rather than compensating. The intermediate rate 3e-4 traced almost exactly the same curve as 2e-4 and peaked at the same epoch, one tenth of a point lower.
On the shared 1000-image set, neither batch-64 rate beat the reference: 2e-4 is -0.56 overall and -0.09 in-domain, 3e-4 is -0.34 and -0.87. Effective batch 64 is therefore refuted at every learning rate tried, and the loss is consistently in VQA while captioning holds or improves. Together with the batch-16 result this closes the batch-size and learning-rate axes: no hyperparameter lever remains untested, and further gains have to come from the training data.
Error bars
Bootstrap over images, 3000 resamples. Absolute standard error:
| Slice | Caption | VQA | Overall |
|---|---|---|---|
| All (1000 img) | 0.48 | 1.12 | 0.63 |
| In-domain (491) | 0.66 | 1.46 | 0.82 |
| RSICD (509) | 0.69 | 1.64 | 0.91 |
Paired model-vs-model error is smaller because image difficulty cancels: 0.42 overall on the full set, 0.56 in-domain. Use the paired figure for any "A beats B" claim.
Caveat
The hyperparameter runs are statistically tied with each other: among runs 001-019, every confidence interval against the leader straddles zero. VQA error is ~2.3x caption error, so no finetune-vs-finetune VQA difference in any column is resolvable; only caption gaps, the gaps to the two references, and the data-scaling result of run 020 are real. Doubling the eval set from 500 to 1000 images did not separate the tied field, and it reshuffled its order.
Findings
- Hyperparameters are saturated; data is not. LR, rank, alpha, dropout, weight decay, gradient clipping, batch geometry, effective batch size, LR scaling at large batch and base-weight precision were all swept without beating the noise floor. Adding 91% more training images cleared it on the first attempt.
- The slices disagree — but data breaks the trade. Ranking by in-domain score almost inverts the RSICD ranking, and every hyperparameter lever that moved one slice moved the other the opposite way. Extra data is the exception: it lifted RSICD by 1.57 while leaving in-domain unchanged.
- Captioning is the real gain. It improves on every slice, by +14 over the base model and +10 to +19 over the in-house reference.
- The in-domain VQA win is not established. The in-house reference posts the single highest in-domain VQA score in the table; it collapses outside that domain, where it falls below the untuned base model.
- The vision tower matters. Freezing it is the one ablation that consistently hurt.
- Extra QA per image does not help. 4-QA and 6-QA mixtures tie with 2-QA.
- Larger batch trades generality for domain fit. Effective batch 64 gives the best in-domain captioning in the table and the worst RSICD VQA.
- Training in bf16 instead of 4-bit is a small, consistent positive — the only change in the whole sweep that never loses on any slice — but it is still inside the error bar.
- Data is the remaining lever, not hyperparameters — and it is not exhausted: the run that used it had not converged when its schedule ended.
Base-weight precision
Runs 001-017 all trained their adapters against 4-bit quantized base weights, while evaluation and the final merge both use the bf16 base. That is a train/serve mismatch: the adapter was fitted to compensate for quantization error that is absent at inference time.
Runs 018 and 019 repeat the two strongest recipes with the base loaded in bf16 and nothing else changed. Against the reference, paired on 1000 images:
| run | overall | in-domain | RSICD |
|---|---|---|---|
| Aspaklarya-018 | +0.17 ±0.42 | -0.05 ±0.59 | +0.39 ±0.59 |
| Aspaklarya-019 | +0.16 ±0.40 | +0.07 ±0.57 | +0.25 ±0.57 |
These are the first two runs in the sweep to post a positive overall delta, and 018 is the only run that is not worse than the reference on any slice. Both are still well inside the paired error bar (p = 0.34 that each is in fact worse), so neither is promoted.
The mechanism is not the expected one. Removing quantization error should mostly help the harder task, VQA; instead the gain is entirely in captioning (+0.48 and +0.35) while VQA is flat to slightly negative. That is the same caption-up / VQA-flat signature produced by every other lever in the sweep, which suggests precision is acting through the same saturated channel rather than unlocking anything new.
Removing quantization also costs ~9 GB of GPU memory during training (19 GB vs 10 GB), which is a real constraint on a shared 40 GB card.
Training data
Every run up to 017 trained on 6,288 images / 18,864 samples. The source table also carries 5,706 further images that the dataset author left unassigned (Notes == other, RSICD only). They are fully populated, statistically indistinguishable from the assigned training rows, and have zero image-name overlap with either the train or the validation split, so they are safe to train on.
Aspaklarya-020 adds them, taking training data to 11,994 images / 35,981 samples (+91%). Everything else is identical to 018. Paired against the previous selection on the same 1000 images:
| slice | delta | 95% CI | p(worse) |
|---|---|---|---|
| overall | +0.74 ±0.47 | [-0.17, 1.66] | 0.059 |
| in-domain | -0.12 ±0.63 | [-1.37, 1.10] | 0.570 |
| RSICD | +1.57 ±0.68 | [0.22, 2.87] | 0.012 |
| caption (all) | +1.34 ±0.42 | — | — |
This is the first change in the whole programme to clear the error bar. The RSICD interval excludes zero, and the overall caption gain is 3.2 standard errors. It is also the first result that does not trade one slice against the other: in-domain is a clean tie while the general slice moves.
Two further points matter for anyone repeating this:
- The in-domain penalty is transient. At matched optimizer steps the extra data looked actively harmful early — step 2,360 was 1.65 behind on in-domain — and that deficit had vanished by step 4,500. Stopping early would have refuted the best run in the programme.
- The run never converged. Overall score rose at all seven checkpoints, including the last. Four epochs is too short for this data volume, so the ceiling here is unknown.
More data is therefore the live axis, and the only one still producing movement.
Status
The hyperparameter search is closed. Rank, alpha, dropout, learning rate, schedule, weight decay, gradient clipping, vision-tower freezing, QA-per-image, caption prompt pool, batch geometry, effective batch size, learning rate at large batch and base-weight precision were all swept across 19 recipes under identical conditions. None displaced the reference recipe by more than the paired error bar.
Batch size and learning rate illustrate that ceiling. Effective batch 16 came in at -0.59 overall, batch 64 at 2e-4 at -0.56, and batch 64 at 3e-4 at -0.34 overall and -0.87 in-domain; batch 64 at 4e-4 was stopped at epoch 4 while declining. In each case captioning held steady or improved while VQA fell.
Enlarging the training set did what none of those could. The next steps follow from it: train the same corpus for longer, since run 020 had not converged, and add in-domain imagery, since the gain so far is concentrated in the general slice.