Open-Source AI Cookbook documentation
Vision Transformer Modelini Özel Bir Biyomedikal Verisetiyle Fine-Tune Etmek
Vision Transformer Modelini Özel Bir Biyomedikal Verisetiyle Fine-Tune Etmek
Yazar: Emre Albayrak Çevirmen: Onuralp Sezer
Bu rehber, Vision Transformer (ViT) modelini özel bir biyomedikal verisetiyle fine-tune etmek için izlenmesi gereken adımları açıklamaktadır. Verisetini yükleme ve hazırlama, farklı veri bölümleri için görüntü dönüşümlerini ayarlama, ViT modelini yapılandırma ve başlatma, ayrıca eğitim sürecini değerlendirme ve görselleştirme araçlarıyla tanımlama adımlarını içermektedir.
Veriseti Bilgisi
Özel veriseti elle oluşturulmuş olup, 780 görüntü ve 3 sınıf içermektedir (iyi huylu, kötü huylu, normal).
Model Bilgisi
Fine-tune edilecek model, Google’ın "vit-large-patch16-224"
modelidir. Model, ImageNet-21k (14M görüntü, 21.843 sınıf) üzerinde eğitilmiş ve ImageNet 2012 (1M görüntü, 1.000 sınıf) üzerinde 224x224 çözünürlükte fine-tune edilmiştir. Google, farklı görüntü boyutları ve yama boyutlarına sahip çeşitli ViT modellerine sahiptir.
Hadi başlayalım!
Başlarken
Öncelikle, gerekli python kütüphanelerini yükleyerek başlayalım.
!pip install datasets transformers accelerate torch torchvision scikit-learn matplotlib wandb huggingface-hub
(İsteğe Bağlı) Modelimizi Hugging Face Hub’a yükleyeceğimiz için giriş yapmamız gerekiyor.
from huggingface_hub import notebook_login
notebook_login()
Verisetini Hazırlamak
Datasets kütüphanesi, verisetinden görüntüleri ve sınıfları otomatik olarak çeker. Detaylı bilgi için bu bağlantıyı
ziyaret edebilirsiniz.
from datasets import load_dataset
dataset = load_dataset("emre570/breastcancer-ultrasound-images")
dataset
Verisetimizi aldık. Ancak elimizde bir doğrulama seti yok. Doğrulama setini oluşturmak için, test setinin boyutuna dayalı olarak eğitim setinin bir kısmını doğrulama seti olarak ayıracağız. Daha sonra, eğitim verisetini yeni eğitim ve doğrulama alt altsetlere böleceğiz.
# Her setin sayısını alalım
test_num = len(dataset["test"])
train_num = len(dataset["train"])
val_size = test_num / train_num
train_val_split = dataset["train"].train_test_split(test_size=val_size)
train_val_split
Ayrılmış test setimizi aldım. Şimdi test seti ile birleştirelim
from datasets import DatasetDict
dataset = DatasetDict(
{"train": train_val_split["train"], "validation": train_val_split["test"], "test": dataset["test"]}
)
dataset
Harika, Verisetimiz hazır olduğuna göre şimdi alt setleri farklı değişkenlere tanımlayarak kolay şekilde kullanabiliriz.
train_ds = dataset["train"]
val_ds = dataset["validation"]
test_ds = dataset["test"]
Şimdi verisetimizdeki resimlerin türünün PIL.Image
olduğunu, ilk resme bakarak doğrulayabiliriz.
train_ds[0]
Eğitim setinin özelliklerini ayrıca görebiliriz.
train_ds.features
Şimdi veriseti içindeki her sınıftan bir tane resim gösterelim.
>>> import matplotlib.pyplot as plt
>>> # Initialize a set to keep track of shown labels
>>> shown_labels = set()
>>> # Initialize the figure for plotting
>>> plt.figure(figsize=(10, 10))
>>> # Loop through the dataset and plot the first image of each label
>>> for i, sample in enumerate(train_ds):
... label = train_ds.features["label"].names[sample["label"]]
... if label not in shown_labels:
... plt.subplot(1, len(train_ds.features["label"].names), len(shown_labels) + 1)
... plt.imshow(sample["image"])
... plt.title(label)
... plt.axis("off")
... shown_labels.add(label)
... if len(shown_labels) == len(train_ds.features["label"].names):
... break
>>> plt.show()
Veri İşleme
Veriseti hazır, ancak fine-tuning için henüz hazır değiliz. Aşağıdaki adımları sırasıyla takip edeceğiz:
Etiket Eşleme: Model eğitimi ve değerlendirmesi sırasında faydalı olacak şekilde, etiket kimliklerini (ID) ve bunların karşılık gelen isimlerini dönüştüreceğiz.
Görüntü İşleme: Daha sonra,
ViTImageProcessor
kullanarak giriş görüntü boyutlarını standartlaştıracağız ve önceden eğitilmiş modele özgü normalizasyon uygulayacağız. Ayrıca, torchvision kullanarak eğitim, doğrulama ve test için farklı dönüşümler tanımlayarak model genellemesini geliştireceğiz.Dönüşüm Fonksiyonları: ViT modeline uygun format ve boyutlara dönüştürerek verisetine bu dönüşümleri uygulayan fonksiyonlar implement edeceğiz.
Veri Yükleme: Görüntü ve etiketleri uygun şekilde gruplamak için özel bir collate fonksiyonu tanımlayacak ve model eğitimi sırasında verimli yükleme ve gruplama için bir DataLoader oluşturacağız.
Batch Hazırlığı: Örnek bir batch’in veri şekil bilgilerini alacak ve görüntüleyerek işlemenin doğru yapıldığını ve model girişine hazır olduğunu doğrulayacağız.
Etiket Eşleme
id2label = {id: label for id, label in enumerate(train_ds.features["label"].names)}
label2id = {label: id for id, label in id2label.items()}
id2label, id2label[train_ds[0]["label"]]
Görüntü İşleme
from transformers import ViTImageProcessor
model_name = "google/vit-large-patch16-224"
processor = ViTImageProcessor.from_pretrained(model_name)
from torchvision.transforms import (
CenterCrop,
Compose,
Normalize,
RandomHorizontalFlip,
RandomResizedCrop,
ToTensor,
Resize,
)
image_mean, image_std = processor.image_mean, processor.image_std
size = processor.size["height"]
normalize = Normalize(mean=image_mean, std=image_std)
train_transforms = Compose(
[
RandomResizedCrop(size),
RandomHorizontalFlip(),
ToTensor(),
normalize,
]
)
val_transforms = Compose(
[
Resize(size),
CenterCrop(size),
ToTensor(),
normalize,
]
)
test_transforms = Compose(
[
Resize(size),
CenterCrop(size),
ToTensor(),
normalize,
]
)
Dönüşüm fonksiyonlarını oluşturma
def apply_train_transforms(examples):
examples["pixel_values"] = [train_transforms(image.convert("RGB")) for image in examples["image"]]
return examples
def apply_val_transforms(examples):
examples["pixel_values"] = [val_transforms(image.convert("RGB")) for image in examples["image"]]
return examples
def apply_test_transforms(examples):
examples["pixel_values"] = [val_transforms(image.convert("RGB")) for image in examples["image"]]
return examples
Dönüşüm fonksiyonlarını her bir sete uygulayalım
train_ds.set_transform(apply_train_transforms) val_ds.set_transform(apply_val_transforms) test_ds.set_transform(apply_test_transforms)
train_ds.features
train_ds[0]
Bu işlem ile görüldüğü üzere piksel değerlerini tensorlara dönüştürmüş oluyoruz.
Veri Yükleme (DataLoader)
import torch
from torch.utils.data import DataLoader
def collate_fn(examples):
pixel_values = torch.stack([example["pixel_values"] for example in examples])
labels = torch.tensor([example["label"] for example in examples])
return {"pixel_values": pixel_values, "labels": labels}
train_dl = DataLoader(train_ds, collate_fn=collate_fn, batch_size=4)
Batch Hazırlığı
>>> batch = next(iter(train_dl))
>>> for k, v in batch.items():
... if isinstance(v, torch.Tensor):
... print(k, v.shape)
pixel_values torch.Size([4, 3, 224, 224]) labels torch.Size([4])
Harika! Şimdi fine-tuning işlemi için hazırız.
Modeli Fine-Tune Etme
Şimdi modeli yapılandırıp fine-tune edeceğiz. İlk olarak, modeli belirli etiket eşlemeleri ve önceden eğitilmiş ayarlarla başlatarak boyut uyuşmazlıklarını ayarlıyoruz. Eğitim parametreleri, modelin öğrenme sürecini tanımlamak için ayarlandı; bu parametreler arasında kaydetme stratejisi, batch boyutları ve eğitim epoch’ları yer alıyor ve sonuçlar Weights & Biases aracılığıyla kaydediliyor. Ardından, Hugging Face Trainer, eğitim ve değerlendirme süreçlerini yönetmek için özel bir veri collator ve modelin dahili işlemcisini kullanarak başlatılacak. Son olarak, eğitim tamamlandıktan sonra modelin performansı bir test veriseti üzerinde değerlendirilecek ve doğruluk gibi metrikler yazdırılarak modelin başarısı değerlendirilecek.
İlk olarak, modelimizi çağırıyoruz.
from transformers import ViTForImageClassification
model = ViTForImageClassification.from_pretrained(
model_name, id2label=id2label, label2id=label2id, ignore_mismatched_sizes=True
)
Burada önemli bir detay var: ignore_mismatched_sizes
parametresi.
Önceden eğitilmiş bir modeli yeni bir veriseti üzerinde fine-tune ederken, bazen görüntülerin giriş boyutu veya model mimarisi özellikleri (örneğin, sınıflandırma katmanındaki etiket sayısı) modelin başlangıçta eğitildiği yapı ile tam olarak uyuşmayabilir. Bu durum, genellikle ImageNet gibi doğal görüntüler üzerinde eğitilmiş bir modeli, tıbbi görüntüler veya özel kamera görüntüleri gibi tamamen farklı bir görüntü verisetine uygularken ortaya çıkar.
ignore_mismatched_sizes
parametresini True
olarak ayarlamak, modelin boyut farklılıklarına uyum sağlamasına ve hata oluşturmadan katmanlarını ayarlamasına olanak tanır.
Örneğin, bu model 1000 sınıf üzerinde eğitilmiştir ve torch.Size([1000])
boyutunda bir giriş bekler. Verisetimiz ise 3 sınıfa sahiptir ve bu torch.Size([3])
boyutundadır. Eğer bunu doğrudan modele verirsek, sınıf sayıları eşleşmediği için bir hata alırız.
Sonrasında, bu model için Google tarafından sağlanan eğitim argümanlarını tanımlayacağız.
(Opsiyonel) report_to
parametresini wandb
olarak ayarladığımız için metrikler Weights & Biases’te kaydedilecektir. W&B sizden bir API anahtarı isteyecek, bu yüzden bir hesap oluşturmalı ve API anahtarı almalısınız. Eğer istemiyorsanız, report_to
parametresini kaldırabilirsiniz.
from transformers import TrainingArguments, Trainer
import numpy as np
train_args = TrainingArguments(
output_dir="output-models",
save_total_limit=2,
report_to="wandb",
save_strategy="epoch",
evaluation_strategy="epoch",
learning_rate=2e-5,
per_device_train_batch_size=10,
per_device_eval_batch_size=4,
num_train_epochs=40,
weight_decay=0.01,
load_best_model_at_end=True,
logging_dir="logs",
remove_unused_columns=False,
)
Artık Trainer
ile fine-tuning sürecine başlayabiliriz.
trainer = Trainer( model, train_args, train_dataset=train_ds, eval_dataset=val_ds, data_collator=collate_fn, tokenizer=processor, ) trainer.train()
Epoch | Eğitim Kaybı | Doğrulama Kaybı | Doğruluk |
---|---|---|---|
40 | 0.174700 | 0.596288 | 0.903846 |
Fine-tuning süreci tamamlandı. Şimdi, modeli test verisetinde değerlendirmeye devam edelim.
>>> outputs = trainer.predict(test_ds)
>>> print(outputs.metrics)
{'test_loss': 0.40843912959098816, 'test_runtime': 4.9934, 'test_samples_per_second': 31.242, 'test_steps_per_second': 7.81}
{'test_loss': 0.3219967782497406, 'test_accuracy': 0.9102564102564102, 'test_runtime': 4.0543, 'test_samples_per_second': 38.478, 'test_steps_per_second': 9.619}
(Opsiyonel) Modeli Hub’a Yükleme
Modelimizi push_to_hub
fonksiyonunu kullanarak Hugging Face Hub’a yükleyebiliriz.
model.push_to_hub("your_model_name")
Sonuçlar
Fine-tuning işlemini tamamladık. Şimdi, modelimizin sınıfları nasıl tahmin ettiğini görelim. Bunun için scikit-learn’ün Confusion Matrix Display fonksiyonunu kullanarak Confusion Matrix’i görselleştirecek ve Recall Skoru göstereceğiz.
Confusion Matrix Nedir?
Confusion Matrix, bir algoritmanın, genellikle bir denetimli öğrenme modelinin, gerçek değerlerin bilindiği bir test veriseti üzerindeki performansını görselleştirmeye olanak tanıyan belirli bir tablo düzenidir. Özellikle bir sınıflandırma modelinin ne kadar iyi performans gösterdiğini kontrol etmek için kullanışlıdır, çünkü gerçek ve tahmin edilen etiketlerin sıklığını gösterir.
Hadi, modelimizin Confusion Matrix’ini çizelim.
>>> from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
>>> y_true = outputs.label_ids
>>> y_pred = outputs.predictions.argmax(1)
>>> labels = train_ds.features["label"].names
>>> cm = confusion_matrix(y_true, y_pred)
>>> disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=labels)
>>> disp.plot(xticks_rotation=45)
Recall Skoru Nedir?
Recall skoru, sınıflandırma görevlerinde kullanılan bir performans metriğidir ve bir modelin bir veriseti içindeki tüm ilgili örnekleri doğru bir şekilde tanımlama yeteneğini ölçer. Özellikle recall, gerçek pozitiflerin model tarafından doğru bir şekilde pozitif olarak tahmin edilen oranını değerlendirir.
Hadi, scikit-learn kullanarak recall skorlarını yazdıralım.
>>> from sklearn.metrics import recall_score
>>> # Calculate the recall scores
>>> # 'None' calculates recall for each class separately
>>> recall = recall_score(y_true, y_pred, average=None)
>>> # Print the recall for each class
>>> for label, score in zip(labels, recall):
... print(f"Recall for {label}: {score:.2f}")
Recall for benign: 0.90 Recall for malignant: 0.86 Recall for normal: 0.78
Recall for benign: 0.90, Recall for malignant: 0.86, Recall for normal: 0.78
Sonuç
Bu cookbook’ta, bir ViT modelini bir tıbbi verisetiyle nasıl eğiteceğimizi ele aldık. Veriseti hazırlığı, görüntü ön işleme, model yapılandırması, eğitim, değerlendirme ve sonuçların görselleştirilmesi gibi önemli adımları kapsadık. Hugging Face’in Transformers kütüphanesi, scikit-learn ve PyTorch Torchvision’u kullanarak, verimli model eğitimi ve değerlendirme süreçlerini kolaylaştırdık. Bu süreç, modelin performansı ve biyomedikal görüntüleri doğru şekilde sınıflandırma yeteneği hakkında değerli bilgiler sunmaktadır.
< > Update on GitHub