File size: 3,389 Bytes
b04d91a
 
 
 
 
 
 
 
 
 
ff0053b
 
 
 
 
 
 
 
e29a08c
ff0053b
b04d91a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import os, sys, torch, gradio as gr
from PIL import Image
from torchvision import transforms
from huggingface_hub import hf_hub_download

# Clone PanDerm source saat startup (sekali saja di container)
PANDERM_DIR = "/tmp/PanDerm"
if not os.path.exists(PANDERM_DIR):
    os.system(f"git clone https://github.com/SiyuanYan1/PanDerm.git {PANDERM_DIR}")
sys.path.insert(0, os.path.join(PANDERM_DIR, "classification"))
sys.path.insert(0, os.path.join(PANDERM_DIR, "classification", "models"))

import importlib.util
_spec = importlib.util.spec_from_file_location(
    "modeling_finetune",
    os.path.join(PANDERM_DIR, "classification", "models", "modeling_finetune.py"),
)
_mod = importlib.util.module_from_spec(_spec)
sys.modules["modeling_finetune"] = _mod   # ← TAMBAHKAN baris ini
_spec.loader.exec_module(_mod)

from timm.models import create_model

CLASSES = ["akiec", "bcc", "bkl", "df", "mel", "nv", "vasc"]
LABELS = {
    "akiec": "Actinic Keratosis (suspicious)",
    "bcc":   "Basal Cell Carcinoma (malignant)",
    "bkl":   "Benign Keratosis (low risk)",
    "df":    "Dermatofibroma (low risk)",
    "mel":   "Melanoma (malignant)",
    "nv":    "Melanocytic Nevus (low risk)",
    "vasc":  "Vascular Lesion (low risk)",
}

device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using device: {device}")

# Download checkpoint dari model repo
ckpt_path = hf_hub_download(
    repo_id="farelfebryan/panderm-ham10000",
    filename="checkpoint-best.pth",
)

# Build model persis seperti training Anda
model = create_model(
    "PanDerm_Large_FT",
    pretrained=False,
    num_classes=7,
    drop_path_rate=0.2,
    use_mean_pooling=True,
    init_scale=0.001,
    use_rel_pos_bias=False,
    use_abs_pos_emb=True,
    init_values=0.1,
    sin_pos_emb=True,
)

ckpt = torch.load(ckpt_path, map_location=device, weights_only=False)
state = ckpt.get("model", ckpt.get("state_dict", ckpt))
state = {k.replace("module.", ""): v for k, v in state.items()}
missing, unexpected = model.load_state_dict(state, strict=False)
print(f"Loaded checkpoint — missing: {len(missing)}, unexpected: {len(unexpected)}")
if missing: print("  missing examples:", missing[:5])
if unexpected: print("  unexpected examples:", unexpected[:5])

model.to(device).eval()

# Transform sesuai training: img_size=224, imagenet mean/std
tfm = transforms.Compose([
    transforms.Resize(256, interpolation=transforms.InterpolationMode.BICUBIC),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
])

@torch.no_grad()
def predict(img: Image.Image):
    if img is None:
        return {}
    x = tfm(img.convert("RGB")).unsqueeze(0).to(device)
    logits = model(x)
    probs = torch.softmax(logits, dim=1)[0].cpu().tolist()
    return {LABELS[CLASSES[i]]: float(probs[i]) for i in range(7)}

demo = gr.Interface(
    fn=predict,
    inputs=gr.Image(type="pil", label="Upload dermoscopy image"),
    outputs=gr.Label(num_top_classes=3, label="Prediction"),
    title="PanDerm Skin Lesion Classifier (HAM10000)",
    description=(
        "7-class skin lesion classifier based on PanDerm-Large, fine-tuned on "
        "HAM10000 with SDXL DoRA synthetic augmentation. "
        "Classes: akiec, bcc, bkl, df, mel, nv, vasc."
    ),
    examples=None,
    flagging_mode="never",
)

if __name__ == "__main__":
    demo.launch()