Ana içeriğe geç

Ministral 3’ü İnce Ayarlama: X-Ray Sınıflandırması için Görüntü-Dil Modeli Eğitimi Adım Adım Kılavuz

LoRA, Hugging Face araçları, özel istemler ve TRL kullanarak X-ray görüntü sınıflandırması için Ministral 3 görüntü-dil modelini nasıl ince ayarlayacağınızı öğrenin.
· 10 dk. oku

Yapay Zeka ile Keşfedin

Ministral 3, 3B, 8B ve 14B boyutlarında sunulan, her biri Base, Instruct ve Reasoning varyantlarına ve tam görsel desteğe sahip, uç cihazlar için optimize edilmiş yeni bir çok modlu model ailesidir. 

Yerel ve özel dağıtım için yeterince hafif kalırken üst düzey performans sunmak üzere tasarlanan Ministral 3, gelişmiş yetenekleri pratik donanım kısıtlarıyla buluşturur; amiral gemisi 14B Instruct modeli FP8’de 24 GB VRAM’e sığar ve Mistral Small 3.2 24B gibi daha büyük sistemlerle rekabet eder. 256k bağlam penceresi, güçlü çok dilli kapsama, yerel fonksiyon çağırma, güçlü sistem-istem uyumu ve Apache 2.0 açık lisanslama ile birlikte gelir. 

Bu öğreticide, kırık tespiti ve kategorilerini doğru sınıflandırma yeteneğini artırmak için Ministral 3 14B Instruct modelini kemik kırığı X-ray veri kümesi üzerinde ince ayarlayacağız. 

Şunları öğreneceksiniz:

  1. Veri setini Kaggle’dan yüklemek.
  2. Bunu bir Hugging Face veri setine dönüştürmek.
  3. X-ray sınıflandırması için net bir eğitim istemi oluşturmak.
  4. Ministral 3 14B görüntü-dil eğitim hattını kurmak.
  5. Modeli ince ayarlamak ve kontrol noktasını kaydetmek.
  6. Çıkarım için eğitilmiş model adaptörünü yüklemek.
  7. İnce ayar öncesi ve sonrası sonuçları karşılaştırmak.

Mistral AI modelleri hakkında daha fazla bilgi edinmek istiyorsanız, Mistral 3 rehberimizi ve Mistral 3 Large öğreticisini öneririm. 

Feragatname: Bu öğretici yalnızca eğitim amaçlı, teknik bir ince ayar sürecini göstermektedir. Ortaya çıkan model tıbbi veya klinik kullanım için tasarlanmamıştır ve teşhis, karar verme veya hasta bakımı için güvenilmemelidir.

1. Ministral 3 Görüntü-Dil İnce Ayarı için Ortam Kurulumu

14B modeli ince ayarlıyor olsak da, görüntü-dil eğitimi metin tabanlı ince ayardan belirgin ölçüde daha fazla bellek gerektirir. Görüntü kodlayıcı GPU yükünü artırır; bu da süreci sorunsuz yürütmek için 80 GB VRAM’li bir A100 GPU’ya ihtiyaç duyduğumuz anlamına gelir. 

Bu proje için Runpod kullanıyor ve bir A100 pod başlatıyorum.

RunPod. A100 Pod.

Pod’u başlattıktan sonra konteyner depolamasını 50 GB’a çıkarın. Ardından hem Kaggle hem de Hugging Face API anahtarları için ortam değişkenlerini ekleyin. 

Kaggle, kemik X-ray veri setini doğrudan indirmemize olanak tanıyacak; Hugging Face ise ince ayarlı LoRA adaptörümüzü model merkezine geri göndermemizi sağlayacak.

Runpod'da ortam değişkeni ayarlama

Sonraki adımda JupyterLab oturumunu açın ve yeni bir not defteri oluşturun. Eğitime başlamadan önce gerekli tüm Python paketlerini kurmamız gerekiyor. 

Transformers kütüphanesinin en son sürüme güncel olduğundan emin olun; çünkü Ministral 3 desteği yakın zamanda eklendi ve eski sürümler modeli doğru şekilde yüklemeyecektir.

! pip install --upgrade --quiet bitsandbytes datasets evaluate hf_transfer peft scikit-learn matplotlib Pillow kaggle ipywidgets
!pip install --quiet git+https://github.com/huggingface/transformers.git@bf3f0ae70d0e902efab4b8517fce88f6697636ce
!pip install --quiet --no-deps trl==0.22.2

Her şey kurulduğunda, veri setini yüklemeye, derleyiciyi hazırlamaya ve ince ayara başlamaya hazırsınız.

2. Kaggle’dan Kemik Kırığı Veri Setini İndirme

Bir sonraki adımda, veri setimiz için bir kök klasör oluşturuyor ve Kaggle Python API’sini kullanarak Bone Break Classification Image veri setini indiriyoruz. 

Bu veri seti X-ray formatında çeşitli kemik kırığı kategorileri içerir ve görsel sınıflandırma için Ministral 3’ü ince ayarlamak üzere kullanılacaktır.

import os
import glob
from kaggle.api.kaggle_api_extended import KaggleApi

DATA_ROOT = "/bone-break"
os.makedirs(DATA_ROOT, exist_ok=True)

kaggle_dataset = "pkdarabi/bone-break-classification-image-dataset"

# Initialize and authenticate Kaggle API (it will read KAGGLE_USERNAME / KAGGLE_KEY)
api = KaggleApi()
api.authenticate()

# Download and unzip the dataset using the Python API
api.dataset_download_files(
    kaggle_dataset,
    path=DATA_ROOT,
    unzip=True,
)

Veri setini Kaggle’da buradan görüntüleyebilirsiniz:

Dataset URL: https://www.kaggle.com/datasets/pkdarabi/bone-break-classification-image-dataset

3. Bir Hugging Face Veri Seti Oluşturma

İndirilen veri seti alışılmış yapıda düzenlenmemiştir. Her kırık kategorisinin içinde hem eğitim hem de test klasörü bulunur. 

Bu nedenle önce her sınıf klasörünü döngüyle gezip iki bölümü ayıran ve ardından temiz bir eğitim ve test eşlemesiyle birleşik bir Hugging Face veri seti oluşturan bir yönteme ihtiyacımız var.

import glob, os
from typing import Any, Dict, List

from datasets import Dataset, DatasetDict, Features, ClassLabel, Image

inner_root = os.path.join(
    DATA_ROOT, "Bone Break Classification", "Bone Break Classification"
)

classes = []
train_records: List[Dict[str, Any]] = []
test_records: List[Dict[str, Any]] = []

for class_name in sorted(os.listdir(inner_root)):
    class_dir = os.path.join(inner_root, class_name)
    if not os.path.isdir(class_dir):
        continue

    classes.append(class_name)

    for split_name, split_key in [("Train", "train"), ("Test", "test")]:
        split_dir = os.path.join(class_dir, split_name)
        if not os.path.isdir(split_dir):
            continue

        for ext in ("*.png", "*.jpg", "*.jpeg"):
            for img_path in glob.glob(os.path.join(split_dir, ext)):
                rec = {"image": img_path, "label_name": class_name}
                if split_key == "train":
                    train_records.append(rec)
                else:
                    test_records.append(rec)

print("Classes:", classes)
print("Train samples:", len(train_records))
print("Test samples:", len(test_records))

Toplam 10 sınıflandırma, 989 eğitim örneği ve 140 test örneğimiz var.

Classes: ['Avulsion fracture', 'Comminuted fracture', 'Fracture Dislocation', 'Greenstick fracture', 'Hairline Fracture', 'Impacted fracture', 'Longitudinal fracture', 'Oblique fracture', 'Pathological fracture', 'Spiral Fracture']
Train samples: 989
Test samples: 140

Hugging Face veri seti için etiketleri şimdi kodlayacağız; böylece her etiket sınıfı sınıf etiketleri olarak, her görüntü ise görüntü özellikleri olarak ele alınacak. 

İkisi eğitim ve test olmak üzere iki veri seti oluşturacağız. Son olarak bunları hem eğitim hem de test alt kümelerini içeren tek bir veri setinde birleştireceğiz.

# Encode labels
classes = sorted(list(set(classes)))
label2id = {name: i for i, name in enumerate(classes)}

for rec in train_records:
    rec["label"] = label2id[rec["label_name"]]
for rec in test_records:
    rec["label"] = label2id[rec["label_name"]]

features = Features(
    {
        "image": Image(),
        "label": ClassLabel(names=classes),
    }
)

train_ds = Dataset.from_list(
    [{"image": r["image"], "label": r["label"]} for r in train_records],
    features=features,
)
test_ds = Dataset.from_list(
    [{"image": r["image"], "label": r["label"]} for r in test_records],
    features=features,
)

data = DatasetDict({"train": train_ds, "test": test_ds})
data

Veri setinin genel görünümü aşağıdadır. 

DatasetDict({
    train: Dataset({
        features: ['image', 'label'],
        num_rows: 989
    })
    test: Dataset({
        features: ['image', 'label'],
        num_rows: 140
    })
})

4. Sınıf Dağılımını ve Örnek X-Ray Görüntülerini Keşfetme

İnce ayara başlamadan önce, veri setinin ne kadar dengeli olduğunu ve görüntülerin nasıl göründüğünü anlamak faydalıdır. Önce her kırık kategorisi için kaç eğitim örneği bulunduğunu kontrol edeceğiz.

from collections import Counter

label_names = data["train"].features["label"].names
label_ids = data["train"]["label"]

counts = Counter(label_ids)
print("Training Class counts:")
for lbl_id, cnt in counts.items():
    print(f"{lbl_id:2d} ({label_names[lbl_id]}): {cnt}")

FRACTURE_CLASSES = label_names

Kategoriler oldukça dengeli, ancak genel örnek sayısı, karmaşık bir görsel sınıflandırma görevi için küçük kalıyor. 

Şimdilik bu veri setiyle ilerleyeceğiz, ancak sınırlı örnek hacmi nedeniyle sonuçlar gerçekçi beklentilerle yorumlanmalıdır.

Training Class counts:
 0 (Avulsion fracture): 109
 1 (Comminuted fracture): 134
 2 (Fracture Dislocation): 137
 3 (Greenstick fracture): 106
 4 (Hairline Fracture): 101
 5 (Impacted fracture): 75
 6 (Longitudinal fracture): 68
 7 (Oblique fracture): 69
 8 (Pathological fracture): 116
 9 (Spiral Fracture): 74

Sonraki adımda, veri setini görsel olarak daha iyi anlamak için birkaç rastgele görüntüye bakalım.

import matplotlib.pyplot as plt
from datasets import Image

# Cast the 'image' column to Hugging Face Image feature
dataset_images = data.cast_column("image", Image())

# Select random samples from the training set
samples = dataset_images["train"].shuffle(seed=420).select(range(4))

# Plot
fig, axes = plt.subplots(1, 4, figsize=(16, 5))

for i, sample in enumerate(samples):
    img_object = sample["image"]              # PIL Image
    label_id = sample["label"]               # int
    label_name = label_names[label_id]       # string

    axes[i].imshow(img_object)
    axes[i].set_title(f"Label: {label_name}")
    axes[i].axis("off")

plt.tight_layout()
plt.show()

Örnek görüntülere baktığımızda boyut, çözünürlük, yön ve tarama kalitesinde farklılıklar görüyoruz. Bu durum bir görüntü-dil modelinin ince ayarını etkilemez, ancak modelin her kırık kategorisini ne kadar tutarlı öğrendiğini etkileyebilir. 

Kırığı görsel olarak tespit etmek çoğu zaman kolaydır; ancak onu on ince tıbbi kırık tipinden birine sınıflandırmak, burada sunulandan daha yapılı bir veri gerektirir.

Kemik kırığı veri setinden 4 rastgele örnek

5. Kemik Kırığı Sınıflandırması için İstem Tasarımı

Şimdi modelin nasıl davranmasını istediğimize karar vermemiz gerekiyor. Bu görev için hedefimiz çok katı: bir X-ray görüntüsü verildiğinde model yalnızca bir kırık sınıf adı ve başka hiçbir şey çıktısı vermelidir. Açıklama yok, markdown yok, fazladan metin yok.

Açık bir talimat istemi yazacağız ve ardından bunu veri setinde bir messages sütunu oluşturmak için kullanacağız. 

PROMPT = f"""
You are a radiology assistant specialised in bone fracture classification.

You must classify the X-ray image into exactly ONE of the following classes:
{", ".join(FRACTURE_CLASSES)}

Rules:
- Reply with ONLY the class name.
- No explanations, no extra words, no markdown, no punctuation.
- Output must be EXACTLY one of: {", ".join(FRACTURE_CLASSES)}
""".strip()


from typing import Dict, Any

def convert_to_conversation(example: Dict[str, Any]) -> Dict[str, Any]:
    conversation = [
        {
            "role": "user",
            "content": [
                {"type": "text",  "text": PROMPT},
                {"type": "image"},     # no image bytes here
            ],
        },
        {
            "role": "assistant",
            "content": [
                {"type": "text", "text": FRACTURE_CLASSES[example["label"]]},
            ],
        },
    ]
    example["messages"] = conversation
    return example




formatted_data = data["train"].map(convert_to_conversation)
formatted_data["messages"][0]

Bu, her kaydın artık eksiksiz bir mini konuşma içerdiği bir messages sütunu oluşturur: talimat ve doğru kırık sınıfı. Görüntü-dil modeli ince ayar sırasında tam olarak bunu görecektir.

Konuşma tarzında veri seti.

6. Ministral 3 Görüntü-Dil Modelini Yükleme

Şimdi Hugging Face Hub’dan Ministral-3 14B Instruct modelinin BF16 sürümünü, işlemciyle birlikte yüklüyoruz. İşlemci, görüntü-dil girdileri için gereken belirteçleyici ve görüntü ön işleme hattını bir araya getirir.

import torch
from transformers import AutoProcessor, AutoModelForImageTextToText, BitsAndBytesConfig

model_id = "mistralai/Ministral-3-14B-Instruct-2512-BF16"


model_kwargs = dict(
    attn_implementation="eager",
    torch_dtype=torch.bfloat16,
    device_map="auto",
)

model = AutoModelForImageTextToText.from_pretrained(model_id, **model_kwargs)
processor = AutoProcessor.from_pretrained(model_id)

# Use right padding to avoid issues during training
processor.tokenizer.padding_side = "right"

7. Özel Sohbet Şablonu Kurma

Mistral AI’ın sağladığı orijinal sohbet şablonu, uzun ve sohbet tarzı kullanım durumları için tasarlanmıştır. Bu projede bu bir sorun haline geldi. Model, uzun rol talimatlarına ve sistem metnine odaklanmaya başladı ve X-ray’den tek bir kemik kırığı sınıfını tahmin etme hedefini göz ardı etti.

Bunu düzeltmek için, yalnızca önemli kısımları tutan daha kısa bir görüntü-dil şablonu tanımlıyoruz: kullanıcı talimatı ve asistanın cevabı. Bu, gürültüyü azaltır ve modelin görüntüden sınıf etiketine temiz bir eşleme öğrenmesine yardımcı olur.

SHORT_VLM_TEMPLATE = r"""{{ bos_token }}[INST]
{% for message in messages if message['role'] == 'user' -%}
  {%- for content in message['content'] -%}
    {%- if content['type'] == 'text' -%}
{{ content['text'] }}

    {%- elif content['type'] == 'image' -%}
[IMG]
    {%- endif -%}
  {%- endfor -%}
{%- endfor -%}
[/INST]{% if not add_generation_prompt %}
  {%- for message in messages if message['role'] == 'assistant' -%}
{{ message['content'][0]['text'] }}{{ eos_token }}
  {%- endfor -%}
{%- endif %}"""


# Attach to processor / tokenizer
processor.chat_template = SHORT_VLM_TEMPLATE
processor.tokenizer.chat_template = SHORT_VLM_TEMPLATE

8. Ministral 3’ü Test Etme (İnce Ayar Öncesi)

İnce ayara başlamadan önce, bir temel çizgi oluşturmak için orijinal Ministral 3 14B Instruct modelini test etmek faydalı olacaktır. 

İlk olarak modele veri setinden rastgele bir görüntü veriyor ve genel bir soru soruyoruz; X-ray içeriğini nasıl anladığını görmek için.

image = formatted_data[200]["image"]

messages = [
    {"role": "user", "content": [
        {"type": "text", "text": "What is the image about?"},
        {"type": "image"},
        
    ]}
]

input_text = processor.apply_chat_template(messages, add_generation_prompt = True)
inputs = processor(
    image,
    input_text,
    add_special_tokens = False,
    return_tensors = "pt",
).to(device="cuda", dtype=torch.bfloat16)

from transformers import TextStreamer
text_streamer = TextStreamer(processor, skip_prompt = True)
_ = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 1000,
                   use_cache = True, temperature = 1.5, min_p = 0.1)

Sonuç olarak, model X-ray’in genel içeriğini anladı; ancak tıbbi kullanım için güvenilir olmayan betimlemelere kaydı.

Şimdi nihai hedefimize daha yakın bir şey deniyoruz. Aynı görüntüyü veriyoruz, ancak bu kez açık bir soru yerine katı kırık sınıflandırma istemimizi kullanıyoruz.

image = formatted_data[200]["image"]

messages = [
    {"role": "user", "content": [
        {"type": "text", "text": PROMPT},
        {"type": "image"},
        
    ]}
]

input_text = processor.apply_chat_template(messages, add_generation_prompt = True)
inputs = processor(
    image,
    input_text,
    add_special_tokens = False,
    return_tensors = "pt",
).to(device="cuda", dtype=torch.bfloat16)

from transformers import TextStreamer
text_streamer = TextStreamer(processor, skip_prompt = True)
_ = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 1000,
                   use_cache = True, temperature = 1.5, min_p = 0.1

Bu örnek için model şu yanıtı verdi:

Hairline Fracture</s>

Şimdi aynı görüntünün gerçek etiketini kontrol ediyoruz.

FRACTURE_CLASSES[formatted_data[200]["label"]]

Bu da şunu döndürüyor:

'Comminuted fracture'

Yani model talimat biçimini doğru takip etti ve tek bir sınıf adı üretti; ancak sınıflandırmanın kendisi yanlıştı. 

Tam da bu nedenle ince ayara ihtiyacımız var. Temel modelin görsel anlama yetenekleri güçlü; ancak ayrıntılı kemik kırığı türlerini ayırt etmek üzere özel olarak eğitilmemiştir. 

Sonraki adımlarda, bu davranışı iyileştirmek için kırık veri setimiz üzerinde ince ayar yapacağız.

9. Verimli Ministral 3 İnce Ayarı için LoRA Yapılandırması

Sonraki adımda, LoRA kurarak Ministral 3 modelini tüm parametreleri güncellemeden verimli biçimde ince ayarlayacağız. Bu yapılandırma, Mistral tarzı bir görüntü-dil modelinde kullanılan ana dikkat ve MLP izdüşüm katmanlarını hedefler.

from peft import LoraConfig, TaskType, get_peft_model

# LoRA config for a Mistral-style VLM used as a causal LM
peft_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    r=16,
    lora_alpha=32,
    lora_dropout=0.05,
    bias="none",
    target_modules=[
        "q_proj",
        "k_proj",
        "v_proj",
        "o_proj",
        "gate_proj",
        "up_proj",
        "down_proj",
    ],
    modules_to_save=None,
)

Ardından denetimli ince ayar (SFT) eğitim argümanlarını tanımlıyoruz.

Bu yapılandırma, yığınların nasıl ele alındığı, bellek optimizasyonu, öğrenme oranı davranışı, günlükleme, kaydetme stratejisi ve Hugging Face Hub ile entegrasyon dahil olmak üzere tam eğitim sürecini kontrol eder. 

from trl import SFTConfig

args = SFTConfig(
    output_dir="ministral-3-bone-fracture",            
    num_train_epochs=1,                       
    per_device_train_batch_size=2,                           
    per_device_eval_batch_size=2,                            
    gradient_accumulation_steps=4,                           
    gradient_checkpointing=True,                             
    optim="adamw_8bit",                               
    logging_steps=0.1,                                        
    save_strategy="epoch",                                                                                                             
    learning_rate=2e-4,                             
    bf16=True,
    fp16=False,
    max_grad_norm=0.3,                                       
    warmup_steps=25,                                       
    lr_scheduler_type="linear",                              
    push_to_hub=True,                                        
    report_to="none",
    gradient_checkpointing_kwargs={"use_reentrant": False},  
    dataset_kwargs={"skip_prepare_dataset": True},           
    remove_unused_columns = False,                           
    label_names=["labels"],                                  
)

10. Eğitim için Görüntü-Dil Veri Birleştirici (Collator) Oluşturma

Ministral 3 gibi bir görüntü-dil modelini ince ayarlamak için, görüntülerle sohbet tarzı metni tutarlı bir biçimde toplu hale getirebilen özel bir veri birleştiriciye ihtiyacımız var. 

Aşağıdaki birleştirici; belirteçleyici ve dolgu belirtecini ayarlama, sohbet şablonunu uygulama, metin ve görüntüleri birlikte belirteçleme, güvenli bir azami dizi uzunluğu uygulama ve dolgu ile görüntü belirteçlerinin kaybı etkilememesi için (-100) maskelendiği etiketler oluşturma işlemlerini üstlenir. 

from typing import Any, Dict, List
import torch

# --- One-time processor setup ---
tokenizer = processor.tokenizer
tokenizer.padding_side = "right"

# Ensure we have a pad token
if tokenizer.pad_token is None:
    tokenizer.add_special_tokens({"pad_token": tokenizer.eos_token})

pad_token_id = tokenizer.pad_token_id
image_token_id = getattr(processor, "image_token_id", None)

# Hard cap for sequence length
MAX_SEQ_LEN = 2048 


def collate_fn(examples: List[Dict[str, Any]]) -> Dict[str, torch.Tensor]:
    """
    Collate function for VLM fine-tuning.

    Each example must contain:
      - "image": a PIL image
      - "messages": chat-style conversation (list[dict])
    """
    images = [ex["image"] for ex in examples]
    conversations = [ex["messages"] for ex in examples]

    # Build chat prompts for the whole batch
    chat_texts = processor.apply_chat_template(
        conversations,
        add_generation_prompt=False,
        tokenize=False,
    )

    # Tokenize + process images
    batch = processor(
        text=chat_texts,
        images=images,
        padding="longest", 
        truncation=True,
        max_length=MAX_SEQ_LEN,
        return_tensors="pt",
    )

    # Labels: same as input_ids but mask pad & image tokens
    labels = batch["input_ids"].clone()

    if pad_token_id is not None:
        labels[labels == pad_token_id] = -100

    if image_token_id is not None and image_token_id != pad_token_id:
        labels[labels == image_token_id] = -100

    batch["labels"] = labels
    return batch

11. TRL Kullanarak Ministral 3’ü İnce Ayarlama

LoRA adaptörü, eğitim yapılandırması ve veri birleştirici hazır olduğunda, her şeyi trl’nin SFTTrainer’ına bağlayabiliriz. 

Bu eğitici, biçimlendirilmiş veri setimizi, LoRA yapılandırmasını ve görüntü–metin yığınları için özel birleştirme işlevini kullanarak, görüntü-dil Ministral 3 modelimiz için tam denetimli ince ayar döngüsünü yürütür.

from trl import SFTTrainer

trainer = SFTTrainer(
    model=model,
    args=args,
    train_dataset=formatted_data,
    peft_config=peft_config,
    processing_class=processor,
    data_collator=collate_fn,
)

Eğitim sürecini başlatmak için aşağıdaki kodu çalıştırın. 

trainer.train()

Benim çalıştırmamda ince ayar yaklaşık 57 GB VRAM kullandı; birkaç iterasyonda bir yapılan değerlendirme adımlarında ise biraz daha fazlası kullanıldı. Pratikte bu, 70 GB’ın altındaki VRAM’e sahip donanımlarda bu kurulumu rahatça ince ayarlayabileceğiniz anlamına gelir.

Ministral 3 14B modelinin ince ayarı sırasında Runpod telemetrisi.

Tüm eğitim yaklaşık yarım saat sürdü ve eğitim kaybı zamanla istikrarlı bir şekilde azaldı; bu da modelin veri setinden öğrendiğine dair iyi bir işaret.

Ministral 3 14B modelinin ince ayarındaki eğitim kaybı

Eğitim tamamlandığında, uyarlanmış modeli Hugging Face Hub’a kaydediyoruz. Bu işlem yeni bir depo oluşturur ve gerekli tüm dosyaları yükler; böylece ince ayarlı modeli herhangi bir ortamdan yeniden yükleyip çalıştırabilirsiniz.

trainer.save_model()

Modeli şu adreste görüntüleyebilirsiniz: kingabzpro/ministral-3-bone-fracture. 

Hugging Face hub’da kaydedilen ince ayarlı model.

12. İnce Ayarlı Ministral 3 Modelinin Değerlendirilmesi

Şimdi ince ayarlı modeli ve işlemciyi Hugging Face Hub’dan yüklüyoruz. Arka planda bu işlem, kaydedilen LoRA adaptörünü indirir, temel Ministral 3 denetim noktasını yükler ve adaptörü temel modelle birleştirerek çıkarıma hazır hale getirir.

import torch
from transformers import AutoProcessor, AutoModelForImageTextToText, BitsAndBytesConfig

model_id = "kingabzpro/ministral-3-bone-fracture"


model_kwargs = dict(
    attn_implementation="eager",
    dtype=torch.bfloat16,
    device_map="auto",
)

model = AutoModelForImageTextToText.from_pretrained(model_id, **model_kwargs)
processor = AutoProcessor.from_pretrained(model_id)

processor.tokenizer.padding_side = "left"

Karşılaştırmayı adil tutmak için önce ince ayar öncesinde test ettiğimiz aynı görüntüyü (indeks 200) yeniden kullanıyor ve katı sınıflandırma istemimizle çıkarım hattından geçiriyoruz.

image = formatted_data[200]["image"]

messages = [
    {"role": "user", "content": [
        {"type": "text", "text": PROMPT},
        {"type": "image"},
        
    ]}
]

input_text = processor.apply_chat_template(messages, add_generation_prompt = True)
inputs = processor(
    image,
    input_text,
    add_special_tokens = False,
    return_tensors = "pt",
).to(device="cuda", dtype=torch.bfloat16)

from transformers import TextStreamer
text_streamer = TextStreamer(processor, skip_prompt = True)
_ = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 100)

Mükemmel bir sonuç elde ettik. Ek bir son işleme gerek kalmadı. Model istem kurallarına uydu ve doğru sınıfı doğrudan üretti.

Comminuted fracture</s>

Ardından, bu davranışın tek bir örnekle sınırlı olmadığını doğrulamak için veri setinden başka bir rastgele örnek deniyoruz.

image = formatted_data[400]["image"]

messages = [
    {"role": "user", "content": [
        {"type": "text", "text": PROMPT},
        {"type": "image"},
        
    ]}
]

input_text = processor.apply_chat_template(messages, add_generation_prompt = True)
inputs = processor(
    image,
    input_text,
    add_special_tokens = False,
    return_tensors = "pt",
).to(device="cuda", dtype=torch.bfloat16)

from transformers import TextStreamer
text_streamer = TextStreamer(processor, skip_prompt = True)
_ = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 100)

Model çıktısı:

Greenstick fracture</s>

Gerçek etiket:

FRACTURE_CLASSES[formatted_data[400]["label"]]

Çıktı:

'Greenstick fracture'

Yine tahmin doğru ve etiketle tamamen uyumlu.

Bu kontrollerle, Ministral 3 14B modelimizin kemik kırığı X-ray veri seti üzerinde başarıyla ince ayarlandığını ve istem talimatını takip ederek bu örneklerde doğru tek sınıf tahminleri üretebildiğini söyleyebiliriz.

Son Düşünceler

Ministral 3 modelini ince ayarlamak sabır ve istikrarlı ayarlamalar gerektirir. Modelin neden beklediğim şekilde eğitilmediğini ve nispeten küçük bir model olmasına rağmen neden GPU’umu bellek taşmalarına zorladığını anlamam iki tam günümü aldı. 

Ana neden basitti ama gözden kaçırması kolaydı. Bu sadece bir dil modeli değil. Bu bir görüntü-dil modeli; yani ek bellek kullanımı getiren bir görüntü kodlayıcısı barındırıyor. 

Daha büyük görüntü çözünürlükleri doğrudan daha yüksek VRAM tüketimine yol açar. Görüntü boyutunu küçültmek veya daha küçük yığınlarla başlamak eğitim sürecini çok daha kararlı hale getirir.

Karşılaştığım bir diğer sorun ise varsayılan sohbet şablonunu kullanmaktı. Bu tür bir görev için fazlasıyla uzun ve kurgusaldı. Model, görüntüleri okumayı ve net bir kırık sınıflandırması üretmeyi öğrenmek yerine şablon biçimini oturtmaya daha fazla çaba harcıyordu. 

İstemi doğrudan talimat biçimine sadeleştirdiğimde, model nihayet görsel girdiye doğru şekilde yanıt vermeye başladı ve her yanıtı tam bir sohbet yanıtı gibi biçimlendirmekten vazgeçti.

Ayrıca modelin güçlü görsel yetenekleri olduğu için tıbbi taramalarda doğal olarak iyi performans göstereceğini varsaymıştım. Bu varsayım beni yavaşlattı. Kafamda ona “MedGemma” demek, modele ve sürece haksızlıktı. Kutu dışı uzmanlaşmış bir tıbbi model değil ve uygun eğitim olmadan öyle davranmasını beklemek benim hatamdı.

Sonunda her engeli aştım ve öğrendiklerimi bu rehbere dönüştürdüm. Amaç, aynı karmaşayı yaşamanızı önlemek ve anlamlı sonuçlara daha hızlı ulaşmanıza yardımcı olmaktır. 

“Daha küçük görüntüler, daha basit istemler ve gerçekçi beklentilerle, Ministral 3 X-ray anlama için çok daha akıcı ve güvenilir bir şekilde ince ayarlanabilir.”

İnce ayar konusunda daha fazla uygulama yapmak isterseniz Llama 3 ile İnce Ayar kursunu öneririm.

Abid Ali Awan

Yazar

Abid Ali Awan

Sertifikalı bir veri bilimcisi olarak, yenilikçi makine öğrenimi uygulamaları oluşturmak için en son teknolojileri kullanmaya büyük ilgi duyuyorum. Konuşma tanıma, veri analizi ve raporlama, MLOps, konuşma yapay zekası ve NLP alanlarında güçlü bir geçmişe sahip olarak, gerçek bir etki yaratabilecek akıllı sistemler geliştirme becerilerimi geliştirdim. Teknik uzmanlığımın yanı sıra, karmaşık kavramları açık ve özlü bir dille ifade etme yeteneğine sahip, becerikli bir iletişimciyim. Sonuç olarak, veri bilimi konusunda aranan bir blog yazarı oldum ve giderek büyüyen veri profesyonelleri topluluğuyla görüşlerimi ve deneyimlerimi paylaşıyorum. Şu anda, içerik oluşturma ve düzenlemeye odaklanıyorum. Büyük dil modelleriyle çalışarak, hem işletmelerin hem de bireylerin verilerinden en iyi şekilde yararlanmalarına yardımcı olabilecek güçlü ve ilgi çekici içerikler geliştiriyorum.

Konular

İlgili