Instructions to use urbanspr1nter/lfm2.5vl-450m-deforestation-classifier with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use urbanspr1nter/lfm2.5vl-450m-deforestation-classifier with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="urbanspr1nter/lfm2.5vl-450m-deforestation-classifier") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("urbanspr1nter/lfm2.5vl-450m-deforestation-classifier") model = AutoModelForMultimodalLM.from_pretrained("urbanspr1nter/lfm2.5vl-450m-deforestation-classifier", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use urbanspr1nter/lfm2.5vl-450m-deforestation-classifier with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16 # Run inference directly in the terminal: llama cli -hf urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16 # Run inference directly in the terminal: llama cli -hf urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16 # Run inference directly in the terminal: ./llama-cli -hf urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16 # Run inference directly in the terminal: ./build/bin/llama-cli -hf urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
Use Docker
docker model run hf.co/urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
- LM Studio
- Jan
- vLLM
How to use urbanspr1nter/lfm2.5vl-450m-deforestation-classifier with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "urbanspr1nter/lfm2.5vl-450m-deforestation-classifier" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "urbanspr1nter/lfm2.5vl-450m-deforestation-classifier", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
- SGLang
How to use urbanspr1nter/lfm2.5vl-450m-deforestation-classifier with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "urbanspr1nter/lfm2.5vl-450m-deforestation-classifier" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "urbanspr1nter/lfm2.5vl-450m-deforestation-classifier", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "urbanspr1nter/lfm2.5vl-450m-deforestation-classifier" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "urbanspr1nter/lfm2.5vl-450m-deforestation-classifier", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Ollama
How to use urbanspr1nter/lfm2.5vl-450m-deforestation-classifier with Ollama:
ollama run hf.co/urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
- Unsloth Desktop
- Pi
How to use urbanspr1nter/lfm2.5vl-450m-deforestation-classifier with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use urbanspr1nter/lfm2.5vl-450m-deforestation-classifier with Docker Model Runner:
docker model run hf.co/urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
- Lemonade
How to use urbanspr1nter/lfm2.5vl-450m-deforestation-classifier with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
Run and chat with the model
lemonade run user.lfm2.5vl-450m-deforestation-classifier-F16
List all available models
lemonade list
- Hermes Agent
How to use urbanspr1nter/lfm2.5vl-450m-deforestation-classifier with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use urbanspr1nter/lfm2.5vl-450m-deforestation-classifier with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "urbanspr1nter/lfm2.5vl-450m-deforestation-classifier:F16" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
| license: other | |
| license_name: lfm-open-license-v1.0 | |
| license_link: LICENSE | |
| base_model: LiquidAI/LFM2.5-VL-450M | |
| tags: | |
| - vision-language | |
| - image-classification | |
| - satellite-imagery | |
| - sentinel-2 | |
| - deforestation | |
| - earth-observation | |
| - lfm2 | |
| - llama-cpp | |
| - gguf | |
| - fine-tuned | |
| - hackathon | |
| language: | |
| - en | |
| library_name: transformers | |
| pipeline_tag: image-text-to-text | |
| # LFM2.5-VL-450M Deforestation Classifier | |
| A fine-tuned variant of [`LiquidAI/LFM2.5-VL-450M`](https://huggingface.co/LiquidAI/LFM2.5-VL-450M) that classifies a 1 km Γ 1 km Sentinel-2 false-color tile into one of three deforestation classes: | |
| - `STANDING_FOREST` β currently forested (β₯ 50 % canopy in 2000, no recent loss) | |
| - `RECENTLY_CLEARED` β was forested, cleared in the last ~5 years | |
| - `LONG_TERM_NON_FOREST` β has not been forest in recent decades (urban, pasture, agriculture, water, bare rock) | |
| Trained on Brazilian Amazon and Cerrado deforestation imagery; evaluated on a held-out Cambodia test split to demonstrate cross-continental generalization. Ships as a 218 MB **Q4_K_M GGUF** for direct deployment via [`llama.cpp`](https://github.com/ggml-org/llama.cpp) on commodity edge hardware (validated on an AMD Ryzen 5 5600U mini-PC with Vega 7 iGPU). | |
| ## Headline result | |
| On a held-out Cambodia test split (996 subtiles, never seen during training), the deployed Q4_K_M GGUF on a $300 mini-PC iGPU **beats Claude Sonnet 4.6 (API) by +15.6 pp accuracy and +11.9 pp macro F1**, at **6Γ lower latency**: | |
| | Eval | Accuracy | Macro F1 | RC F1 | RC Recall | Latency / sample | Hardware | | |
| |---|---|---|---|---|---|---| | |
| | LFM2.5-VL-450M zero-shot | 64.4 % | 26.1 % | 0.000 | 0.000 | 0.47 s | Vega 7 iGPU | | |
| | Claude Sonnet 4.6 (API) | 71.5 % | 54.9 % | 0.065 | 0.583 | 1.81 s | API | | |
| | **This model (Q4_K_M GGUF)** | **87.0 %** | **66.8 %** | **0.207** | **0.833** | **0.30 s** | **Vega 7 iGPU** | | |
| Macro F1 is the right headline metric for this 65/34/1 % imbalanced 3-class task β accuracy alone is misleading because the dominant class (`LONG_TERM_NON_FOREST`) inflates correctness via majority frequency. **RC Recall is the deployment-relevant rare-class metric**: the model catches **10 of 12** active-clearing test tiles, vs Claude's 7/12. False positives are cheap (a human-review queue item); false negatives are missed deforestation. | |
| ## Task | |
| Single-snapshot three-class classification from Sentinel-2 imagery. Input is a 100 Γ 100 px **false-color composite** of a 1 km Γ 1 km region: | |
| - R channel: NIR (band 8) | |
| - G channel: Red (band 4) | |
| - B channel: Green (band 3) | |
| This NIR-leading false-color emphasizes vegetation (NDVI signal lives in NIR vs Red) better than natural-color RGB. | |
| Output is JSON-schema-bound: | |
| ```json | |
| {"class_label": "STANDING_FOREST" | "RECENTLY_CLEARED" | "LONG_TERM_NON_FOREST"} | |
| ``` | |
| Both `llama.cpp`'s `response_format=json_schema` and HuggingFace constrained decoding can enforce this directly. Empirically, after fine-tuning the model emits clean JSON without constrained decoding (0 parse failures across 996 test generations). | |
| ## Dataset | |
| 5,729 subtiles labeled from [Hansen Global Forest Change v1.12](https://glad.umd.edu/dataset/global-2010-tree-cover-30-m) `treecover2000` + `lossyear` layers, fetched via the [SimSat](https://github.com/DPhi-Space/SimSat) hackathon API. | |
| | Split | Subtiles | Region | Recent-window | | |
| |---|---|---|---| | |
| | train | 3,973 | Brazilian Amazon (RondΓ΄nia + Mato Grosso) + Brazilian Cerrado | **5 yr** | | |
| | val | 760 | Bolivian Lowlands | 3 yr | | |
| | test | 996 | Cambodia | 3 yr | | |
| ### Class distribution | |
| | Split | LTNF | RC | SF | | |
| |---|---|---|---| | |
| | train | 1,842 (46 %) | **485 (12 %)** | 1,646 (41 %) | | |
| | val | 416 (55 %) | 77 (10 %) | 267 (35 %) | | |
| | test | 644 (65 %) | 12 (1.2 %) | 340 (34 %) | | |
| The training split uses a 5-year recent-loss window (lossyear β {2020-2024}) to densify the rare RC class; val and test use a stricter 3-year window so test results stay aligned with the production-relevant "very recent" definition. This mixed-window design directly addresses the Hansen-derived rare-class undersupply. | |
| ### Geographic split | |
| The train/val/test split is **region-level by geography** β no parent location appears in more than one split. This is the only way to test cross-continental generalization without a coordinate-memorization shortcut. The model trained on Brazil + Cerrado biomes generalizes to Cambodian dry-deciduous forest deforestation it has never seen. | |
| ## Training | |
| Standard supervised fine-tuning with completion-only loss (cross-entropy applied only on the assistant's JSON output, ignoring system + user tokens). 5 epochs, batch 16 Γ grad-accum 2 = 32 effective, AdamW lr 2e-5, cosine schedule with 5 % warmup, bf16 mixed precision. Single RTX 6000 Ada, 8.6 minute total wall clock. | |
| Per-class inverse-frequency loss weighting: | |
| ``` | |
| RECENTLY_CLEARED: 2.28 Γ (rare class) | |
| STANDING_FOREST: 0.43 Γ | |
| LONG_TERM_NON_FOREST: 0.29 Γ | |
| ``` | |
| Trained without coordinates (`include_coords=False`). An ablation arm (`v1_with_coords` from an earlier run on the same dataset) showed lat/lon in the user message either had no effect or slightly hurt performance, mirroring Claude Sonnet 4.6's behavior on the same test set. The image alone carries the discrimination signal. | |
| ## Files in this repository | |
| - `model.safetensors` β full HF-format weights (856 MB, bf16). Use with `transformers.AutoModelForImageTextToText`. | |
| - `config.json`, `generation_config.json` β model and generation config. | |
| - `chat_template.jinja`, `processor_config.json`, `tokenizer.json`, `tokenizer_config.json` β preprocessor (inherited unchanged from the base model). | |
| - `trainer_state.json` β per-epoch eval curve (val_loss, val_macro_f1, val_accuracy across 5 epochs). | |
| - `training_args.bin` β pickled `TrainingArguments` for exact reproducibility. | |
| - `gguf/v2_no_coords-Q4_K_M.gguf` β **deployment artifact**, 218.7 MB, Q4_K_M-quantized text LM. | |
| - `gguf/mmproj-v2_no_coords-F16.gguf` β vision projector, 180.4 MB, f16 (un-quantized for visual fidelity). | |
| Total deployable footprint: **399 MB**. | |
| ## Usage | |
| ### System prompt (use this exactly β the model was trained against this string) | |
| ``` | |
| You are an expert satellite imaging analyst. | |
| You receive a Sentinel-2 false-color image (NIR β R channel, Red β G, Green β B) of a 1 km Γ 1 km region of the Earth's surface, plus the geographic coordinates of the region's center. | |
| Classify the region as exactly one of: | |
| - STANDING_FOREST β currently forested (β₯ 50% canopy in 2000, no recent loss) | |
| - RECENTLY_CLEARED β was forested, cleared in the last ~5 years | |
| - LONG_TERM_NON_FOREST β has not been forest in recent decades (urban, pasture, agriculture, water, bare rock) | |
| Output strict JSON only: {"class_label": "..."}. | |
| No code fences, no commentary, no extra fields. | |
| ``` | |
| ### User-message content | |
| The user message is multimodal: one image (the 1 km Γ 1 km false-color tile) plus a short text payload. The deployed model was trained with **no coordinates** in the text β pass an empty JSON object: | |
| ``` | |
| {} | |
| ``` | |
| (An ablation arm with `{"lat": ..., "lon": ...}` showed coords either had no effect or slightly hurt performance, mirroring frontier-model behavior. The image carries the discrimination signal.) | |
| ### llama.cpp (recommended for edge deployment) | |
| ```bash | |
| llama-server \ | |
| --model gguf/v2_no_coords-Q4_K_M.gguf \ | |
| --mmproj gguf/mmproj-v2_no_coords-F16.gguf \ | |
| --port 8001 \ | |
| --jinja \ | |
| -ngl 99 | |
| ``` | |
| Then POST to the OpenAI-compatible endpoint with the system prompt, false-color tile, and request JSON-schema enforcement: | |
| ```python | |
| import base64, json, requests | |
| SYSTEM_PROMPT = """You are an expert satellite imaging analyst. | |
| You receive a Sentinel-2 false-color image (NIR β R channel, Red β G, Green β B) of a 1 km Γ 1 km region of the Earth's surface, plus the geographic coordinates of the region's center. | |
| Classify the region as exactly one of: | |
| - STANDING_FOREST β currently forested (β₯ 50% canopy in 2000, no recent loss) | |
| - RECENTLY_CLEARED β was forested, cleared in the last ~5 years | |
| - LONG_TERM_NON_FOREST β has not been forest in recent decades (urban, pasture, agriculture, water, bare rock) | |
| Output strict JSON only: {"class_label": "..."}. | |
| No code fences, no commentary, no extra fields.""" | |
| img_b64 = base64.b64encode(open("tile.png", "rb").read()).decode() | |
| body = { | |
| "model": "v2_no_coords-Q4_K_M", | |
| "messages": [ | |
| {"role": "system", "content": SYSTEM_PROMPT}, | |
| {"role": "user", "content": [ | |
| {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{img_b64}"}}, | |
| {"type": "text", "text": "{}"}, | |
| ]}, | |
| ], | |
| "response_format": { | |
| "type": "json_schema", | |
| "schema": { | |
| "type": "object", | |
| "required": ["class_label"], | |
| "properties": { | |
| "class_label": { | |
| "type": "string", | |
| "enum": ["STANDING_FOREST", "RECENTLY_CLEARED", "LONG_TERM_NON_FOREST"], | |
| } | |
| }, | |
| "additionalProperties": False, | |
| }, | |
| }, | |
| "temperature": 0.1, | |
| } | |
| r = requests.post("http://localhost:8001/v1/chat/completions", json=body) | |
| result = json.loads(r.json()["choices"][0]["message"]["content"]) | |
| print(result["class_label"]) | |
| ``` | |
| ### HuggingFace transformers (for further fine-tuning or HF-native inference) | |
| ```python | |
| import torch | |
| from PIL import Image | |
| from transformers import AutoModelForImageTextToText, AutoProcessor | |
| SYSTEM_PROMPT = """You are an expert satellite imaging analyst. | |
| You receive a Sentinel-2 false-color image (NIR β R channel, Red β G, Green β B) of a 1 km Γ 1 km region of the Earth's surface, plus the geographic coordinates of the region's center. | |
| Classify the region as exactly one of: | |
| - STANDING_FOREST β currently forested (β₯ 50% canopy in 2000, no recent loss) | |
| - RECENTLY_CLEARED β was forested, cleared in the last ~5 years | |
| - LONG_TERM_NON_FOREST β has not been forest in recent decades (urban, pasture, agriculture, water, bare rock) | |
| Output strict JSON only: {"class_label": "..."}. | |
| No code fences, no commentary, no extra fields.""" | |
| model = AutoModelForImageTextToText.from_pretrained( | |
| "urbanspr1nter/lfm2.5vl-450m-deforestation-classifier", | |
| dtype="bfloat16", | |
| device_map="cuda", | |
| ) | |
| processor = AutoProcessor.from_pretrained( | |
| "urbanspr1nter/lfm2.5vl-450m-deforestation-classifier", | |
| ) | |
| model.eval() | |
| image = Image.open("tile.png").convert("RGB") | |
| messages = [ | |
| {"role": "system", "content": SYSTEM_PROMPT}, | |
| {"role": "user", "content": [ | |
| {"type": "image", "image": image}, | |
| {"type": "text", "text": "{}"}, | |
| ]}, | |
| ] | |
| inputs = processor.apply_chat_template( | |
| messages, | |
| add_generation_prompt=True, | |
| tokenize=True, | |
| return_tensors="pt", | |
| return_dict=True, | |
| ).to(model.device) | |
| with torch.no_grad(): | |
| out_ids = model.generate(**inputs, max_new_tokens=32, do_sample=False) | |
| completion = processor.tokenizer.decode( | |
| out_ids[0, inputs["input_ids"].shape[1]:], skip_special_tokens=True | |
| ) | |
| print(completion) # e.g. '{"class_label": "RECENTLY_CLEARED"}' | |
| ``` | |
| ## Per-class evaluation | |
| Cambodia held-out test, 996 subtiles. Q4_K_M GGUF on Vega 7 iGPU (the deployed configuration): | |
| | Class | Precision | Recall | F1 | Support | | |
| |---|---|---|---|---| | |
| | STANDING_FOREST | 0.865 | 0.885 | 0.875 | 340 | | |
| | RECENTLY_CLEARED | 0.118 | 0.833 | 0.207 | 12 | | |
| | LONG_TERM_NON_FOREST | 0.988 | 0.863 | 0.921 | 644 | | |
| | **macro avg** | 0.657 | 0.860 | **0.668** | 996 | | |
| | **weighted avg** | 0.929 | 0.870 | 0.890 | 996 | | |
| The model catches **10 of 12 RC test tiles** at moderate precision. RC precision (0.118) is lower than precision on the easy classes because the model is calibrated to err toward catching active clearing β false positives feed a human-review queue; false negatives are missed deforestation, which is the operational worst case. RC remains the hardest class to score statistically β 12 supports is a measurement noise floor that no test-set evaluation can fully escape. | |
| ## Limitations | |
| - **Recent-loss window definition.** "RECENTLY_CLEARED" means cleared in the last ~5 years (training labels) β Hansen `lossyear β {2020, 2021, 2022, 2023, 2024}` for capture year 2024. The held-out val/test labels use a stricter 3-year window which is a strict subset of the training window. Models trained for "this season's clearings" only should use a tighter window (and rebuild the dataset accordingly). | |
| - **Subtile size.** The model is trained on 1 km Γ 1 km tiles. Inference on much larger or much smaller crops should slice into 1 km tiles first; the model has no zoom-invariant training signal. | |
| - **Cloud cover.** Training data was filtered to β€ 10 % cloud cover. Inference on cloudy tiles is undefined behavior β recommend gating at the SimSat metadata level (return `unclassifiable` when `cloud_cover` exceeds a threshold) rather than asking the model to classify through cloud. | |
| - **Region transfer.** Train regions are mechanized-clearing-dominated (Brazilian ranching, soy expansion). Test on Cambodia validates transfer to selective-logging + Economic Land Concessions. Transfer to *very* different visual styles (palm oil monoculture, charcoal-driven miombo) wasn't tested and may degrade β we attempted Mozambique (charcoal-driven miombo) during dataset construction and found the visual signal didn't survive our 1 km tile gate. | |
| - **Imbalanced test set.** Cambodia test has only 12 RC supports. RC F1 is intrinsically noisy at this support level. | |
| - **License.** LFM Open License v1.0 (inherited from base model). Includes a non-commercial threshold; use commercial-scale inference only after reviewing Section 5. | |
| ## Acknowledgements | |
| - Base model: [LiquidAI/LFM2.5-VL-450M](https://huggingface.co/LiquidAI/LFM2.5-VL-450M) under the LFM Open License v1.0. | |
| - Ground truth: [Hansen Global Forest Change v1.12](https://glad.umd.edu/dataset/global-2010-tree-cover-30-m) (Hansen et al., 2013). | |
| - Imagery: ESA Sentinel-2 via the [SimSat](https://github.com/DPhi-Space/SimSat) hackathon API. | |
| - Inference: [llama.cpp](https://github.com/ggml-org/llama.cpp) (multimodal mtmd backend). | |
| ## License | |
| LFM Open License v1.0 β see `LICENSE`. This is a derivative work of LiquidAI's `LFM2.5-VL-450M` and inherits its license terms, including the non-commercial / research-purposes scope and the commercial-use threshold defined in Section 5. Attribution to LiquidAI is preserved. | |