Machine Learning Academy · Oppitunti

Toimialan mukauttaminen: lääketieteellinen kuvantaminen niukoilla tunnisteilla

Oppijat soveltavat ImageNet-siirto-oppimista röntgenkuva-aineistoon, toteuttavat luokkapainotetun häviön epätasapainoisille sairauksille ja arvioivat AUC-ROC-arvon.

Oppitunti 4/412 vaihetta

Toimialan mukauttaminen: lääketieteellinen kuvantaminen niukoilla tunnisteilla on ilmainen Machine Learning Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Machine Learning Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Machine Learning Academy-kurssilla on yhteensä 4 oppituntia.

Lääketieteellisen kuvantamisen haaste

Lääketieteellinen kuvantaminen asettaa siirto-oppimiselle ainutlaatuisia haasteita. Toisin kuin luonnolliset valokuvat, röntgenkuvat, MRI-kuvat ja histologiset näytteet eivät muistuta lainkaan ImageNet-kuvia: ne ovat harmaasävyisiä tai niissä on alakohtaisia värikuvioita, olennaiset piirteet (leesiot, kyhmyt ja kalkkeumat) ovat hienovaraisia ja alakohtaisia, ja merkityn datan tuottaminen vaatii radiologien asiantuntemusta – siksi laajat merkityt aineistot ovat kalliita ja harvinaisia.

Näistä haasteista huolimatta ImageNet-esikoulutetut mallit suoriutuvat lääketieteellisen kuvantamisen tehtävissä johdonmukaisesti paremmin kuin alusta asti koulutetut mallit, vaikka visuaalinen ulkoasu poikkeaisi huomattavasti. Yleiset matalan tason piirteet (reunantunnistimet ja tekstuurisuodattimet) siirtyvät toimialalta toiselle ja tarjoavat vahvan alustusratkaisun, joka nopeuttaa konvergenssia ja parantaa yleistämistä, kun merkittyä dataa on niukasti.

CheXpert-aineisto: moniluokkainen röntgenkuvien luokittelu

CheXpert on rintakehän röntgenkuvien vertailuaineisto, jossa on 224 316 kuvaa ja 14 luokkaa (Cardiomegaly, Pleural Effusion, Pneumonia, Atelectasis jne.). Niukasti merkittyjen tietojen tilanteessa simuloimme vain pienen osuuden käyttöä – esimerkiksi 1 prosenttia (noin 2 243 kuvaa) – jäljitelläksemme todellisia kliinisiä tilanteita, joissa annotointibudjetti on rajallinen.

Tämä on monilabel-luokitteluongelma: kullakin kuvalla voi olla samanaikaisesti useita patologioita, toisin kuin yksilabel-luokittelussa. Kohde on 14 binääriarvon vektori, ja käytämme Binary Cross-Entropy with Logits -häviötä elementtikohtaisesti. Arvioinnissa käytetään kunkin patologian AUC-ROC-arvoa, joka lasketaan kaikkien 14 luokan keskiarvona.

# 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, label

Harmaasävyjen muuntaminen RGB-muotoon esikoulutettuja malleja varten

Useimmat lääketieteelliset kuvat (röntgen- ja TT-kuvat) ovat harmaasävykuvia (1 kanava), mutta ImageNet-esikoulutetut mallit odottavat 3-kanavaisia RGB-syötteitä. Yksinkertaisin ratkaisu on Image.convert('RGB'), joka kopioi yhden kanavan kolme kertaa, tai transforms.Grayscale(num_output_channels=3) muunnosputkessa.

Tämä on hieman tuhlailevaa – kaikki kolme kanavaa ovat identtisiä – mutta käytännössä se toimii hyvin, koska malli oppii yksinkertaisesti painottamaan kaikkia kolmea kanavaa yhtä paljon. Vaihtoehtona ensimmäinen konvoluutiokerros voidaan korvata uudella Conv2d(1, 64, kernel_size=7, ...)-kerroksella, joka alustetaan laskemalla kolmen syötekanavan painojen keskiarvo. Tämä on periaatteellisempi ratkaisu, mutta lisää koulutuksen monimutkaisuutta.

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 = w

Monilabel-häviö: BCE with Logits

Monilabel-luokittelussa kukin luokka on itsenäinen binääriennuste. Käytämme nn.BCEWithLogitsLoss()-häviötä 14 logitin vektoriin sovellettuna. Häviö lasketaan elementtikohtaisesti ja keskiarvoistetaan sekä 14 luokan että eräkoon suhteen.

Epätasapainoiset luokat ovat merkittävä haaste lääketieteellisessä kuvantamisessa: vain 5–10 prosentissa kuvista esiintyy Pneumonia tai Consolidation, kun taas 40–60 prosentissa esiintyy Pleural Effusion. Välittäkää pos_weight parametrille BCEWithLogitsLoss, jotta harvinaisen positiivisen luokan painoa voidaan kasvattaa: arvo pos_weight 10 saa mallin kiinnittämään 10 kertaa enemmän huomiota kyseisen patologian positiivisiin esimerkkeihin.

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 emphasis

Monilabel-tulostuksen mallirakenne

Korvatkaa ResNet-50:n luokittelupää lineaarisella kerroksella, joka tuottaa 14 logitia (yhden kutakin patologiaa kohden) ImageNetin oletusarvon 1000 sijaan. Emme käytä sigmoid-funktiota forward-vaiheessa – BCEWithLogitsLoss soveltaa sen sisäisesti numeerisen vakauden varmistamiseksi. Päättelyvaiheessa sigmoid-funktio on käytettävä manuaalisesti todennäköisyyksien saamiseksi.

Dropout-kerroksen lisääminen ennen viimeistä lineaarista kerrosta on erityisen tärkeää, kun dataa on niukasti, sillä regularisointi estää pientä päätä ylisovittamasta. Dropout-todennäköisyys 0,3–0,5 on lääketieteellisen kuvantamisen hienosäädössä tyypillinen.

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: oikea mittari lääketieteellisiin tehtäviin

Tarkkuus on hyödytön epätasapainoisissa lääketieteellisissä aineistoissa. Jos vain 5 prosentilla potilaista on Pneumonia, malli, joka ennustaa aina ”ei pneumoniaa”, saavuttaa 95 prosentin tarkkuuden, vaikka se on kliinisesti täysin hyödytön. AUC-ROC (ROC-käyrän alle jäävä pinta-ala) mittaa erottelukykyä kaikilla kynnysarvoilla.

Laskemme AUC-ROC-arvon erikseen jokaiselle 14 patologialle ja ilmoitamme kaikkien luokkien AUC-keskiarvon. AUC-arvo 0,5 vastaa satunnaista arvausta, 0,7 on hyväksyttävä, 0,85 tai enemmän on kliinisen tason tulos, ja 0,9 tai enemmän lähestyy usein radiologin suoritustasoa. scikit-learnin roc_auc_score laskee tämän tehokkaasti.

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), aucs

Koulutus niukasti merkityillä tiedoilla: tärkeimmät tekniikat

Kun käytettävissä on vain satoja tai muutama tuhat merkittyä lääketieteellistä kuvaa, useat tekniikat auttavat hyödyntämään saatavilla olevan datan mahdollisimman tehokkaasti. Voimakas datan augmentointi on tärkeintä: satunnaiset käännöt, kierrot sekä kontrastin ja kirkkauden vaihtelu auttavat, kunhan augmentoinnit pysyvät kliinisesti uskottavina (rintakehän röntgenkuvaa ei pidä kääntää pystysuunnassa, koska sellaista ei tapahtuisi kliinisessä käytännössä).

Progressiivinen koon muuttaminen (koulutuksen aloittaminen pienemmällä tarkkuudella ja koon kasvattaminen myöhemmin) on toinen tehokas tekniikka. Aloittakaa koosta 128×128 nopeaa kokeilua varten ja hienosäätäkää sitten koolla 224×224 tai jopa 320×320 lopullisen tarkkuuden saavuttamiseksi. Tämä on paljon nopeampaa kuin kouluttaminen aina täydellä tarkkuudella, ja tarkkuus vastaa usein täyden tarkkuuden tulosta.

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])
])

Itseohjautuva esikoulutus lääketieteelliseen kuvantamiseen

Kun ImageNet-piirteet eivät siirry riittävän hyvin, itseohjautuva esikoulutus merkitsemättömillä lääketieteellisillä kuvilla on tehokas vaihtoehto. Menetelmät, kuten SimCLR, MoCo ja DINO, oppivat esityksiä kouluttamalla mallin tunnistamaan, että saman kuvan kaksi augmentoitua versiota ovat samanlaisia – ilman merkintöjä.

Työnkulku on seuraava: (1) esikouluttakaa malli suurilla merkitsemättömillä lääketieteellisillä aineistoilla (CheXpert sisältää 224 000 merkitsemätöntä kuvaa), (2) hienosäätäkää malli pienellä merkityllä aineistolla. Tämä päihittää lääketieteellisissä tehtävissä johdonmukaisesti ImageNet-siirron, koska malli oppii lääketieteelliselle toimialalle ominaisia piirteitä yleisten objektintunnistuspiirteiden sijaan.

# 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 illustration

Epävarmuuden kvantifiointi lääketieteellisessä tekoälyssä

Lääketieteellisessä päätöksenteon tuessa sen tietäminen, kuinka varma malli on, on yhtä tärkeää kuin itse ennuste. Malliin, joka ilmoittaa ”Pneumonia: 95 %:n todennäköisyys”, tulisi luottaa enemmän kuin malliin, joka ilmoittaa ”52 %:n todennäköisyys”. Tavalliset softmax-todennäköisyydet ovat usein liian varmoja eivätkä kuvaa todellista epävarmuutta.

Monte Carlo Dropout (MC Dropout) arvioi bayesilaista epävarmuutta pitämällä dropoutin käytössä päättelyn aikana ja suorittamalla forward-vaiheen useita kertoja. Ennusteiden varianssi ajojen välillä antaa arvion epävarmuudesta. Ennusteet, joiden varianssi on suuri, tulisi ohjata ihmisen tarkistettaviksi sen sijaan, että niiden perusteella toimittaisiin automaattisesti.

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.15

Lääketieteellisen koneoppimisen eettiset näkökohdat

Koneoppimismallien käyttöönottoon lääketieteellisissä ympäristöissä liittyy vakavia eettisiä vastuita. Aineiston vinouma on keskeinen huolenaihe: mallit, jotka on koulutettu pääasiassa yhden sairaalan skannereista, potilasryhmistä tai skannerivalmistajista peräisin olevilla kuvilla, saattavat epäonnistua eri ympäristöistä peräisin olevien kuvien kanssa – tämä on tunnettu ongelma radiologian tekoälyssä.

Ennen käyttöönottoa arvioikaa aina mallin suorituskyky demografisissa alaryhmissä (ikä, sukupuoli, rotu) ja erilaisilla skannauslaitteilla. Sääntelykehykset, kuten Yhdysvaltojen FDA:n AI/ML-pohjaisia lääkinnällisinä laitteina käytettäviä ohjelmistoja (SaMD) koskevat ohjeet ja EU:n lääkinnällisiä laitteita koskeva asetus (MDR), edellyttävät perusteellista kliinistä validointia ennen käyttöönottoa. Mallien tulee avustaa radiologeja, ei korvata heitä – erityisesti vakavissa patologioissa, joissa virheillä voi olla hengenvaarallisia seurauksia.

Pikatarkistus

Testatkaa tässä oppitunnissa oppimaasi lääketieteellisen kuvantamisen toimialasovituksesta.

Oppitunnin yhteenveto

Tässä oppitunnissa opitte, että lääketieteellisen kuvantamisen siirto-oppimisessa ImageNet-esikoulutettuja malleja sovelletaan harmaasävykuvien ja niukasti merkittyjen aineistojen toimialoille muuntamalla kanavat ja vaihtamalla luokittelupää, monilabel-luokittelun BCE-häviö pos_weight-parametrilla käsittelee patologioiden aineistoille tyypillistä voimakasta luokkien epätasapainoa ja AUC-ROC on oikea arviointimittari, joka mittaa erottelukykyä luokkatasapainosta riippumatta. Kun siirto-oppimisen taidot ovat hallussa, olette valmiita tutustumaan seuraavalla kurssilla NLP:hen BERTin avulla.

Aloita maksutta

Opi Python tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
30
Oppitunnit
120

Usein kysytyt kysymykset

Onko oppitunti ”Toimialan mukauttaminen: lääketieteellinen kuvantaminen niukoilla tunnisteilla” ilmainen?

Kyllä – oppitunnin ”Toimialan mukauttaminen: lääketieteellinen kuvantaminen niukoilla tunnisteilla” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Machine Learning Academy-kurssin, päivitä CoddyKit PROhon. Machine Learning Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Toimialan mukauttaminen: lääketieteellinen kuvantaminen niukoilla tunnisteilla”?

Oppijat soveltavat ImageNet-siirto-oppimista röntgenkuva-aineistoon, toteuttavat luokkapainotetun häviön epätasapainoisille sairauksille ja arvioivat AUC-ROC-arvon. Harjoittelet Machine Learning Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Machine Learning Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Machine Learning Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”Toimialan mukauttaminen: lääketieteellinen kuvantaminen niukoilla tunnisteilla”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Machine Learning Academy-oppitunnilla?

Kyllä. Jokainen Machine Learning Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Esikoulutetut mallit torchvisionissa: ResNet, EfficientNet ja ViT
  2. Piirteiden erottaminen: rungon jäädyttäminen
  3. Hienosäätö: kerrosten vapauttaminen ja pieni oppimisnopeus
  4. Toimialan mukauttaminen: lääketieteellinen kuvantaminen niukoilla tunnisteilla
← Takaisin: Machine Learning Academy