Ukratko

Najvažnije iz članka

  • Postavite PyTorch okolinu provjerom GPU kompatibilnosti, instalacijom NVIDIA drivera i CUDA Toolkit-a, te kreiranjem virtualne okoline za izolaciju paketa.
  • Koristite `torch.device("cuda" if torch.cuda.is_available() else "cpu")` za dinamičko odabiranje između GPU i CPU, te osigurajte da su svi tenzori i modeli premješteni na odabrani uređaj s `.to(device)`.
  • Implementirajte jednostavnu linearnu regresiju i konvolucijsku neuronsku mrežu (CNN) koristeći `torch.nn` za definiranje modela, `torch.optim` za optimizatore i `torch.utils.data` za učitavanje podataka.
  • Optimizirajte GPU korištenje smanjenjem veličine batcha, izbjegavanjem nepotrebnih CPU-GPU prijenosa, korištenjem `DataLoader` s `num_workers` i razmatranjem `torch.amp` za mješovitu preciznost.
Sadržaj članka
  1. Zašto PyTorch i GPU?
  2. Postavljanje razvojne okoline
  3. 1. Provjera GPU kompatibilnosti i instalacija drivera
  4. 2. Instalacija CUDA Toolkit-a (opcionalno, preporučeno)
  5. 3. Kreiranje virtualne okoline
  6. 4. Instalacija PyTorcha
  7. 5. Provjera instalacije
  8. Osnovni pojmovi u PyTorch-u
  9. Vaš prvi PyTorch program: Jednostavna linearna regresija
  10. Napredniji primjer: Klasifikacija slika s konvolucijskom neuronskom mrežom (CNN)
  11. Savjeti za optimizaciju GPU korištenja
  12. Zaključak

Strojno učenje (ML) i duboko učenje (DL) transformirali su mnoge industrije, omogućujući računalima da uče iz podataka i donose inteligentne odluke. U srcu ovih tehnologija leže moćni okviri poput PyTorcha, koji developerima i istraživačima nude fleksibilnost i efikasnost. Još važnije, za postizanje performansi potrebnih za treniranje složenih modela, GPU (Graphics Processing Unit) akceleracija postala je neizostavan dio procesa. Ovaj sveobuhvatni vodič provest će vas kroz osnove korištenja PyTorcha, od postavljanja okoline do treniranja vaše prve neuronske mreže, s posebnim naglaskom na iskorištavanje GPU snage.

Zašto PyTorch i GPU?

PyTorch je open-source biblioteka za strojno učenje koju je razvio Facebook (Meta AI). Poznat je po svojoj fleksibilnosti, intuitivnom API-ju i dinamičkom računalnom grafikonu (computational graph), što ga čini omiljenim izborom među istraživačima i developerima. Njegova "Pythonic" priroda omogućuje jednostavno učenje i brzi razvoj prototipova.

GPU akceleracija, s druge strane, ključna je jer tradicionalni CPU-ovi nisu optimizirani za masivne paralelne operacije koje su potrebne za treniranje dubokih neuronskih mreža. GPU-ovi, sa svojim tisućama manjih jezgri, mogu istovremeno obavljati velik broj izračuna, drastično smanjujući vrijeme treniranja modela. Bez GPU-a, treniranje složenijih modela može trajati danima ili čak tjednima, dok s GPU-om taj proces može biti sveden na sate.

Postavljanje razvojne okoline

Prije nego što zaronimo u kod, moramo postaviti našu razvojnu okolinu. To uključuje instalaciju PyTorcha i osiguravanje da je vaša grafička kartica ispravno konfigurirana za CUDA (Compute Unified Device Architecture) ako koristite NVIDIA GPU, što je de facto standard za GPU akceleraciju u ML-u. Ako nemate NVIDIA GPU, i dalje možete koristiti PyTorch na CPU-u, ali performanse će biti značajno niže.

1. Provjera GPU kompatibilnosti i instalacija drivera

Za NVIDIA GPU-ove, prvi korak je osigurati da su instalirani najnoviji, kompatibilni NVIDIA driveri. Posjetite službenu web stranicu NVIDIA-e, preuzmite i instalirajte odgovarajuće drivere za vašu grafičku karticu i operativni sustav. Nakon instalacije, provjerite verziju drivera putem nvidia-smi naredbe u terminalu:

nvidia-smi

Ova naredba će prikazati informacije o vašem GPU-u, uključujući verziju drivera i CUDA verziju koju podržavaju. To je ključno za odabir ispravne PyTorch instalacije.

2. Instalacija CUDA Toolkit-a (opcionalno, preporučeno)

Iako PyTorch conda i pip instalacije obično dolaze s potrebnom CUDA runtime bibliotekom, instalacija punog CUDA Toolkit-a može biti korisna za naprednije scenarije ili ako naiđete na probleme. Preuzmite odgovarajući CUDA Toolkit sa NVIDIA web stranice koji odgovara verziji vašeg drivera i podržanoj CUDA verziji. Slijedite upute za instalaciju.

3. Kreiranje virtualne okoline

Preporučuje se korištenje virtualne okoline (npr. conda ili venv) kako bi se izbjegli sukobi paketa. Ovdje ćemo koristiti conda:

conda create -n pytorch_env python=3.9
conda activate pytorch_env

4. Instalacija PyTorcha

Idite na službenu web stranicu PyTorcha (pytorch.org/get-started/locally/) i odaberite opcije koje odgovaraju vašem sustavu (OS, paket menadžer, CUDA verzija). Na primjer, za Linux s Condom i CUDA 11.8:

conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia

Ako koristite pip i imate kompatibilan GPU:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

Ako nemate GPU ili ne možete koristiti CUDA, odaberite opciju "CPU Only":

conda install pytorch torchvision torchaudio cpuonly -c pytorch

5. Provjera instalacije

Otvorite Python interpreter i provjerite je li PyTorch ispravno instaliran i može li detektirati GPU:

import torch
print(f"PyTorch verzija: {torch.__version__}")
print(f"CUDA dostupna: {torch.cuda.is_available()}")
if torch.cuda.is_available():
    print(f"Trenutni GPU: {torch.cuda.get_device_name(0)}")
    print(f"Broj GPU-ova: {torch.cuda.device_count()}")

Ako torch.cuda.is_available() vrati True i vidite informacije o vašem GPU-u, uspješno ste postavili okolinu!

Osnovni pojmovi u PyTorch-u

Prije nego što krenemo, upoznajmo se s ključnim pojmovima:

  • Tensor: Temeljna podatkovna struktura u PyTorch-u, slična NumPy arrayu, ali s mogućnošću rada na GPU-u. Tenzori mogu imati različite dimenzije (skalari, vektori, matrice, 3D tenzori, itd.).
  • torch.nn modul: Sadrži klase za izradu neuronskih mreža (npr. Linear slojevi, Conv2d slojevi, aktivacijske funkcije).
  • torch.optim modul: Sadrži implementacije različitih optimizatora (npr. SGD, Adam) za ažuriranje težina modela.
  • torch.utils.data modul: Pruža alate za učitavanje i obradu podataka (npr. Dataset, DataLoader).
  • Autograd: PyTorch-ov sustav za automatsko izračunavanje gradijenata, ključan za backpropagation.

Vaš prvi PyTorch program: Jednostavna linearna regresija

Započnimo s jednostavnim primjerom: implementacijom linearne regresije za predviđanje vrijednosti. Cilj je naučiti liniju y = mx + b koja najbolje aproksimira dane podatke.

import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt

# 1. Definiranje uređaja za treniranje (CPU ili GPU)
# PyTorch automatski premješta tenzore i modele na odabrani uređaj
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Korištenje uređaja: {device}")

# 2. Generiranje sintetičkih podataka
# y = 2x + 1 + šum (noise)
X = torch.randn(100, 1) * 10 # 100 uzoraka, 1 značajka
y = 2 * X + 1 + torch.randn(100, 1) * 2 # Ciljna varijabla s malo šuma

# Premještanje podataka na odabrani uređaj
X = X.to(device)
y = y.to(device)

# 3. Definiranje modela (jednostavna linearna regresija)
class LinearRegression(nn.Module):
    def __init__(self):
        super(LinearRegression, self).__init__()
        # Linearni sloj: ulazna dimenzija 1, izlazna dimenzija 1
        self.linear = nn.Linear(1, 1)

    def forward(self, x):
        return self.linear(x)

model = LinearRegression().to(device) # Premještanje modela na uređaj

# 4. Definiranje funkcije gubitka (Loss Function) i optimizatora
criterion = nn.MSELoss() # Srednja kvadratna pogreška
optimizer = optim.SGD(model.parameters(), lr=0.01) # Stochastic Gradient Descent

# 5. Treniranje modela
num_epochs = 1000
losses = []

print("\
Započinje treniranje modela...")
for epoch in range(num_epochs):
    # Forward pass: izračun predikcija
    outputs = model(X)

    # Izračun funkcije gubitka
    loss = criterion(outputs, y)

    # Backward pass i optimizacija (ažuriranje težina)
    optimizer.zero_grad() # Resetiranje gradijenata
    loss.backward()       # Izračun gradijenata
    optimizer.step()      # Ažuriranje težina

    losses.append(loss.item())

    if (epoch+1) % 100 == 0:
        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

print("Treniranje završeno.\
")

# 6. Prikaz rezultata
# Premještanje podataka natrag na CPU za vizualizaciju ako je model bio na GPU-u
predicted_y = model(X).detach().cpu().numpy()
X_cpu = X.cpu().numpy()
y_cpu = y.cpu().numpy()

plt.figure(figsize=(10, 6))
plt.scatter(X_cpu, y_cpu, label='Stvarni podaci')
plt.plot(X_cpu, predicted_y, color='red', label='Predviđena linija')
plt.xlabel('X')
plt.ylabel('y')
plt.title('Linearna regresija s PyTorch-om')
plt.legend()
plt.grid(True)
plt.show()

# Prikaz gubitka kroz epohe
plt.figure(figsize=(10, 6))
plt.plot(range(num_epochs), losses)
plt.xlabel('Epoha')
plt.ylabel('Gubitak (MSE)')
plt.title('Gubitak kroz epohe')
plt.grid(True)
plt.show()

# Ispis naučenih parametara
print(f"Naučeni parametri (Weights): {model.linear.weight.item():.4f}")
print(f"Naučeni parametri (Bias): {model.linear.bias.item():.4f}")

Objašnjenje koda:

  1. Određivanje uređaja: S torch.device("cuda" if torch.cuda.is_available() else "cpu") automatski biramo GPU ako je dostupan, inače CPU. Svi tenzori i modeli moraju biti na istom uređaju.
  2. Generiranje podataka: Stvaramo jednostavan sintetički skup podataka X i y. Važno je premjestiti ih na odabrani uređaj s .to(device).
  3. Definiranje modela: Definiramo klasu LinearRegression koja nasljeđuje nn.Module. U konstruktoru (__init__) definiramo slojeve mreže (u ovom slučaju jedan nn.Linear sloj). Metoda forward definira kako se ulazni podaci transformiraju kroz mrežu. Instanciramo model i premjestimo ga na device.
  4. Funkcija gubitka i optimizator: nn.MSELoss() se koristi za mjerenje razlike između predviđenih i stvarnih vrijednosti. optim.SGD() (Stochastic Gradient Descent) je algoritam za optimizaciju koji ažurira težine modela kako bi minimizirao funkciju gubitka.
  5. Treniranje modela:
    • Petlja for epoch in range(num_epochs) iterira kroz proces treniranja.
    • model(X): Predikcije modela (forward pass).
    • criterion(outputs, y): Izračun funkcije gubitka.
    • optimizer.zero_grad(): Prije svakog backward passa, gradijenti se moraju resetirati na nulu. Ako se to ne učini, gradijenti će se akumulirati iz prethodnih iteracija.
    • loss.backward(): Izračun gradijenata svih tenzora s requires_grad=True u odnosu na funkciju gubitka. Ovo je srce PyTorch-ovog autograd sustava.
    • optimizer.step(): Ažuriranje težina modela koristeći izračunate gradijente i pravila optimizatora.
  6. Prikaz rezultata: Nakon treniranja, možemo vizualizirati naučenu liniju i kako se gubitak smanjivao kroz epohe. Prilikom vizualizacije, tenzore s GPU-a moramo premjestiti natrag na CPU s .cpu() i pretvoriti ih u NumPy arraye s .numpy() za crtanje. .detach() je važan jer stvara kopiju tenzora koja više ne prati gradijente, što je sigurno za vizualizaciju.

Napredniji primjer: Klasifikacija slika s konvolucijskom neuronskom mrežom (CNN)

Za realističniji primjer s GPU akceleracijom, koristit ćemo konvolucijsku neuronsku mrežu (CNN) za klasifikaciju slika iz popularnog MNIST skupa podataka. MNIST sadrži slike ručno pisanih znamenki (0-9).

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt

# 1. Definiranje uređaja
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Korištenje uređaja: {device}")

# 2. Priprema podataka (MNIST)
# Definiramo transformacije za slike (normalizacija)
transform = transforms.Compose([
    transforms.ToTensor(), # Pretvara PIL sliku ili NumPy array u PyTorch Tensor
    transforms.Normalize((0.1307,), (0.3081,)) # Normalizira tenzor (srednja vrijednost, standardna devijacija)
])

# Preuzimanje i učitavanje MNIST skupa podataka
train_dataset = datasets.MNIST('./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST('./data', train=False, download=True, transform=transform)

# Stvaranje DataLoadera za batch obradu i miješanje podataka
train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=False)

# 3. Definiranje CNN modela
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3) # 1 ulazni kanal (grayscale), 32 izlazna kanala, kernel 3x3
        self.relu1 = nn.ReLU()
        self.maxpool1 = nn.MaxPool2d(kernel_size=2)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3)
        self.relu2 = nn.ReLU()
        self.maxpool2 = nn.MaxPool2d(kernel_size=2)
        self.dropout = nn.Dropout(0.25)
        self.fc1 = nn.Linear(64 * 5 * 5, 128) # 64 kanala * 5x5 dimenzije slike nakon konvolucija i poolinga
        self.relu3 = nn.ReLU()
        self.fc2 = nn.Linear(128, 10) # 10 izlaznih klasa (znamenke 0-9)

    def forward(self, x):
        x = self.conv1(x)
        x = self.relu1(x)
        x = self.maxpool1(x)
        x = self.conv2(x)
        x = self.relu2(x)
        x = self.maxpool2(x)
        x = self.dropout(x)
        x = x.view(-1, 64 * 5 * 5) # Poravnavanje (flattening) tenzora za ulaz u fully connected sloj
        x = self.fc1(x)
        x = self.relu3(x)
        x = self.fc2(x)
        return x

model = CNN().to(device) # Premještanje modela na uređaj

# 4. Funkcija gubitka i optimizator
criterion = nn.CrossEntropyLoss() # Prikladno za klasifikaciju s više klasa
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 5. Treniranje modela
num_epochs = 5

print("\
Započinje treniranje CNN modela...")
for epoch in range(num_epochs):
    model.train() # Postavljanje modela u način treniranja (dropout uključen)
    running_loss = 0.0
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device) # Premještanje batcha na uređaj

        optimizer.zero_grad()
        outputs = model(data)
        loss = criterion(outputs, target)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()

        if batch_idx % 100 == 0:
            print(f'Epoch: {epoch+1}, Batch: {batch_idx}/{len(train_loader)}, Loss: {loss.item():.4f}')
    
    print(f'Epoch {epoch+1} završena, Prosječan gubitak: {running_loss / len(train_loader):.4f}')

    # Evaluacija modela na testnom skupu nakon svake epohe
    model.eval() # Postavljanje modela u način evaluacije (dropout isključen)
    correct = 0
    total = 0
    with torch.no_grad(): # Isključivanje izračuna gradijenata za evaluaciju (štedi memoriju i ubrzava)
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)
            outputs = model(data)
            _, predicted = torch.max(outputs.data, 1) # Dobivanje indeksa s najvećom vjerojatnošću
            total += target.size(0)
            correct += (predicted == target).sum().item()
    
    print(f'Točnost na testnom skupu nakon epohe {epoch+1}: {100 * correct / total:.2f}%\
')

print("Treniranje CNN modela završeno.\
")

# 6. Pohrana i učitavanje modela (opcionalno)
# torch.save(model.state_dict(), 'mnist_cnn_model.pth')
# loaded_model = CNN().to(device)
# loaded_model.load_state_dict(torch.load('mnist_cnn_model.pth'))
# loaded_model.eval()

Objašnjenje ključnih dijelova za CNN:

  1. torchvision: Biblioteka koja nudi popularne skupove podataka (MNIST, CIFAR-10), arhitekture modela i transformacije slika.
  2. transforms.Compose: Nudi način za lančano povezivanje više transformacija koje se primjenjuju na slike. ToTensor() pretvara slike u PyTorch tenzore, a Normalize() ih normalizira kako bi se poboljšala stabilnost treniranja.
  3. DataLoader: Osigurava efikasno učitavanje podataka u batch-evima. Omogućuje nam postavljanje batch_size (broj uzoraka po batchu) i shuffle=True za miješanje podataka u svakoj epohi.
  4. CNN arhitektura:
    • nn.Conv2d: Konvolucijski sloj, ključan za prepoznavanje uzoraka u slikama. Parametri su: ulazni kanali (1 za grayscale MNIST), izlazni kanali (broj filtera), veličina kernela.
    • nn.ReLU: Aktivacijska funkcija koja dodaje nelinearnost.
    • nn.MaxPool2d: Smanjuje dimenzionalnost (pooling) i pomaže u postizanju invarijantnosti na pomake.
    • nn.Dropout: Tehnika regularizacije koja isključuje (drop-out) neke neurone tijekom treniranja kako bi se spriječilo preprjeđivanje (overfitting).
    • x.view(-1, ...): Prije nn.Linear sloja, izlaz konvolucijskih slojeva (koji je obično 4D tenzor: [batch_size, channels, height, width]) mora se poravnati u 2D tenzor ([batch_size, features]). -1 automatski izračunava batch veličinu.
  5. nn.CrossEntropyLoss: Pogodna funkcija gubitka za klasifikacijske probleme s više klasa. Ona kombinira log_softmax i NLLLoss.
  6. model.train() i model.eval(): Važno je prebacivati model između ovih načina. model.train() uključuje slojeve poput Dropout i BatchNorm (ako su prisutni) za treniranje, dok ih model.eval() isključuje za evaluaciju, osiguravajući dosljedne rezultate.
  7. with torch.no_grad(): Tijekom evaluacije, nema potrebe za izračunavanjem gradijenata. Korištenje ovog kontekstnog upravitelja isključuje autograd sustav, štedeći memoriju i ubrzavajući proces.
  8. torch.max(outputs.data, 1): Vraća maksimalnu vrijednost i njen indeks po određenoj dimenziji. U klasifikaciji, indeks najveće vjerojatnosti je predviđena klasa.

Savjeti za optimizaciju GPU korištenja

  • Koristite DataLoader s num_workers: Za ubrzavanje učitavanja podataka, DataLoader može koristiti više procesa s parametrom num_workers > 0. To omogućuje CPU-u da učitava podatke dok GPU trenira.
  • Smanjite veličinu batcha ako ponestaje GPU memorije: Ako dobijete CUDA out of memory pogrešku, smanjite batch_size.
  • Koristite torch.amp (Automatic Mixed Precision): Za novije GPU-ove (s Volta arhitekturom ili novijim), mješovita preciznost (float16 i float32) može značajno ubrzati treniranje i smanjiti potrošnju memorije bez značajnog gubitka točnosti.
  • Profiliranje koda: Koristite alate poput PyTorch Profilera da biste identificirali uska grla u vašem kodu.
  • Uvijek prebacite podatke i model na GPU: Ne zaboravite .to(device) za oba!
  • Izbjegavajte nepotrebne CPU-GPU prijenose: Prijenosi podataka između CPU-a i GPU-a su spori. Pokušajte držati sve što je moguće na GPU-u tijekom treniranja.

Zaključak

PyTorch je izuzetno moćan alat za strojno učenje koji, kada se koristi s GPU akceleracijom, otključava nevjerojatne mogućnosti za treniranje kompleksnih modela. Ovaj vodič pokrio je sve od osnovnog postavljanja okoline do implementacije linearne regresije i konvolucijske neuronske mreže, demonstrirajući kako iskoristiti GPU snagu. S ovim znanjem, spremni ste za istraživanje naprednijih tema i izgradnju vlastitih aplikacija strojnog učenja. Nastavite eksperimentirati s različitim arhitekturama, funkcijama gubitka i optimizatorima, te ne zaboravite pratiti službenu PyTorch dokumentaciju za najnovije značajke i najbolje prakse.

Izvori i dodatno čitanje

  1. Službena PyTorch Dokumentacija
  2. PyTorch Get Started Locally
  3. CUDA Toolkit Download
  4. NVIDIA Driver Downloads
B
Uredništvo portala

BAJT

Službeni autorski profil redakcije portala BAJT. Sadržaj priprema i provjerava uredništvo portala.