--- license: apache-2.0 base_model: google/medgemma-1.5-4b-it tags: - medical - ophthalmology - vision-language-model - fundus - retinal-imaging - unsloth datasets: - smrndmdude/eye-diseases-dataset language: - en metrics: - loss pipeline_tag: image-text-to-text library_name: peft --- # Anidane (MedGemma 1.5 4B Fine-Tuned for Ophthalmic Analysis) **Anidane** is a fine-tuned, multimodal vision-language model optimized for the analysis and diagnostic assessment of ophthalmic imagery, specifically fundus and retinal photography. Built on top of the `google/medgemma-1.5-4b-it` architecture and accelerated using **Unsloth**, Anidane bridges the gap in clinical accessibility by enabling parameter-efficient interpretation of localized eye pathologies and structural abnormalities. ## Model Details - **Developed by:** WILLIAMS OPOKU & SAMUEL AGYEMANG - **Model Type:** Multimodal Vision-Language Model (Image-Text to Text) - **Base Model:** `google/medgemma-1.5-4b-it` (Gemma 3 / MedSigLIP Core) - **Fine-Tuning Method:** QLoRA (4-bit quantized) via Unsloth - **Primary Domain:** Ophthalmology, Retinal Image Diagnostic Reporting ## Intended Uses & Limitations ### Intended Use - **Clinical Assistant Tool:** Providing detailed descriptive impressions of fundus abnormalities (e.g., microaneurysms, vascular alterations, optic disc changes). - **Research & Education:** Analyzing pathological trends in public ophthalmic imagery datasets, with an emphasis on mitigating geographic screening biases in underrepresented cohorts. ### Limitations & Out of Scope - **Not a Standalone Diagnostic Tool:** Anidane is designed strictly as an assistive reporting tool and must not be used for definitive medical diagnoses without certified practitioner oversight. - **Data Demographics:** While optimized to interpret global clinical profiles, the model's accuracy is closely tied to the imaging quality and distribution found within the underlying train sets. ## Training Details ### Training Dataset - **Dataset Source:** `smrndmdude/eye-diseases-dataset` - **Modality:** High-resolution eye/fundus photography paired with localized clinical diagnostic captions. ### Hyperparameters & Optimization The model was fine-tuned using the following configurations: - **Quantization:** 4-bit NormalFloat4 (NF4) - **LoRA Rank ($r$):** 16 - **LoRA Alpha ($\alpha$):** 16 - **Optimizer:** `adamw_8bit` - **Learning Rate:** $2 \times 10^{-4}$ (Linear decay) - **Gradient Accumulation Steps:** 4 - **Batch Size:** 2 per device - **Total Steps:** 59 ### Training Loss Curve Performance During fine-tuning, the model displayed highly stable convergence characteristics, with training loss scaling down seamlessly as follows: - **Initial Phase (Step 1):** 6.061622 - **Mid Phase (Step 30):** 0.171660 - **Final Convergence Phase (Step 59):** 0.080335 ## How to Use the Model You can load and query **Anidane** using the Hugging Face `transformers` library or via `unsloth` for accelerated inference. ```python import torch from PIL import Image from transformers import AutoProcessor from unsloth import FastVisionModel # Import FastVisionModel model_id = "Willie999/Anidane" processor = AutoProcessor.from_pretrained(model_id) # Use FastVisionModel for loading the model, consistent with training # FastVisionModel.from_pretrained returns a tuple (model, processor), so we unpack it. model, _ = FastVisionModel.from_pretrained( model_name = model_id, # Use model_name for FastVisionModel torch_dtype=torch.bfloat16, device_map="auto" ) # Load a target retinal image image = Image.open("/content/red-eye-disease.jpg").convert("RGB") messages = [ { "role": "user", "content": [ {"type": "image"}, {"type": "text", "text": "Analyze this fundus/eye photograph. Provide a clear diagnostic assessment focusing on localized anomalies."} ] } ] prompt = processor.apply_chat_template(messages, add_generation_prompt=True) inputs = processor(text=prompt, images=image, return_tensors="pt").to(model.device) with torch.no_grad(): generated_ids = model.generate( input_ids=inputs["input_ids"], pixel_values=inputs["pixel_values"], # Explicitly pass pixel_values max_new_tokens=256, do_sample=False ) response = processor.batch_decode( generated_ids[:, inputs["input_ids"].shape[1]:], skip_special_tokens=True )[0] print("Anidane Analysis:", response)