Views
No views yet
google/medgemma-27b-it for chest X-ray finding prediction.| Adapter variant | Training data | Intended behavior |
|---|---|---|
disease_only | Images with disease findings only | Better specialization on abnormal cases |
no_finding_only | Healthy / no-disease images only | Better specialization on normal cases |
all | Mixed healthy + disease images | Balanced general-purpose adapter |
google/medgemma-27b-it{"findings": ["Pleural effusion", "Cardiomegaly"]}3320481.02e-41180.03paged_adamw_8bitcosine16160.05all-linearCAUSAL_LMnonenf4bfloat16bfloat16{"findings": ["Pneumothorax"]}pip install -U "transformers>=4.50.0" datasets peft accelerate trl bitsandbytes pillow scikit-learn huggingface_hub1import torch
2from transformers import AutoProcessor, AutoModelForImageTextToText, BitsAndBytesConfig
3from peft import PeftModel
4
5BASE_MODEL_ID = "google/medgemma-27b-it"
6ADAPTER_PATH = "/path/to/your/adapter_or_checkpoint_directory"
7
8bnb_config = BitsAndBytesConfig(
9 load_in_4bit=True,
10 bnb_4bit_use_double_quant=True,
11 bnb_4bit_quant_type="nf4",
12 bnb_4bit_compute_dtype=torch.bfloat16,
13 bnb_4bit_quant_storage=torch.bfloat16,
14)
15
16processor = AutoProcessor.from_pretrained(BASE_MODEL_ID)
17processor.tokenizer.padding_side = "right"
18
19if processor.tokenizer.pad_token is None:
20 processor.tokenizer.pad_token = processor.tokenizer.eos_token
21
22base_model = AutoModelForImageTextToText.from_pretrained(
23 BASE_MODEL_ID,
24 quantization_config=bnb_config,
25 torch_dtype=torch.bfloat16,
26 attn_implementation="eager",
27 device_map="auto",
28)
29
30model = PeftModel.from_pretrained(base_model, ADAPTER_PATH)
31model.eval()1from PIL import Image
2
3DISEASE_CLASSES = [
4 "Aortic enlargement",
5 "Atelectasis",
6 "Calcification",
7 "Cardiomegaly",
8 "Clavicle fracture",
9 "Consolidation",
10 "Edema",
11 "Emphysema",
12 "Enlarged PA",
13 "ILD",
14 "Infiltration",
15 "Lung Opacity",
16 "Lung cavity",
17 "Lung cyst",
18 "Mediastinal shift",
19 "Nodule/Mass",
20 "Pleural effusion",
21 "Pleural thickening",
22 "Pneumothorax",
23 "Pulmonary fibrosis",
24 "Rib fracture",
25 "Other lesion",
26 "COPD",
27 "Lung tumor",
28 "Pneumonia",
29 "Tuberculosis",
30 "Other diseases",
31]
32
33OPTIONS_TEXT = "\n".join(DISEASE_CLASSES)
34
35USER_PROMPT = (
36 "Analyze this X-ray image and identify the most likely findings. "
37 "Choose findings only from the options below. "
38 "Format your output as {'findings': ['disease 1', 'disease 2', ...]}.\n"
39 f"\nOptions:\n{OPTIONS_TEXT}"
40)
41
42SYSTEM_PROMPT = """
43You are a senior, board-certified radiologist with extensive clinical experience.
44
45Base your analysis strictly on clearly visible, high-confidence visual evidence observed in the provided medical image.
46If visual findings are subtle, ambiguous, low-confidence, or potentially attributable to image quality, limited field of view, positioning, or artifacts, explicitly state this.
47If bounding boxes are present, each box marks a suspected lesion location. If multiple boxes are shown, review all of them.
48Focus primarily on the boxed regions, but do not restrict your assessment to the boxes alone; consider the surrounding areas and the full image context as well.
49If no boxes are present, evaluate the entire X-ray image.
50
51Clearly distinguish between:
52- Directly observed imaging findings
53- Inferred clinical interpretations (which must remain tentative)
54
55Do not provide definitive diagnoses.
56Do not label findings as abnormal unless there is clear, high-confidence visual evidence.
57If the image or provided context is insufficient to support a conclusion, explicitly state uncertainty.
58Do not fabricate findings.
59Do not assume clinical history, symptoms, prior studies, or patient context not explicitly provided.
60Follow the user-requested output structure strictly.
61Do not add any information beyond what is explicitly requested.
62Use precise, professional radiologic language.
63Limit your response to within 1000 tokens.
64""".strip()
65
66image = Image.open("/path/to/image.png").convert("RGB")
67
68messages = [
69 {
70 "role": "system",
71 "content": [{"type": "text", "text": SYSTEM_PROMPT}],
72 },
73 {
74 "role": "user",
75 "content": [
76 {"type": "image"},
77 {"type": "text", "text": USER_PROMPT},
78 ],
79 },
80]
81
82prompt_text = processor.apply_chat_template(
83 messages,
84 tokenize=False,
85 add_generation_prompt=True,
86)
87
88inputs = processor(
89 text=[prompt_text],
90 images=[image],
91 return_tensors="pt",
92 padding=True,
93)
94
95inputs = {k: v.to(model.device) for k, v in inputs.items()}
96
97with torch.no_grad():
98 generated = model.generate(
99 **inputs,
100 max_new_tokens=256,
101 do_sample=False,
102 )
103
104output = processor.batch_decode(
105 generated[:, inputs["input_ids"].shape[1]:],
106 skip_special_tokens=True,
107)[0]
108
109print(output.strip())/medgemma_finetune/checkpoints/<adapter_name>/checkpoint-XXXtrainer.train(resume_from_checkpoint="./medgemma_finetune/checkpoints/<adapter_name>/checkpoint-XXX")1import torch
2from transformers import AutoProcessor, AutoModelForImageTextToText, BitsAndBytesConfig
3from peft import PeftModel
4
5BASE_MODEL_ID = "google/medgemma-27b-it"
6PREVIOUS_ADAPTER_PATH = "/home/ubuntu/medgemma_finetune/checkpoints/<adapter_name>"
7
8bnb_config = BitsAndBytesConfig(
9 load_in_4bit=True,
10 bnb_4bit_use_double_quant=True,
11 bnb_4bit_quant_type="nf4",
12 bnb_4bit_compute_dtype=torch.bfloat16,
13 bnb_4bit_quant_storage=torch.bfloat16,
14)
15
16processor = AutoProcessor.from_pretrained(BASE_MODEL_ID)
17
18base_model = AutoModelForImageTextToText.from_pretrained(
19 BASE_MODEL_ID,
20 quantization_config=bnb_config,
21 torch_dtype=torch.bfloat16,
22 attn_implementation="eager",
23 device_map="auto",
24)
25
26model = PeftModel.from_pretrained(base_model, PREVIOUS_ADAPTER_PATH, is_trainable=True)Trainer again and call:trainer.train()checkpoint-* directories when you want an exact resume.| Training Loss | Epoch | Step | Validation Loss |
|---|---|---|---|
| 0.0469 | 1.0 | 1875 | 0.1599 |