Kurs
Unsloth’un NVIDIA ile iş birliği, gizli eğitim ek yükünü azaltarak ince ayarı hızlandırmaya odaklanıyor. Sadece daha büyük GPU’lara veya daha küçük modellere güvenmek yerine, iyileştirmeler eğitim sürecinin içindeki darboğazları hedefliyor: tekrarlanan meta veri oluşturma, aktivasyon yeniden yükleme gecikmeleri ve verimsiz belirteç yönlendirme gibi. Kullanıcılar için bu, desteklenen NVIDIA GPU’larda daha hızlı eğitim ve daha akıcı bir ince ayar iş akışı anlamına gelir.
Bu rehberde, bu yeni Unsloth performans iyileştirmelerini öğrenecek ve Unsloth’un optimize edilmiş ince ayar iş akışını pratik bir görsel-dil görevine uygulayacağız. Qwen3.5 Vision 4B modelini tıbbi OCR için ince ayarlayacağız; model, bir OCR veri kümesinin tıbbi görünümlü küçük bir alt kümesini kullanarak tıbbi doküman görüntülerinden yapılandırılmış metin çıkarmayı öğrenecek.
Şunları kullanacağız:
- Qwen3.5 4B (Vision) temel model olarak
- VRAM kullanımını azaltmak için 4-bit QLoRA
- Verimli ince ayar için LoRA adaptörleri
- Eğitim sırasında bellek tasarrufu için Unsloth gradyan denetimleme
- Bir tıbbi OCR veri kümesinden 300 örnekten oluşan alt küme
- Daha sorunsuz görsel eğitim için sabit boyutlu görüntü önişleme
- Temel ve ince ayarlı model çıktıları karşılaştırması için öncesi-sonrası değerlendirme
Unsloth’un NVIDIA’ya Optimize Edilmiş İnce Ayar İş Akışını Kullanma
İnce ayara başlamadan önce, Unsloth’un NVIDIA iş birliğinin neleri iyileştirdiğini ve bu rehberle nasıl bağlantılı olduğunu anlamak faydalı olacaktır.
Unsloth, NVIDIA iş birliğinin LLM eğitimini mevcut 2–5 kat ince ayar hızlanmalarına ek olarak, yaklaşık %25 hızlandırdığını ve doğruluk kaybı olmadığını bildiriyor. Bu kazanımlar, modelin öğrenme hedefini değiştirmek yerine ana eğitim sürecinin etrafındaki gizli ek yükü azaltmaktan geliyor. Başka bir deyişle, amaç doğruluğu değiştirmeden ince ayarı daha hızlı ve verimli hale getirmek.

Kaynak: Unsloth ve NVIDIA ile LLM Eğitimini Nasıl Hızlandırırsınız
Geliştirilmiş eğitim performansı
İş birliği, aşağıdakiler de dahil olmak üzere çeşitli performans iyileştirmeleri bildiriyor:
- Paketlenmiş dizi meta verisi önbelleklemesi sayesinde Qwen3-14B QLoRA SFT kıyaslamasında toplu başına %14,3 daha hızlı
- Çift tamponlu eşzamansız gradyan denetimlemeden 8B modellerde %8,4, 14B modellerde %6,7 ve 32B modellerde %4,6 hızlanma
- GPT-OSS MoE eğitiminde yaklaşık %10–15 hızlanma; hedefli yönlendirme yolunda ileri geçişte %23 ve geri geçişte %13 daha hızlı
Unsloth ve NVIDIA iş birliğinden elde edilen en büyük performans kazanımlarının bir kısmı, yalnızca metinle paketlenmiş eğitim ve Uzman Karışımı (Mixture-of-Experts) modellere uygulanır. Bu rehberde onları kullanmıyoruz; çünkü iş akışımız Qwen3.5 Vision OCR ince ayarına odaklanıyor.
Bu rehberde bir NVIDIA RTX 3090 GPU kullanıyoruz; dolayısıyla iş akışı NVIDIA GPU hızlandırması ve Unsloth’un optimize edilmiş ince ayar yoluna dayanıyor. Unsloth’u başka bir eğiticiye karşı kıyaslamıyoruz; bu nedenle bu rehber rapor edilen hızlanmaların bağımsız kanıtı olarak okunmamalıdır. Bunun yerine, Unsloth’un optimize edilmiş ince ayar iş akışını gerçek bir görsel-dil görevine uyguluyoruz.
Gradyan denetimleme
Bu iş akışı için en ilgili iyileştirme Unsloth’un gradyan denetimlemesidir. GPU belleğinde her aktivasyonu saklama gereğini ortadan kaldırarak eğitim sırasında bellek kullanımını azaltmaya yardımcı olur. Bu, modelin hem görüntü girdilerini hem de metin çıktıları işlemesi gerektiği görsel-dil ince ayarında özellikle kullanışlıdır.
1. Daha Hızlı İnce Ayar için Unsloth Kurulumu
Bu rehberi çalıştırmak için bir NVIDIA GPU’ya erişiminiz olmalı. RunPod, Vast.ai veya başka bir bulut GPU sağlayıcısından kiralayabilirsiniz. Başta genelde hızlı ve güvenilir olduğu için RunPod’u denedim; ancak o sırada mevcut RTX 3090 seçenekleri sınırlıydı. Bu nedenle bu iş akışı için Vast.ai RTX 3090 GPU makinesi kullandım.
Farklı platformların karşılaştırması için şu rehberimize göz atın: en iyi GPU bulut sağlayıcıları.

Kaynak: Vast.ai | Console
Örneği başlattıktan sonra Jupyter Notebook’u açtım ve yeni bir defter oluşturdum. Vast.ai üzerinde, gerekli Python paketlerini sistem düzeyindeki bağımlılıkları etkilemeden defter ortamına kurmak için mevcut ana ortam çekirdeğini seçtim.
Gerekli paketlerin kurulumu
Önce, Unsloth, PyTorch, görsel model eğitimi, veri kümesi yükleme ve Hugging Face entegrasyonu için gerekli paketleri kurun:
!pip install --upgrade \
"torch>=2.8.0" "triton>=3.4.0" \
numpy pillow torchvision bitsandbytes \
unsloth "unsloth_zoo>=2026.4.6" \
"datasets>=4.0.0" huggingface_hub hf_transfer pandas \
transformers==5.2.0 torchcodec timm
Bu paketler resmi Unsloth defter kurulumuna dayanır ve Qwen3.5 Vision’ı yüklemek, görüntü-metin verisi hazırlamak ve Unsloth ile modeli ince ayar yapmak için gereken ana kütüphaneleri içerir.
CUDA aygıtını yapılandırma
Sırada CUDA aygıtını yapılandırıp doğru NVIDIA GPU’nun mevcut olduğunu doğruluyoruz. Bu rehber RTX 3090 kullandığından, kod CUDA’nın etkin olup olmadığını kontrol eder, seçilen GPU’yu doğrular, CUDA ve PyTorch sürümlerini yazdırır ve makinenin bu deney için yeterli VRAM’e sahip olduğunu teyit eder.
import os
import platform
CUDA_DEVICE_INDEX = 0
TARGET_GPU_NAME = "3090"
# Must be set before CUDA / Unsloth are initialized. Restart the kernel if you change these.
os.environ["CUDA_VISIBLE_DEVICES"] = str(CUDA_DEVICE_INDEX)
# RunPod + Qwen3.5 Vision OCR can hit Torch Dynamo fullgraph recompile limits.
# This disables Unsloth's torch.compile path while keeping Unsloth model loading,
# LoRA, gradient checkpointing, collator, and 8-bit optimizer benefits.
os.environ["UNSLOTH_COMPILE_DISABLE"] = "1"
os.environ["TORCH_COMPILE_DISABLE"] = "1"
import torch
DEVICE = torch.device("cuda:0")
print("Python:", platform.python_version())
print("PyTorch:", torch.__version__)
print("CUDA available:", torch.cuda.is_available())
if not torch.cuda.is_available():
raise RuntimeError("CUDA is not available. Select a GPU instance before continuing.")
torch.cuda.set_device(0)
props = torch.cuda.get_device_properties(0)
gpu_name = torch.cuda.get_device_name(0)
total_gpu_memory_gb = props.total_memory / 1024**3
print("Selected device:", DEVICE)
print("GPU:", gpu_name)
print("CUDA version:", torch.version.cuda)
print("BF16 supported:", torch.cuda.is_bf16_supported())
print("Total GPU memory:", round(total_gpu_memory_gb, 2), "GB")
if TARGET_GPU_NAME not in gpu_name:
raise RuntimeError(f"Expected an RTX {TARGET_GPU_NAME}, but CUDA device 0 is: {gpu_name}")
if total_gpu_memory_gb < 20:
raise RuntimeError(f"Expected a 24 GB class 3090, but only found {total_gpu_memory_gb:.2f} GB VRAM.")
Benim kurulumumda, ortam aşağıdaki GPU yapılandırmasını döndürdü:
Python: 3.12.13
PyTorch: 2.12.0+cu130
CUDA available: True
Selected device: cuda:0
GPU: NVIDIA GeForce RTX 3090
CUDA version: 13.0
BF16 supported: True
Total GPU memory: 23.56 GB
Bu, defterin yeterli VRAM’e sahip bir NVIDIA GeForce RTX 3090 üzerinde çalıştığını doğrular.
Eğitim ayarlarını ve istemleri tanımlama
GPU’yu doğruladıktan sonra modeli, veri kümesini, eğitim ayarlarını, çıktı dizinlerini, görüntü boyutunu ve OCR istemlerini tanımlıyoruz.
MODEL_NAME = "unsloth/Qwen3.5-4B"
DATASET_NAME = "naazimsnh02/medocr-vision-dataset"
SAMPLE_COUNT = 300
EVAL_INDEX = 0
MAX_LENGTH = 4096
MAX_STEPS = 30
PER_DEVICE_BATCH_SIZE = 4
GRADIENT_ACCUMULATION_STEPS = 2
LEARNING_RATE = 2e-4
SEED = 3407
OUTPUT_DIR = "outputs/qwen35_vision_medical_ocr"
ADAPTER_DIR = "qwen35-vision-medical-ocr-lora"
# Medical document images vary heavily in size. Fixed-size canvases avoid
# repeated Torch Dynamo recompiles during vision training.
# 768x1024 is a practical portrait-page compromise for a 24 GB 3090 smoke test.
FIXED_IMAGE_SIZE = (768, 1024)
# Official Unsloth Qwen3.5 Vision notebook uses False here for 16-bit LoRA.
# Set True only if you hit VRAM limits.
LOAD_IN_4BIT = True
SYSTEM_PROMPT = "You are a medical OCR transcription engine. Return only the exact text visible in the medical document image."
INSTRUCTION = "Extract all readable text from this medical document exactly. Preserve structure when possible. Return only the OCR text, with no explanation, no diagnosis, no medical advice, and no reasoning."
Burada Unsloth’tan Qwen3.5 Vision 4B ve tıbbi OCR görsel veri kümesini kullanıyoruz. Bu rehber için 300 örnek seçiyor ve 30 adım eğitiyoruz; bu da çalıştırmayı hafif tutarken modelin hedef OCR formatına nasıl uyum sağladığını göstermeye yetiyor.
768×1024 sabit görüntü boyutu, eğitim sırasında görüntü girdilerini tutarlı tutmaya yardımcı olur. Tıbbi dokümanlar çözünürlük ve en-boy oranında büyük farklılıklar gösterebilir; bu yüzden onları sabit bir tuvale yeniden boyutlandırmak iş akışını pürüzsüzleştirir ve görsel-dil ince ayarı sırasında şekle bağlı sorunları azaltır.
2. Modeli Yükleme
Artık ortam hazır olduğuna göre, Unsloth’un FastVisionModel ’ini kullanarak Qwen3.5 Vision 4B modelini yükleyebiliriz.
import unsloth
from unsloth import FastVisionModel
torch.cuda.set_device(0)
model, tokenizer = FastVisionModel.from_pretrained(
MODEL_NAME,
load_in_4bit=LOAD_IN_4BIT,
use_gradient_checkpointing="unsloth",
)
print("Loaded:", MODEL_NAME)
print("4-bit:", LOAD_IN_4BIT)
print("Model device:", next(model.parameters()).device)
Model yüklendikten sonra çıktı, doğru modelin yüklendiğini, 4-bit modun etkin olduğunu ve modelin GPU’ya yerleştirildiğini doğrular:
Loaded: unsloth/Qwen3.5-4B
4-bit: True
Model device: cuda:0
Burada, FastVisionModel.from_pretrained() görsel-dil modelini yükler ve Unsloth’un daha hızlı ve daha bellek verimli ince ayar için optimizasyonlarını uygular. Ayrıca VRAM kullanımını azaltmak için load_in_4bit ’i etkinleştiriyoruz; bu, RTX 3090 gibi 24 GB GPU ile çalışırken kullanışlıdır.
Ayrıca use_gradient_checkpointing="unsloth" ile Unsloth gradyan denetimlemesini etkinleştiriyoruz.
Bu, özellikle hem görüntü hem de metin girdilerini işleyen görsel-dil modelleri için önemli olan eğitim sırasında bellek kullanımını azaltmaya yardımcı olur.
3. LoRA Adaptörlerini Ekleme
Sırada modele LoRA adaptörleri ekliyoruz. LoRA, tüm modeli güncellemek yerine daha küçük bir eğitilebilir parametre kümesiyle ince ayar yapmamıza olanak tanır. Bu da eğitimi daha hızlı, daha bellek verimli ve tek bir GPU’da çalıştırılabilir hale getirir.
model = FastVisionModel.get_peft_model(
model,
finetune_vision_layers=True,
finetune_language_layers=True,
finetune_attention_modules=True,
finetune_mlp_modules=True,
r=16,
lora_alpha=16,
lora_dropout=0,
bias="none",
random_state=SEED,
use_rslora=False,
loftq_config=None,
)
Bu rehberde adaptörler modelin hem görsel hem de dil kısımlarına eklenir. Bu, modelin tıbbi doküman görüntülerini okumayı ve beklenen yapılandırılmış OCR metnini üretmeyi öğrenmesine yardımcı olur. Bu adımdan sonra model tıbbi OCR veri kümesinde eğitime hazırdır.
4. Tıbbi OCR Veri Kümesini Yükleme
Şimdi Hugging Face üzerinden tıbbi OCR veri kümesini yüklüyor ve ince ayar için küçük bir alt küme hazırlıyoruz.
from datasets import load_dataset
from PIL import Image
raw_dataset = load_dataset(DATASET_NAME, split="train")
MEDICAL_KEYWORDS = [
"doctor", "dr.", "clinic", "hospital", "patient", "medication",
"medications", "prescription", "signature", "department", "report",
"diagnosis", "lab", "laboratory", "blood", "hemoglobin", "mg", "dose",
"<s_ocr>",
]
Veri kümesi, doküman görüntülerini ve bunlara karşılık gelen OCR metnini içerir. Bu rehber için yalnızca tıbbi tarzda OCR örnekleri istediğimizden, veri kümesini basit bir anahtar kelime tabanlı yaklaşımla filtreliyoruz. Kod; doctor, clinic, patient, medication, prescription, diagnosis ve dozajla ilgili sözcükler gibi tıbbi dokümanlarda sık görülen terimleri arar.
def looks_medical(sample):
text = str(sample.get("text", "")).lower()
return any(keyword in text for keyword in MEDICAL_KEYWORDS)
medical_indices = []
for idx, sample in enumerate(raw_dataset):
if looks_medical(sample):
medical_indices.append(idx)
if len(medical_indices) >= SAMPLE_COUNT:
break
if not medical_indices:
raise RuntimeError("No medical-looking OCR samples found. Broaden MEDICAL_KEYWORDS or inspect the dataset text field.")
print(f"Selected {len(medical_indices)} medical-looking samples.")
Bu, tıbbi OCR görevine uygun görünen örnekleri seçmek için hafif bir yol sunar. Bu çalıştırmada 300 tıbbi görünümlü örnek seçiyoruz.
Sonraki adımda her görüntüyü sabit 768×1024 tuvale normalleştiriyoruz. Tıbbi doküman görüntüleri farklı boyut ve en-boy oranlarına sahip olabilir; bu adım eğitim verilerini daha tutarlı hale getirmeye yardımcı olur. Görüntü, orijinal en-boy oranı korunarak yeniden boyutlandırılır ve beyaz bir arka plan üzerine yerleştirilir.
def normalize_ocr_image(image, size=FIXED_IMAGE_SIZE):
image = image.convert("RGB")
target_w, target_h = size
scale = min(target_w / image.width, target_h / image.height)
new_w = max(1, int(image.width * scale))
new_h = max(1, int(image.height * scale))
resized = image.resize((new_w, new_h), Image.Resampling.LANCZOS)
canvas = Image.new("RGB", size, "white")
left = (target_w - new_w) // 2
top = (target_h - new_h) // 2
canvas.paste(resized, (left, top))
return canvas
datasets.map kullanmak yerine basit bir Python listesi oluşturuyoruz. Bu, bazı bulut defter ortamlarında PIL görüntülerini yeniden yazarken görülebilecek takılma sorunlarını önler.
dataset = []
for idx in medical_indices:
sample = raw_dataset[idx]
dataset.append(
{
"image": normalize_ocr_image(sample["image"]),
"text": sample["text"],
}
)
print("Examples:", len(dataset))
print("Columns:", list(dataset[0].keys()))
print("Fixed image size:", dataset[EVAL_INDEX]["image"].size)
print("Sample text:", dataset[EVAL_INDEX]["text"])
Önişlemeden sonra her örnek iki alan içerir: normalleştirilmiş görüntü ve hedef OCR metni.
Examples: 300
Columns: ['image', 'text']
Fixed image size: (768, 1024)
Sample text: <s_ocr> doctor_name: Dr. A. Smith clinic_name: Meadowview Health clinic_address: 45 Oak Ave. patient_name: John Doe patient_age: 35 date: 2024-12-16 medications: - Hydrochlorothiazide 25 mg - Before meals signature: Dr. A. Smith </s>
Yeniden boyutlandırılmış örneklerden birini de önizleyebiliriz:
dataset[EVAL_INDEX]["image"].resize((384, 512))
Önizleme; klinik bilgileri, doktor adı, hasta bilgileri, ilaç ve imzayı içeren tıbbi tarzda bir doküman görüntüsü gösterir. Bu da veri kümesinin OCR ince ayar görevi için uygun olduğunu doğrular.

5. Örnekleri Görsel Diyaloglara Dönüştürme
Artık veri kümesi yüklendi ve görüntüler normalleştirildi; her örneği Qwen3.5 Vision’ın beklediği diyalog formatına dönüştürmemiz gerekiyor.
Her eğitim örneği üç bölüm içermelidir:
- Modelin rolünü tıbbi bir OCR transkripsiyon motoru olarak tanımlayan bir sistem mesajı
- Görüntüyü ve OCR talimatını içeren bir kullanıcı mesajı
- Beklenen OCR çıktısını içeren bir asistan mesajı
def build_ocr_messages(image=None, target_text=None, instruction=INSTRUCTION):
user_content = [
{"type": "image"},
{"type": "text", "text": instruction},
]
if image is not None:
user_content[0]["image"] = image
messages = [
{"role": "system", "content": [{"type": "text", "text": SYSTEM_PROMPT}]},
{"role": "user", "content": user_content},
]
if target_text is not None:
messages.append(
{
"role": "assistant",
"content": [{"type": "text", "text": target_text}],
}
)
return messages
Yukarıdaki yardımcı işlev hem eğitim hem de çıkarım (inference) için mesaj yapısını oluşturur. Eğitim sırasında hedef OCR metnini asistan yanıtı olarak ekleriz. Çıkarım sırasında yalnızca görüntüyü ve talimatı verir, ardından modelden OCR metnini üretmesini isteriz.
Şimdi her veri kümesi örneğini bu diyalog formatına dönüştürüyoruz:
def convert_to_conversation(sample):
return {
"messages": build_ocr_messages(
image=sample["image"],
target_text=sample["text"],
)
}
converted_dataset = [convert_to_conversation(sample) for sample in dataset]
converted_dataset[0]
Dönüştürmeden sonra her örnek bir mesaj listesi içerir. İlk örnekte sistem istemi, tıbbi doküman görüntüsü, OCR talimatı ve beklenen yapılandırılmış OCR transkripsiyonu yer alır. Bu format, modelin bir görüntü ve bir talimatı doğru metin çıktısına nasıl eşleyeceğini öğrenmesini sağlar.
{'messages': [{'role': 'system',
'content': [{'type': 'text',
'text': 'You are a medical OCR transcription engine. Return only the exact text visible in the medical document image.'}]},
{'role': 'user',
'content': [{'type': 'image',
'image': <PIL.Image.Image image mode=RGB size=768x1024>},
{'type': 'text',
'text': 'Extract all readable text from this medical document exactly. Preserve structure when possible. Return only the OCR text, with no explanation, no diagnosis, no medical advice, and no reasoning.'}]},
{'role': 'assistant',
'content': [{'type': 'text',
'text': '<s_ocr> doctor_name: Dr. A. Smith clinic_name: Meadowview Health clinic_address: 45 Oak Ave. patient_name: John Doe patient_age: 35 date: 2024-12-16 medications: - Hydrochlorothiazide 25 mg - Before meals signature: Dr. A. Smith </s>'}]}]}
6. İnce Ayardan Önce Temel Modeli Değerlendirme
Eğitime başlamadan önce temel modeli bir OCR örneği üzerinde test etmeliyiz. Bu, modelin ince ayardan önce ve sonra çıktısını karşılaştırabilmemiz için bir referans noktası sağlar.
Önce, modelin sohbet şablonunu uygulamak için bir yardımcı işlev tanımlıyoruz. Bazı belirteçleyici sürümleri enable_thinking=False seçeneğini desteklerken bazıları desteklemez; bu nedenle işlev kodu uyumlu tutmak için bir geri dönüş yolu içerir.
def render_ocr_chat_template(tokenizer, messages):
try:
return tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
enable_thinking=False,
)
except TypeError:
return tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
)
Sırada üretim işlevini tanımlıyoruz. OCR istemini oluşturur, hem görüntü hem de metin talimatlarını belirteçleyiciye iletir, model çıktısını üretir ve yalnızca yeni üretilen belirteçleri çözümler.
def generate_ocr_text(model, tokenizer, image, instruction=INSTRUCTION, max_new_tokens=512):
messages = build_ocr_messages(instruction=instruction)
input_text = render_ocr_chat_template(tokenizer, messages)
inputs = tokenizer(
images=image,
text=input_text,
add_special_tokens=False,
return_tensors="pt",
).to(DEVICE)
with torch.inference_mode():
outputs = model.generate(
**inputs,
max_new_tokens=max_new_tokens,
use_cache=True,
do_sample=False,
temperature=None,
top_p=None,
)
prompt_length = inputs["input_ids"].shape[-1]
generated_tokens = outputs[:, prompt_length:]
return tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)[0]
Şimdi modeli çıkarım moduna alıp ilk değerlendirme görüntüsü için OCR metni üretiyoruz:
FastVisionModel.for_inference(model)
eval_image = dataset[EVAL_INDEX]["image"]
base_output = generate_ocr_text(model, tokenizer, eval_image)
print("Target:")
print(dataset[EVAL_INDEX]["text"])
print("\nBase model output:")
print(base_output)
Temel model çıktısı okunaklı; ancak hedef yapıyı tam olarak takip etmiyor:
Target:
<s_ocr> doctor_name: Dr. A. Smith clinic_name: Meadowview Health clinic_address: 45 Oak Ave. patient_name: John Doe patient_age: 35 date: 2024-12-16 medications: - Hydrochlorothiazide 25 mg - Before meals signature: Dr. A. Smith </s>
Base model output:
Meadowview Health
45 Oak Ave.
Prescribed by: Dr. A. Smith
Date: 2024-12-16
Patient: John Doe, Age: 35
Hydrochlorothiazide 25 mg - Before meals
Signature: Dr. A. Smith
Bu yararlı bir başlangıç noktasıdır. Temel model belgenin büyük kısmını zaten okuyabiliyor; ancak çıktıyı veri kümesinde kullanılan yapılandırılmış formattan ziyade doğal bir OCR tarzında veriyor. İnce ayar, modeli hedef formatla hizalamaya ve yanıtlarını daha tutarlı hale getirmeye yardımcı olmalıdır.
7. Modeli Eğitme
Artık veri kümesi doğru görsel-diyalog formatında olduğuna göre, Unsloth’un görsel veri birleştiricisiyle TRL’nin SFTTrainer ’ını kullanarak modeli eğitebiliriz.
from unsloth.trainer import UnslothVisionDataCollator
from trl import SFTTrainer, SFTConfig
FastVisionModel.for_training(model)
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
data_collator=UnslothVisionDataCollator(model, tokenizer),
train_dataset=converted_dataset,
args=SFTConfig(
per_device_train_batch_size=PER_DEVICE_BATCH_SIZE,
gradient_accumulation_steps=GRADIENT_ACCUMULATION_STEPS,
warmup_steps=5,
max_steps=MAX_STEPS,
learning_rate=LEARNING_RATE,
logging_steps=1,
optim="adamw_8bit",
weight_decay=0.001,
lr_scheduler_type="linear",
seed=SEED,
output_dir=OUTPUT_DIR,
report_to="none",
remove_unused_columns=False,
dataset_text_field="",
dataset_kwargs={"skip_prepare_dataset": True},
max_length=MAX_LENGTH,
),
)
trainer_stats = trainer.train()
Önce FastVisionModel.for_training(model) ile modeli eğitim moduna geçiriyoruz. Ardından dönüştürülmüş OCR veri kümesini kullanarak eğiticiyi oluşturuyoruz.
Buradaki önemli kısım UnslothVisionDataCollator ’dır. Bu bir görsel-dil görevi olduğundan, eğiticinin hem tıbbi doküman görüntülerini hem de hedef OCR metnini doğru şekilde işlemesi gerekir. Birleştirici, bu çok modlu örnekleri denetimli ince ayar sırasında modele aktarılmak üzere hazırlar.
Bu rehberde 30 adım eğitiyor; aygıt başına 4 yığın boyutu ve 2 gradyan birikimi kullanıyoruz, böylece etkin yığın boyutu 8 oluyor. Bu, çalıştırmayı hafif tutarken modelin yapılandırılmış OCR formatına uyum sağlamaya başladığını göstermeye yetiyor.

Eğitim sırasında Unsloth kurulumla ilgili yararlı bilgiler yazdırır: örnek, adım ve yığın sayısı; eğitilebilir parametre sayısı ve bellek tasarrufu özellikleri gibi. Bu çalıştırmada Unsloth, geri yayılım için çift arabelleğin etkin olduğunu bildiriyor; bu da gradyan denetimlemesi sırasında bekleme süresini azaltmaya yardımcı olur.
8. İnce Ayarlı Modeli Değerlendirme
Eğitimden sonra modeli tekrar çıkarım moduna alıyor ve ince ayardan önce kullandığımız aynı değerlendirme görüntüsü için OCR metni üretiyoruz.
FastVisionModel.for_inference(model)
fine_tuned_output = generate_ocr_text(model, tokenizer, eval_image)
print("Target:")
print(dataset[EVAL_INDEX]["text"])
print("\nBase model output:")
print(base_output)
print("\nFine-tuned output:")
print(fine_tuned_output)
İnce ayardan sonra model çıktısı veri kümesinin hedef yapısına çok daha yakındır:
Target:
<s_ocr> doctor_name: Dr. A. Smith clinic_name: Meadowview Health clinic_address: 45 Oak Ave. patient_name: John Doe patient_age: 35 date: 2024-12-16 medications: - Hydrochlorothiazide 25 mg - Before meals signature: Dr. A. Smith </s>
Base model output:
Meadowview Health
45 Oak Ave.
Prescribed by: Dr. A. Smith
Date: 2024-12-16
Patient: John Doe, Age: 35
Hydrochlorothiazide 25 mg - Before meals
Signature: Dr. A. Smith
Fine-tuned output:
<s_ocr> doctor_name: Dr. A. Smith clinic_name: Meadowview Health clinic_address: 45 Oak Ave. patient_name: John Doe patient_age: 35 date: 2024-12-16 medications: - Hydrochlorothiazide 25 mg - Before meals signature: Dr. A. Smith </s>
Bu, ince ayarlı modelin beklenen OCR yanıt formatını öğrendiğini gösterir. Temel model görünür metnin çoğunu zaten çıkarabiliyordu; ancak ince ayar, çıktıyı eğitim verilerinde kullanılan yapılandırılmış formatla hizalamaya yardımcı oldu.
Modeli veri kümesinden başka bir örnek üzerinde de test edebiliriz:
EVAL_INDEX_2 = 35
eval_image_2 = dataset[EVAL_INDEX_2]["image"]
fine_tuned_output = generate_ocr_text(model, tokenizer, eval_image_2)
print("Target:")
print(dataset[EVAL_INDEX]["text"])
print("\nFine-tuned output:")
print(fine_tuned_output)
Bu ikinci örnekte model beklenen yapıyı takip ediyor; ancak Amlodipine yerine Amoxicillin üreterek küçük bir OCR hatası yapıyor:
Target:
<s_ocr> doctor_name: Dr. C. Rossi clinic_name: Riverside Clinic clinic_address: 45 Oak Ave. patient_name: Wei Li patient_age: 70 date: 2024-12-16 medications: - Acetaminophen 20 mg - Take twice daily - Amlodipine 20 mg - After meals signature: Dr. C. Rossi </s>
Fine-tuned output:
<s_ocr> doctor_name: Dr. C. Rossi clinic_name: Riverside Clinic clinic_address: 45 Oak Ave. patient_name: Wei Li patient_age: 70 date: 2024-12-16 medications: - Acetaminophen 20 mg - Take twice daily - Amoxicillin 20 mg - After meals signature: Dr. C. Rossi </s>
Bu, modelin format hizalamasında ilerlediğini; ancak OCR doğruluğunun hâlâ veri kalitesi, görüntü netliği, eğitim boyutu ve ince ayar adımı sayısına bağlı olduğunu hatırlatır. Üretim için bir OCR sistemi kurarken daha büyük ve çeşitli bir veri kümesi üzerinde eğitmek ve çok sayıda örnekte doğruluğu değerlendirmek gerekir.
9. İnce Ayarlı Adaptörü Kaydetme
Eğitim tamamlandığında LoRA adaptörünü ve belirteçleyiciyi yerel olarak kaydediyoruz.
model.save_pretrained(ADAPTER_DIR)
tokenizer.save_pretrained(ADAPTER_DIR)
print("Saved adapter to:", ADAPTER_DIR)
Çıktı adaptörün kaydedildiğini doğrular:
Saved adapter to: qwen35-vision-medical-ocr-lora
Bu işlem, temel modelin tam bir kopyasını değil; yalnızca ince ayarlı adaptör ağırlıklarını kaydeder. Daha sonra temel Qwen3.5-4B modelini yeniden yükleyip bu adaptörü uygulayarak ince ayarlı OCR davranışını yeniden kullanabilirsiniz. Bu da kaydedilen modeli hafif kılar ve saklamayı, paylaşmayı veya dağıtmayı kolaylaştırır.
Son Düşünceler
Eğitim süreci tek bir NVIDIA RTX 3090 üzerinde hafif ve pratiktir. Görsel-dil ince ayarı genelde bellek yoğun olmasına rağmen, çalışma beklenenden çok daha az VRAM kullandı. Maksimum VRAM kullanımı yaklaşık 14 GB civarındaydı; ortalama ise 9 GB’a daha yakındı ki bir Qwen3.5 Vision modelini ince ayarlamak için etkileyicidir.
Model de hızlı uyum sağladı. Sadece birkaç eğitim adımından sonra çıktı, hedef OCR yapısına çok daha yakın hale geldi. Temel model belgeyi zaten okuyabiliyordu; ancak ince ayardan sonra veri kümesi formatını daha tutarlı şekilde takip etti.
Bununla birlikte, kurulum deneyimi kusursuz değildi. Unsloth’u kurmak epey deneme-yanılma gerektirdi. Özellikle farklı yerel ortamlar, sanal ortamlar, CUDA sürümleri ve bulut GPU sağlayıcıları arasında çalışırken doğru şekilde yapılandırmak zor olabilir.
Bazı durumlarda CUDA uyumluluk sorunları ortamı bozabilir ve bu problemleri ayıklamak beklenenden daha fazla zaman alabilir. Bir bulut GPU platformunda Unsloth Docker imajıyla başlamak bile ortam kutudan çıktığı gibi temiz çalışmıyorsa zaman alıcı olabilir.
Bir diğer önemli ders ise şablonun önemli olduğudur. Veri kümesi doğru sohbet veya görsel-diyalog formatına dönüştürülmemişse model düzgün öğrenemeyebilir. Qwen3.5 Vision için doğru görüntü-metin mesaj yapısını kullanmak esastır. Doğru şablon olmadan eğitim çalışsa bile model göreve gerçekten uyum sağlayamayabilir.
Genel olarak, yerel makinelerde veya kiralanan GPU’larda verimli şekilde model ince ayarı yapmak isteyen ve sınırlı GPU erişimi olan kullanıcılar için Unsloth güçlü bir seçenektir. Bellek kullanımını azaltır, daha küçük donanımı daha kullanışlı hale getirir ve denemeleri hızlandırabilir. Ancak düzenli olarak model ince ayarı ve eğitimi yapan kullanıcılar için kurulum karmaşıklığı can sıkıcı olabilir. Standart Transformers tabanlı eğitim genellikle daha istikrarlı, kurması daha kolay ve ortamlar arasında yeniden üretmesi daha basittir.
Kurulum sürtünmesi sizi vazgeçiren kısım ise, manuel ortam kurulumu olmadan Unsloth’un yerel web arayüzünde Qwen3.5-9B’yi nasıl ince ayarlayacağınızı gösteren Unsloth Studio rehberimizi okumanızı öneririm.
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.

