--- license: other base_model: LiquidAI/LFM2.5-VL-450M library_name: transformers tags: - vision-language - remote-sensing - illegal-mining - image-classification pipeline_tag: image-text-to-text --- # sentinel-lfm — LFM2.5-VL-450M FULL fine-tune v2 (improved recipe) All-layers fine-tune of LiquidAI/LFM2.5-VL-450M with an improved training recipe over `ASTRALK/sentinel-lfm-mining-450m-full`: **(1)** all 1965 train patches (no downsampling) + class-weighted loss, **(2)** validation-based best-checkpoint selection (balanced accuracy), **(3)** weight decay, longer schedule. Replies `{"mine_present": true|false}`. ## Results on the held-out test split (419 patches, 303 pos / 116 neg) | model | acc | F1 | recall | recall_neg | precision | |-------|-----|----|--------|-----------|-----------| | base (zero-shot) | 0.7208 | 0.8326 | 0.9604 | 0.0948 | 0.7348 | | LoRA fine-tuned | 0.7995 | 0.8645 | 0.8845 | 0.5776 | 0.8454 | | FULL fine-tuned (v1) | 0.8138 | 0.8754 | 0.9043 | 0.5776 | 0.8483 | | **FULL fine-tuned v2 (this)** | 0.8353 | 0.8900 | 0.9208 | 0.6121 | 0.8611 | ## Training - FULL fine-tune, 448718848 params, class-weighted loss - 6 epochs, lr=2e-05 (warmup->cosine), wd=0.01 - best checkpoint by val balanced-acc: epoch 1 (bal_acc=0.7713) - bf16 autocast + gradient checkpointing, ~25.8 min on H100 ## Usage ```python from transformers import AutoProcessor, AutoModelForImageTextToText from transformers.image_utils import load_image model = AutoModelForImageTextToText.from_pretrained("ASTRALK/sentinel-lfm-mining-450m-full-v2", dtype="bfloat16", device_map="auto") proc = AutoProcessor.from_pretrained("ASTRALK/sentinel-lfm-mining-450m-full-v2") img = load_image("patch.png") conv = [{"role":"user","content":[ {"type":"image","image":img}, {"type":"text","text":'Does this satellite patch show illegal mining? Reply with only this JSON: {"mine_present": true} or {"mine_present": false}'}]}] inp = proc.apply_chat_template(conv, add_generation_prompt=True, return_tensors="pt", return_dict=True, tokenize=True).to(model.device) print(proc.decode(model.generate(**inp, max_new_tokens=16)[0][inp["input_ids"].shape[1]:], skip_special_tokens=True)) ```