Alan Uyarlama: Etiketlerin Az Olduğu Tıbbi Görüntüleme
ImageNet'ten göğüs röntgeni veri kümesine aktarım öğrenmesi uygulayacak, dengesiz patolojiler için sınıf ağırlıklı kayıp uygulayacak ve AUC-ROC değerini değerlendireceksiniz.
Alan Uyarlama: Etiketlerin Az Olduğu Tıbbi Görüntüleme, CoddyKit'te ücretsiz bir Machine Learning Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Machine Learning Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Machine Learning Academy kursu toplamda 4 dersten oluşur.
Bu dersin bazı bölümleri henüz çevrilmemiş olup İngilizce olarak gösterilmektedir.
The Medical Imaging Challenge
Medical imaging presents unique transfer learning challenges. Unlike natural photographs, chest X-rays, MRI scans, and histology slides look nothing like ImageNet images: they are grayscale or have domain-specific colour patterns, the features that matter (lesions, nodules, calcifications) are subtle and domain-specific, and labelled data requires expert radiologists — making large labelled datasets expensive and rare.
Despite these challenges, ImageNet pre-trained models consistently outperform training from scratch on medical imaging tasks, even when the visual appearance differs substantially. Universal low-level features (edge detectors, texture filters) transfer across domains, providing a strong initialisation that speeds convergence and improves generalisation with scarce labels.
The CheXpert Dataset: Multi-Label X-Ray Classification
CheXpert is a benchmark chest X-ray dataset with 224,316 images and 14 labels (Cardiomegaly, Pleural Effusion, Pneumonia, Atelectasis, etc.). In our scarce-label scenario, we simulate using only a small fraction — say 1% (about 2,243 images) — to mimic real-world clinical settings where annotation budget is limited.
This is a multi-label classification problem: each image can have multiple pathologies simultaneously, unlike single-label classification. The target is a vector of 14 binary values, and we use Binary Cross-Entropy with Logits (BCE) applied element-wise. Evaluation uses AUC-ROC per pathology, averaged across all 14 labels.
# Dataset setup (pseudo-code for illustration)
import torch
from torch.utils.data import Dataset
from PIL import Image
import pandas as pd
class CheXpertDataset(Dataset):
def __init__(self, csv_path, img_dir, transform=None):
self.df = pd.read_csv(csv_path)
self.img_dir = img_dir
self.transform = transform
self.labels = ['Atelectasis', 'Cardiomegaly',
'Consolidation', 'Edema', 'Pleural Effusion']
def __len__(self):
return len(self.df)
def __getitem__(self, idx):
img_path = self.df.iloc[idx]['Path']
img = Image.open(img_path).convert('RGB') # Convert grayscale to 3-ch
label = torch.tensor(self.df.iloc[idx][self.labels].values.astype(float))
if self.transform:
img = self.transform(img)
return img, labelConverting Grayscale to RGB for Pre-trained Models
Most medical images (X-rays, CT scans) are grayscale (1 channel), but ImageNet pre-trained models expect 3-channel RGB inputs. The simplest solution is Image.convert('RGB') which replicates the single channel three times, or transforms.Grayscale(num_output_channels=3) in the transform pipeline.
This is slightly wasteful — the three channels are identical — but in practice it works well because the model simply learns to weight all three channels equally. An alternative is to replace the first convolutional layer with a new Conv2d(1, 64, kernel_size=7, ...) and initialise it by averaging the three input channel weights. This is more principled but adds training complexity.
from torchvision import transforms
# Method 1: Replicate channel at loading time (simplest)
# img = Image.open(path).convert('RGB')
# Method 2: Use transforms
medical_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=3), # 1 -> 3 channels
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
# Method 3: Modify first conv layer for single-channel input
import torchvision.models as models
model = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1)
# Average the 3-channel weights into 1 channel
w = model.conv1.weight.mean(dim=1, keepdim=True)
model.conv1 = torch.nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)
model.conv1.weight.data = wMulti-Label Loss: BCE with Logits
For multi-label classification, each label is an independent binary prediction. We use nn.BCEWithLogitsLoss() applied to a vector of 14 logits. The loss is computed element-wise and averaged across both the 14 classes and the batch size.
Imbalanced labels are a major challenge in medical imaging: only 5-10% of images have Pneumonia or Consolidation, while 40-60% have Pleural Effusion. Pass pos_weight to BCEWithLogitsLoss to upweight the rare positive class: a pos_weight of 10 makes the model pay 10× more attention to positive examples of that pathology.
import torch
import torch.nn as nn
# Multi-label BCE loss
criterion = nn.BCEWithLogitsLoss()
# With class weighting for imbalanced pathologies
# Compute pos_weight from training data frequencies
pos_counts = train_labels.sum(dim=0) # Positives per class
neg_counts = len(train_labels) - pos_counts
pos_weight = (neg_counts / pos_counts.clamp(min=1)).clamp(max=20) # Cap at 20
criterion = nn.BCEWithLogitsLoss(pos_weight=pos_weight)
print('pos_weight per label:', pos_weight)
# High values mean that class is rare and needs more emphasisModel Architecture for Multi-Label Output
Replace the ResNet-50 classification head with a linear layer that outputs 14 logits (one per pathology), rather than the default 1000 for ImageNet. We do not apply sigmoid in the forward pass — the BCEWithLogitsLoss applies it internally for numerical stability. At inference time, apply sigmoid manually to get probabilities.
Adding a dropout layer before the final linear layer is especially important with scarce data, as regularisation prevents the small head from overfitting. A dropout probability of 0.3-0.5 is typical for medical imaging fine-tuning.
import torchvision.models as models
import torch.nn as nn
NUM_CLASSES = 14 # One per CheXpert pathology label
model = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1)
# Replace with multi-label head
model.fc = nn.Sequential(
nn.Dropout(p=0.4),
nn.Linear(model.fc.in_features, NUM_CLASSES)
)
# No sigmoid here - BCEWithLogitsLoss handles it internally
print('Model output shape for batch of 16:',
model(torch.randn(16, 3, 224, 224)).shape) # (16, 14)AUC-ROC: The Right Metric for Medical Tasks
Accuracy is useless for imbalanced medical datasets. If only 5% of patients have Pneumonia, a model that always predicts 'no pneumonia' achieves 95% accuracy while being completely useless clinically. AUC-ROC (Area Under the ROC Curve) measures discrimination ability across all thresholds.
We compute AUC-ROC for each of the 14 pathologies separately and report the mean AUC across all labels. AUC of 0.5 is random chance; 0.7 is acceptable; 0.85+ is clinical grade; 0.9+ often approaches radiologist-level performance. scikit-learn's roc_auc_score computes this efficiently.
import numpy as np
from sklearn.metrics import roc_auc_score
import torch
def evaluate_auc(model, loader, device):
model.eval()
all_logits, all_labels = [], []
with torch.no_grad():
for images, labels in loader:
logits = model(images.to(device))
all_logits.append(torch.sigmoid(logits).cpu().numpy())
all_labels.append(labels.numpy())
probs = np.vstack(all_logits) # (N, 14)
targets = np.vstack(all_labels) # (N, 14)
# AUC per class, then average
aucs = [roc_auc_score(targets[:, i], probs[:, i])
for i in range(targets.shape[1])]
return np.mean(aucs), aucsTraining with Scarce Labels: Key Techniques
When you have only hundreds or a few thousand labelled medical images, several techniques help maximally exploit the available data. Strong data augmentation is the most important: random flips, rotations, contrast and brightness jitter all help, while keeping augmentations clinically plausible (a chest X-ray should not be vertically flipped — that would never occur in clinical practice).
Progressive resizing (training initially at lower resolution, then increasing) is another effective technique. Start at 128×128 to quickly iterate, then fine-tune at 224×224 or even 320×320 for final accuracy. This is much faster than always training at full resolution and often matches full-resolution accuracy.
from torchvision import transforms
# Clinically appropriate augmentations for chest X-rays
medical_aug = transforms.Compose([
transforms.RandomResizedCrop(224, scale=(0.85, 1.0)), # Mild crop
transforms.RandomHorizontalFlip(p=0.5), # OK: X-rays can be flipped
# transforms.RandomVerticalFlip(p=0.5), # NOT OK: clinically invalid
transforms.ColorJitter(brightness=0.2, contrast=0.3), # Simulate scan variation
transforms.RandomRotation(degrees=10), # Slight mis-alignment
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])Self-Supervised Pre-Training for Medical Imaging
When ImageNet features do not transfer well enough, self-supervised pre-training on unlabelled medical images is a powerful alternative. Methods like SimCLR, MoCo, and DINO learn representations by training the model to recognise that two augmented versions of the same image are similar, without any labels.
The workflow: (1) pre-train on large unlabelled medical datasets (CheXpert has 224K unlabelled images), (2) fine-tune with the small labelled set. This consistently outperforms ImageNet transfer on medical tasks because the model learns features specific to the medical domain rather than general object recognition features.
# Self-supervised pre-training concept (SimCLR-style)
# No labels needed during this phase
class SimCLRLoss(torch.nn.Module):
def __init__(self, temperature=0.07):
super().__init__()
self.temperature = temperature
def forward(self, z_i, z_j):
# z_i, z_j: augmented views of the same images
# Maximise agreement between paired views
# Minimise agreement between all other pairs in batch
z = torch.cat([z_i, z_j], dim=0)
z = torch.nn.functional.normalize(z, dim=1)
sim = torch.matmul(z, z.T) / self.temperature
# Contrastive loss computation...
return sim # Simplified illustrationUncertainty Quantification in Medical AI
In medical decision support, knowing how confident a model is is as important as the prediction itself. A model that says 'Pneumonia: 95% probability' should be more trusted than one saying '52% probability'. Standard softmax probabilities are often overconfident and do not represent true uncertainty.
Monte Carlo Dropout (MC Dropout) approximates Bayesian uncertainty by keeping dropout active at inference time and running forward pass multiple times. The variance of predictions across runs estimates uncertainty. Predictions with high variance should be flagged for human review rather than acted upon automatically.
import torch
def mc_dropout_predict(model, x, n_samples=30):
model.train() # Keep dropout active during inference
predictions = []
with torch.no_grad():
for _ in range(n_samples):
logits = model(x)
probs = torch.sigmoid(logits)
predictions.append(probs)
preds = torch.stack(predictions) # (n_samples, batch, num_classes)
mean_pred = preds.mean(dim=0) # Average prediction
uncertainty = preds.std(dim=0) # Std = uncertainty estimate
return mean_pred, uncertainty
# High uncertainty cases should be reviewed by a radiologist
MEAN_THRESHOLD = 0.5
UNCERTAINTY_THRESHOLD = 0.15Ethical Considerations in Medical ML
Deploying ML models in medical settings carries serious ethical responsibilities. Dataset bias is a critical concern: models trained predominantly on images from one hospital's scanners, patient demographics, or scanner manufacturers may fail on images from different settings — a known problem in radiology AI.
Before deployment, always evaluate model performance across demographic subgroups (age, sex, race) and across different scanning equipment. Regulatory frameworks like the FDA's AI/ML-based Software as a Medical Device (SaMD) guidelines in the US and the EU Medical Device Regulation (MDR) require rigorous clinical validation before deployment. Models should assist radiologists, not replace them — especially on high-stakes pathologies where errors have life-or-death consequences.
Quick Check
Test your understanding of domain adaptation for medical imaging from this lesson.
Lesson Recap
In this lesson you learned: medical imaging transfer learning applies ImageNet pre-trained models to domains with grayscale images and scarce labels by converting channels and replacing the classification head, multi-label BCE loss with pos_weight handles the extreme class imbalance typical of pathology datasets, and AUC-ROC is the correct evaluation metric that measures discrimination ability independent of class balance. With these transfer learning skills mastered, you are ready to explore NLP with BERT in the next course.
Sıkça Sorulan Sorular
“Alan Uyarlama: Etiketlerin Az Olduğu Tıbbi Görüntüleme” dersi ücretsiz mi?
Evet — “Alan Uyarlama: Etiketlerin Az Olduğu Tıbbi Görüntüleme” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Machine Learning Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Machine Learning Academy kursu toplamda 4 dersten oluşur.
“Alan Uyarlama: Etiketlerin Az Olduğu Tıbbi Görüntüleme” dersinde ne öğreneceğim?
ImageNet'ten göğüs röntgeni veri kümesine aktarım öğrenmesi uygulayacak, dengesiz patolojiler için sınıf ağırlıklı kayıp uygulayacak ve AUC-ROC değerini değerlendireceksiniz. Machine Learning Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Machine Learning Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Machine Learning Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.
“Alan Uyarlama: Etiketlerin Az Olduğu Tıbbi Görüntüleme” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Machine Learning Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Machine Learning Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- torchvision'da Önceden Eğitilmiş Modeller: ResNet, EfficientNet ve ViT
- Özellik Çıkarma: Ana Gövdeyi Dondurma
- İnce Ayar: Katmanların Buzunu Çözme ve Düşük Öğrenme Oranları
- Alan Uyarlama: Etiketlerin Az Olduğu Tıbbi Görüntüleme