PyTorch – framework do uczenia maszynowego, budowania sieci neuronowych i rozwoju sztucznej inteligencji

PyTorch – framework do uczenia maszynowego, budowania sieci neuronowych i rozwoju sztucznej inteligencji

PyTorch to otwartoźródłowy framework przeznaczony do obliczeń tensorowych, uczenia maszynowego i tworzenia sieci neuronowych. Jest wykorzystywany przez badaczy, programistów, inżynierów danych oraz zespoły rozwijające rozwiązania oparte na sztucznej inteligencji. Umożliwia projektowanie modeli, prowadzenie treningu, obliczanie gradientów, korzystanie z akceleratorów sprzętowych, przetwarzanie dużych zbiorów danych oraz przygotowywanie modeli do późniejszego wdrożenia.

Popularność PyTorch wynika przede wszystkim z połączenia dużych możliwości obliczeniowych z elastycznym, zbliżonym do zwykłego Pythona sposobem programowania. Kod modelu można analizować krok po kroku, modyfikować w trakcie eksperymentów i integrować z wieloma narzędziami używanymi w analizie danych. Dzięki temu framework znajduje zastosowanie zarówno podczas nauki podstaw sieci neuronowych, jak i w rozbudowanych projektach obejmujących modele językowe, analizę obrazów, rozpoznawanie mowy, systemy rekomendacyjne czy generowanie treści.

PyTorch nie jest pojedynczym programem automatycznie tworzącym sztuczną inteligencję. To zestaw bibliotek, klas, funkcji i mechanizmów, z których programista buduje konkretny system. Framework dostarcza między innymi tensory, operacje matematyczne, automatyczne różniczkowanie, moduły sieci neuronowych, optymalizatory, narzędzia do ładowania danych i rozwiązania wspierające obliczenia rozproszone.

Co to jest PyTorch?

PyTorch jest biblioteką programistyczną służącą do wykonywania obliczeń numerycznych oraz tworzenia modeli uczenia maszynowego. Jego podstawową strukturą danych jest tensor, czyli wielowymiarowa tablica liczb. Tensory mogą reprezentować obrazy, tekst po przekształceniu na liczby, dźwięk, dane tabelaryczne, parametry modelu i wyniki pośrednich obliczeń.

Framework pozwala wykonywać operacje na tensorach za pomocą procesora głównego, procesora graficznego lub innego obsługiwanego akceleratora. W praktyce oznacza to, że ten sam ogólny sposób budowania modelu może być wykorzystywany zarówno na zwykłym komputerze, jak i na wydajnej infrastrukturze obliczeniowej.

Jedną z najważniejszych funkcji PyTorch jest automatyczne obliczanie gradientów. Podczas uczenia sieci neuronowej framework rejestruje operacje wykonywane na tensorach, a następnie wyznacza, w jaki sposób poszczególne parametry wpłynęły na wartość błędu. Gradienty są później używane przez optymalizator do aktualizacji wag modelu.

W uproszczeniu typowa praca z PyTorch obejmuje:

  • przygotowanie danych w postaci tensorów,
  • zdefiniowanie architektury modelu,
  • wykonanie predykcji,
  • obliczenie funkcji straty,
  • wyznaczenie gradientów,
  • aktualizację parametrów,
  • ocenę i zapis modelu.

Każdy z tych etapów można kontrolować, modyfikować i rozszerzać zgodnie z potrzebami projektu.

Do czego służy PyTorch?

PyTorch służy przede wszystkim do projektowania, trenowania i uruchamiania modeli uczenia maszynowego. Najczęściej kojarzy się go z deep learningiem, czyli uczeniem głębokim wykorzystującym wielowarstwowe sieci neuronowe. Framework może jednak wykonywać również ogólne obliczenia tensorowe i wspierać rozwiązania, które nie ograniczają się do klasycznych sieci neuronowych.

Klasyfikacja danych

Model klasyfikacyjny przypisuje dane wejściowe do jednej z określonych kategorii. Może na przykład rozpoznawać, jaki obiekt znajduje się na zdjęciu, określać temat dokumentu, wykrywać rodzaj usterki albo przypisywać wiadomości do odpowiednich działów.

PyTorch dostarcza elementy potrzebne do przygotowania takiego systemu: warstwy modelu, funkcje aktywacji, funkcje straty, optymalizatory i obsługę danych. Programista sam określa architekturę oraz sposób prowadzenia treningu.

Regresja i przewidywanie wartości

Regresja polega na przewidywaniu wartości liczbowej zamiast kategorii. Model może szacować cenę, zapotrzebowanie, czas realizacji, zużycie energii, poziom ryzyka lub inną wartość ciągłą.

W prostym przypadku model może składać się z kilku warstw liniowych. Bardziej złożone zadania wymagają uwzględnienia zależności czasowych, przestrzennych albo kontekstowych.

Analiza obrazów

PyTorch jest szeroko wykorzystywany w computer vision, czyli komputerowej analizie obrazu. Modele mogą rozpoznawać obiekty, klasyfikować zdjęcia, wykrywać elementy sceny, tworzyć maski segmentacyjne, poprawiać jakość obrazu lub generować nowe grafiki.

Obraz jest zazwyczaj reprezentowany jako tensor zawierający wartości pikseli. Model przetwarza go przez kolejne warstwy, stopniowo wyodrębniając cechy potrzebne do wykonania zadania.

Przetwarzanie języka naturalnego

W projektach NLP PyTorch może służyć do klasyfikowania tekstów, wyszukiwania informacji, tłumaczenia, odpowiadania na pytania, streszczania dokumentów i budowania modeli generujących język.

Tekst musi zostać najpierw zamieniony na reprezentację liczbową. Zwykle dzieli się go na tokeny, a następnie przypisuje im identyfikatory lub wektory. Dopiero takie dane mogą zostać przetworzone przez sieć neuronową.

Rozpoznawanie i generowanie mowy

Dźwięk może być analizowany jako fala, spektrogram lub inna reprezentacja numeryczna. PyTorch umożliwia tworzenie modeli rozpoznających mowę, klasyfikujących dźwięki, identyfikujących mówców i generujących sygnały audio.

Tego rodzaju projekty są wymagające obliczeniowo, dlatego możliwość korzystania z GPU oraz trenowania rozproszonego ma w nich szczególne znaczenie.

Systemy rekomendacyjne

System rekomendacyjny przewiduje, jakie produkty, filmy, artykuły, utwory lub usługi mogą zainteresować użytkownika. Model może analizować historię aktywności, podobieństwo elementów i zachowania innych osób.

PyTorch pozwala tworzyć reprezentacje użytkowników i obiektów, trenować modele rankingowe oraz łączyć różne źródła informacji. Rozwiązania rekomendacyjne są stosowane w handlu elektronicznym, mediach, edukacji i platformach społecznościowych.

Modele generatywne

Modele generatywne tworzą nowe treści na podstawie wzorców poznanych podczas treningu. Mogą generować tekst, obraz, dźwięk, kod, animacje lub dane syntetyczne.

PyTorch jest wykorzystywany do rozwijania modeli transformatorowych, sieci generatywnych, modeli dyfuzyjnych i innych architektur. Framework pozwala eksperymentować zarówno z gotowymi rozwiązaniami, jak i z całkowicie nowymi konstrukcjami.

Uczenie ze wzmocnieniem

W reinforcement learning agent podejmuje działania w określonym środowisku i otrzymuje nagrody lub kary. Jego celem jest nauczenie się strategii maksymalizującej długoterminowy rezultat.

PyTorch może odpowiadać za budowę sieci oceniającej stany, wybierającej działania lub aproksymującej funkcję wartości. Uczenie ze wzmocnieniem znajduje zastosowanie w robotyce, grach, optymalizacji i sterowaniu.

Historia i rozwój PyTorch

PyTorch wyrósł z wcześniejszych doświadczeń związanych z biblioteką Torch. Został zaprojektowany z myślą o środowisku Python i elastycznym budowaniu modeli. Szybko zdobył popularność w środowisku naukowym, ponieważ ułatwiał testowanie nowych architektur i analizowanie przebiegu obliczeń.

Z czasem framework przestał być postrzegany wyłącznie jako narzędzie badawcze. Rozbudowano mechanizmy kompilacji, eksportu, optymalizacji, przetwarzania rozproszonego i uruchamiania modeli w środowiskach produkcyjnych.

Rozwój PyTorch dobrze pokazuje zmianę zachodzącą w branży sztucznej inteligencji. Początkowo kluczowa była swoboda eksperymentowania, natomiast obecnie równie ważne są wydajność, skalowalność, powtarzalność i możliwość wdrażania modeli na różnym sprzęcie.

Najważniejsze elementy PyTorch

PyTorch składa się z wielu modułów, lecz kilka z nich pojawia się w niemal każdym projekcie.

Pakiet torch

torch jest podstawowym pakietem biblioteki. Zawiera definicję tensora, operacje matematyczne, narzędzia losujące, funkcje związane ze sprzętem oraz wiele mechanizmów potrzebnych podczas budowania modeli.

Typowy program rozpoczyna się od:

import torch

Następnie można tworzyć tensory, wykonywać na nich operacje i sprawdzać dostępność urządzeń obliczeniowych.

Moduł torch.nn

torch.nn zawiera klasy i funkcje przeznaczone do tworzenia sieci neuronowych. Znajdują się w nim między innymi warstwy liniowe, warstwy splotowe, funkcje aktywacji, normalizacja, dropout i funkcje straty.

Model najczęściej dziedziczy po klasie nn.Module. W konstruktorze definiuje się warstwy, natomiast w metodzie forward określa sposób przepływu danych.

Moduł torch.optim

torch.optim udostępnia optymalizatory zmieniające parametry modelu na podstawie gradientów. Do znanych metod należą między innymi SGD i Adam.

Optymalizator otrzymuje parametry modelu oraz podstawowe ustawienia, takie jak tempo uczenia. Po obliczeniu gradientów wykonuje krok aktualizujący wagi.

Dataset i DataLoader

Klasa Dataset opisuje sposób dostępu do pojedynczych przykładów, a DataLoader organizuje ich ładowanie w partie. Pozwala również mieszać kolejność danych, wykorzystywać procesy pomocnicze i sprawniej przygotowywać kolejne porcje do treningu.

Oddzielenie danych od modelu zwiększa czytelność projektu. Ta sama architektura może pracować z różnymi zbiorami, a jeden zbiór może być używany przez kilka modeli.

Autograd

Autograd odpowiada za automatyczne różniczkowanie. Framework buduje graf operacji prowadzących od danych i parametrów do wyniku, a następnie wykorzystuje regułę łańcuchową do obliczenia pochodnych.

Dzięki temu programista nie musi ręcznie wyprowadzać wzorów dla każdej warstwy. Nadal powinien jednak rozumieć znaczenie gradientu, funkcji straty i propagacji wstecznej.

Tensory w PyTorch

Tensor jest podstawowym obiektem używanym przez framework. Można go porównać do wielowymiarowej tablicy, która oprócz przechowywania liczb obsługuje obliczenia na akceleratorach i może uczestniczyć w automatycznym różniczkowaniu.

Wymiary tensora

Tensor skalarny może zawierać jedną liczbę. Wektor ma jeden wymiar, macierz dwa, a dane o większej liczbie osi tworzą tensory wyższych rzędów.

Przykładowo partia kolorowych obrazów może mieć kształt opisujący:

  • liczbę obrazów,
  • liczbę kanałów,
  • wysokość,
  • szerokość.

Kolejność osi ma znaczenie. Warstwa oczekująca określonego układu wymiarów zgłosi błąd albo zwróci nieprawidłowy wynik, jeśli otrzyma tensor w innym formacie.

Tworzenie tensorów

Tensor można utworzyć na podstawie listy, tablicy innej biblioteki, wartości losowych albo danych wczytanych z pliku.

import torch

x = torch.tensor([[1.0, 2.0], [3.0, 4.0]])
zeros = torch.zeros(2, 3)
ones = torch.ones(2, 3)
random_values = torch.rand(2, 3)

Każdy obiekt ma określony kształt, typ danych i urządzenie.

Typ danych

Typ danych określa sposób przechowywania wartości. Może to być liczba całkowita, zmiennoprzecinkowa lub logiczna. Wybór typu wpływa na pamięć, dokładność i dostępność operacji.

Parametry sieci najczęściej mają typ zmiennoprzecinkowy. Etykiety klas wykorzystywane przez niektóre funkcje straty powinny być natomiast liczbami całkowitymi.

Zmiana kształtu

Operacje takie jak reshape, view, squeeze, unsqueeze i permute pozwalają dostosować wymiary tensora do wymagań modelu.

Zmiana kształtu nie powinna modyfikować semantycznego znaczenia danych. Programista musi rozumieć, co reprezentuje każda oś.

Operacje na tensorach

PyTorch obsługuje dodawanie, mnożenie, potęgowanie, redukcje, iloczyny macierzy, indeksowanie i wiele innych operacji.

a = torch.tensor([1.0, 2.0, 3.0])
b = torch.tensor([4.0, 5.0, 6.0])

sum_values = a + b
product = a * b
average = a.mean()

Operacje mogą być wykonywane element po elemencie albo zgodnie z zasadami algebry liniowej.

Broadcasting

Broadcasting umożliwia wykonywanie działań na tensorach o różnych, ale zgodnych kształtach. Mniejszy tensor jest logicznie rozszerzany do potrzeb operacji bez konieczności ręcznego kopiowania wszystkich danych.

Mechanizm jest wygodny, ale może prowadzić do trudnych do wykrycia błędów. Jeżeli wynik ma nieoczekiwany kształt, warto sprawdzić, czy broadcasting nie został zastosowany w sposób inny niż planowano.

Tensory na GPU

Tensor może zostać przeniesiony na obsługiwane urządzenie obliczeniowe. Model i jego dane powinny znajdować się na tym samym urządzeniu.

Ogólny schemat może wyglądać następująco:

device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")

x = x.to(device)
model = model.to(device)

Samo użycie GPU nie gwarantuje przyspieszenia. Małe operacje mogą być ograniczone kosztem przesyłania danych i uruchamiania jąder obliczeniowych. Największe korzyści pojawiają się zwykle w obciążeniach o dużej intensywności obliczeniowej.

Automatyczne różniczkowanie i autograd

Uczenie sieci neuronowej polega na takim modyfikowaniu parametrów, aby zmniejszać błąd predykcji. Do ustalenia kierunku zmian potrzebne są gradienty funkcji straty względem wag modelu.

PyTorch automatyzuje ten proces.

requires_grad

Tensor może mieć ustawiony parametr requires_grad=True. Oznacza to, że framework powinien śledzić operacje wykonywane z jego udziałem, aby później obliczyć gradient.

Parametry warstw sieci neuronowej są zazwyczaj konfigurowane w ten sposób automatycznie.

Graf obliczeniowy

Podczas wykonywania operacji powstaje graf zależności. Każdy wynik wie, z jakich wcześniejszych działań został utworzony. Po wywołaniu propagacji wstecznej graf jest przechodzony w odwrotnym kierunku.

Dynamiczny charakter grafu ułatwia stosowanie instrukcji warunkowych, pętli oraz architektur zmieniających sposób działania w zależności od danych.

Backward

Metoda backward() rozpoczyna obliczanie gradientów.

loss.backward()

Po jej wykonaniu gradienty parametrów modelu są dostępne w polach .grad. Optymalizator wykorzystuje je podczas aktualizacji.

Zerowanie gradientów

PyTorch domyślnie akumuluje gradienty. Oznacza to, że przed kolejną iteracją należy je wyzerować, o ile celowo nie prowadzi się akumulacji.

optimizer.zero_grad()
loss.backward()
optimizer.step()

Pominięcie zerowania może powodować niezamierzone sumowanie wartości i nieprawidłowy przebieg treningu.

Wyłączanie śledzenia gradientów

Podczas walidacji i inferencji gradienty nie są zwykle potrzebne. Wyłączenie ich obliczania zmniejsza zużycie pamięci i narzut obliczeniowy.

with torch.no_grad():
    predictions = model(inputs)

W nowszych przepływach inferencyjnych można również korzystać z trybów specjalnie przeznaczonych do wykonywania obliczeń bez budowania grafu gradientów.

Budowanie modelu w PyTorch

Model jest najczęściej klasą dziedziczącą po torch.nn.Module. Konstruktor definiuje jego elementy, a metoda forward opisuje przetwarzanie danych.

import torch
from torch import nn

class SimpleNetwork(nn.Module):
    def __init__(self, input_size: int, hidden_size: int, classes: int):
        super().__init__()
        self.layers = nn.Sequential(
            nn.Linear(input_size, hidden_size),
            nn.ReLU(),
            nn.Linear(hidden_size, classes),
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return self.layers(x)

Tak zdefiniowany model można przenieść na urządzenie, przekazać do optymalizatora i trenować.

Warstwa liniowa

nn.Linear realizuje transformację liniową z uwzględnieniem wag i opcjonalnego wyrazu wolnego. Jest podstawowym elementem sieci gęstych, klasyfikatorów i fragmentów bardziej złożonych modeli.

Funkcje aktywacji

Bez funkcji nieliniowych wiele warstw liniowych zachowywałoby się jak jedna transformacja liniowa. Aktywacje pozwalają modelowi reprezentować bardziej złożone zależności.

Popularne przykłady to ReLU, sigmoid, tanh i GELU. Wybór zależy od architektury oraz miejsca zastosowania.

nn.Sequential

nn.Sequential pozwala utworzyć prosty ciąg warstw. Dane przechodzą kolejno przez wszystkie elementy w podanej kolejności.

Rozwiązanie jest czytelne dla modeli o liniowym przepływie. Gdy architektura zawiera wiele wejść, połączenia resztkowe lub warunki, lepiej samodzielnie opisać działanie w metodzie forward.

Parametry modelu

Metoda model.parameters() zwraca parametry, które mogą być optymalizowane. Można również przeglądać nazwane parametry i wybierać różne ustawienia optymalizatora dla poszczególnych części sieci.

Tryb treningowy i ewaluacyjny

Model może działać w trybie treningowym albo ewaluacyjnym:

model.train()
model.eval()

Zmiana wpływa na działanie warstw takich jak dropout i normalizacja wsadowa. Samo wyłączenie gradientów nie zastępuje wywołania eval(), ponieważ są to dwa różne mechanizmy.

Przygotowanie danych

Jakość i poprawność danych często mają większy wpływ na wynik niż niewielkie zmiany architektury. PyTorch umożliwia zbudowanie własnego przepływu ładowania i przekształcania przykładów.

Klasa Dataset

Własny Dataset powinien zwykle implementować metody zwracające liczbę przykładów oraz pojedynczy element.

from torch.utils.data import Dataset

class CustomDataset(Dataset):
    def __init__(self, features, labels):
        self.features = features
        self.labels = labels

    def __len__(self):
        return len(self.features)

    def __getitem__(self, index):
        return self.features[index], self.labels[index]

Dzięki temu format danych zostaje oddzielony od pętli treningowej.

DataLoader

DataLoader łączy przykłady w partie i dostarcza je do modelu.

from torch.utils.data import DataLoader

loader = DataLoader(
    dataset,
    batch_size=32,
    shuffle=True,
)

Parametr shuffle=True jest często stosowany dla zbioru treningowego, aby ograniczyć wpływ kolejności przykładów.

Wielkość partii

Batch size określa liczbę przykładów przetwarzanych przed aktualizacją parametrów. Większa partia może lepiej wykorzystać GPU, ale wymaga więcej pamięci. Mniejsza zwiększa zmienność gradientu i liczbę kroków.

Nie istnieje jedna prawidłowa wartość. Należy uwzględnić rozmiar modelu, pamięć, charakter danych i zachowanie optymalizacji.

Transformacje

Dane często wymagają normalizacji, zmiany rozmiaru, tokenizacji, uzupełniania sekwencji lub augmentacji. Transformacje mogą być wykonywane w klasie zbioru, osobnym pipeline albo wcześniej podczas przygotowania danych.

Augmentacja

Augmentacja tworzy zmodyfikowane wersje przykładów, zachowując ich znaczenie. Dla obrazu może to być obrót, odbicie, przycięcie lub zmiana jasności. Celem jest zwiększenie różnorodności i ograniczenie przeuczenia.

Transformacje muszą być rozsądne. Nie każda zmiana zachowuje etykietę. Odwrócenie obrazu może być właściwe w klasyfikacji zwierząt, ale błędne w rozpoznawaniu znaków lub tekstu.

Podział danych

Zbiór jest zwykle dzielony na część treningową, walidacyjną i testową. Zbiór treningowy służy do aktualizacji wag, walidacyjny do wyboru konfiguracji, a testowy do końcowej oceny.

Należy zapobiegać wyciekowi danych. Informacja ze zbioru testowego nie powinna wpływać na dobór modelu.

Pętla treningowa

Pętla treningowa jest centralnym elementem pracy z PyTorch. Framework daje dużą swobodę, dlatego programista może dokładnie kontrolować każdy etap.

for epoch in range(epochs):
    model.train()

    for inputs, targets in train_loader:
        inputs = inputs.to(device)
        targets = targets.to(device)

        optimizer.zero_grad()

        outputs = model(inputs)
        loss = loss_function(outputs, targets)

        loss.backward()
        optimizer.step()

Mimo niewielkiej liczby instrukcji w każdej iteracji wykonywany jest pełny proces: pobranie danych, predykcja, obliczenie błędu, propagacja wsteczna i aktualizacja parametrów.

Epoka

Epoka oznacza jedno pełne przejście przez zbiór treningowy. Liczba epok zależy od problemu i sposobu uczenia.

Zbyt mała liczba może prowadzić do niedouczenia. Zbyt długa praca może zwiększać ryzyko przeuczenia, szczególnie gdy wynik na zbiorze treningowym poprawia się, a na walidacyjnym pogarsza.

Funkcja straty

Funkcja straty określa, jak bardzo predykcja różni się od wartości oczekiwanej. Jej dobór zależy od zadania.

Klasyfikacja wieloklasowa, klasyfikacja binarna, regresja, segmentacja i uczenie reprezentacji wymagają różnych funkcji lub ich kombinacji.

Optymalizator

Optymalizator modyfikuje parametry w kierunku zmniejszającym stratę. Tempo uczenia jest jednym z najważniejszych hiperparametrów.

Zbyt wysokie tempo może powodować niestabilność, a zbyt niskie bardzo wolne uczenie. Często stosuje się harmonogramy zmieniające wartość w trakcie treningu.

Walidacja

Po każdej epoce lub określonej liczbie kroków warto ocenić model na danych walidacyjnych.

model.eval()
validation_loss = 0.0

with torch.no_grad():
    for inputs, targets in validation_loader:
        outputs = model(inputs.to(device))
        loss = loss_function(outputs, targets.to(device))
        validation_loss += loss.item()

Podczas walidacji nie aktualizuje się parametrów.

Metryki

Strata jest potrzebna do optymalizacji, ale nie zawsze jest najbardziej zrozumiałą miarą jakości. W zależności od problemu można obliczać dokładność, precyzję, czułość, F1, błąd średni, miary rankingowe lub inne wskaźniki.

Metryka powinna odpowiadać rzeczywistemu celowi biznesowemu albo naukowemu.

Funkcje straty w PyTorch

Dobór funkcji straty wpływa na to, czego model faktycznie się uczy.

CrossEntropyLoss

Jest często używana w klasyfikacji wieloklasowej. Model zwraca wyniki dla poszczególnych klas, a funkcja porównuje je z prawidłowymi etykietami.

Istotne jest dostarczenie danych w oczekiwanym formacie. Nieprawidłowe użycie dodatkowej funkcji softmax przed stratą może prowadzić do problemów, jeśli dana implementacja oczekuje surowych logitów.

BCEWithLogitsLoss

Stosuje się ją między innymi w klasyfikacji binarnej i wieloetykietowej. Łączy operację sigmoidalną z obliczeniem straty w sposób korzystny numerycznie.

MSELoss

Błąd średniokwadratowy jest popularny w regresji. Silniej karze duże różnice, ponieważ błąd jest podnoszony do kwadratu.

L1Loss

Strata L1 wykorzystuje wartość bezwzględną różnicy. Bywa mniej wrażliwa na pojedyncze bardzo duże odchylenia niż błąd kwadratowy.

Własna funkcja straty

W PyTorch można tworzyć własne funkcje, łącząc operacje tensorowe. Autograd obliczy gradienty, o ile wykorzystane operacje są różniczkowalne i obsługiwane.

Własna strata powinna mieć sens matematyczny oraz odpowiadać zadaniu. Nie wystarczy, że kod działa bez błędu.

Optymalizatory

Optymalizator wpływa na szybkość i stabilność treningu.

SGD

Stochastic Gradient Descent aktualizuje parametry na podstawie gradientów obliczonych dla partii danych. Może korzystać z momentum, które wygładza kierunek aktualizacji.

SGD pozostaje ważnym wyborem, szczególnie w niektórych zadaniach związanych z obrazem i tam, gdzie odpowiednio dobrany harmonogram przynosi dobrą generalizację.

Adam

Adam dostosowuje skalę aktualizacji na podstawie oszacowań pierwszego i drugiego momentu gradientów. Jest często wybierany na początku eksperymentów, ponieważ zwykle działa stabilnie bez bardzo rozbudowanego strojenia.

Nie oznacza to, że zawsze zapewnia najlepszy wynik końcowy.

AdamW

AdamW rozdziela mechanizm zaniku wag od właściwej aktualizacji gradientowej. Jest powszechnie wykorzystywany w trenowaniu transformatorów i wielu nowoczesnych architektur.

Weight decay

Weight decay ogranicza wzrost parametrów i może pełnić funkcję regularizacji. Jego wpływ zależy od optymalizatora i sposobu implementacji.

Scheduler

Scheduler zmienia tempo uczenia w czasie. Może je zmniejszać stopniowo, reagować na brak poprawy albo realizować bardziej złożony harmonogram.

Dobrze dobrany przebieg learning rate często poprawia stabilność i jakość modelu.

Sieci konwolucyjne

Konwolucyjne sieci neuronowe, określane jako CNN, są szczególnie dobrze dostosowane do danych posiadających strukturę przestrzenną.

Warstwy splotowe

Warstwa splotowa przesuwa zestaw filtrów po danych wejściowych. Filtry uczą się wykrywać lokalne wzorce, takie jak krawędzie, tekstury i bardziej złożone elementy.

W głębszych warstwach reprezentacje stają się bardziej abstrakcyjne.

Pooling

Pooling zmniejsza rozdzielczość map cech. Może redukować koszt obliczeń i zwiększać odporność na niewielkie przesunięcia.

Nie każda nowoczesna architektura korzysta z klasycznego poolingu. Czasami zmniejszenie rozmiaru jest realizowane przez splot z odpowiednim krokiem.

Liczba kanałów

Pierwsza warstwa obrazu kolorowego może otrzymywać trzy kanały, natomiast kolejne warstwy tworzą większą liczbę map cech.

Liczba kanałów wpływa na pojemność modelu, koszt obliczeń i zużycie pamięci.

Segmentacja obrazu

W segmentacji model przypisuje etykietę każdemu pikselowi. Architektura musi zachować lub odtworzyć informację przestrzenną, dlatego często wykorzystuje część kodującą i dekodującą.

Sieci rekurencyjne i dane sekwencyjne

Sieci rekurencyjne zostały zaprojektowane do przetwarzania sekwencji. Mogą uwzględniać wcześniejsze elementy podczas analizy kolejnych kroków.

RNN

Podstawowa sieć rekurencyjna przekazuje stan ukryty z jednego kroku do następnego. W praktyce może mieć trudności z uczeniem bardzo długich zależności.

LSTM

LSTM wykorzystuje mechanizmy bramek kontrolujących przepływ informacji. Został zaprojektowany w celu ograniczenia problemu zanikających gradientów i zachowywania ważnych zależności przez dłuższy czas.

GRU

GRU jest prostszą konstrukcją o podobnym przeznaczeniu. W części zastosowań oferuje dobrą równowagę między złożonością a jakością.

Maskowanie i długość sekwencji

Sekwencje mają często różne długości. Można je uzupełniać do wspólnego rozmiaru i stosować maski wskazujące, które pozycje są rzeczywistymi danymi, a które wypełnieniem.

Transformatory w PyTorch

Transformator opiera się na mechanizmie uwagi i jest podstawą wielu współczesnych modeli językowych, wizualnych i multimodalnych.

Mechanizm attention

Attention pozwala modelowi określać, które elementy wejścia są najważniejsze dla przetwarzanej pozycji. Zamiast przekazywać informację wyłącznie krok po kroku, model może analizować zależności pomiędzy wieloma pozycjami.

Self-attention

W self-attention zapytania, klucze i wartości powstają na podstawie tej samej sekwencji. Umożliwia to budowanie kontekstowych reprezentacji tokenów.

Multi-head attention

Wielogłowicowa uwaga pozwala modelowi analizować różne rodzaje zależności równolegle. Każda głowica może skupiać się na innych relacjach.

Kodowanie pozycji

Sam mechanizm uwagi nie zawiera informacji o kolejności tokenów. Z tego powodu stosuje się kodowanie pozycyjne lub inne rozwiązania wprowadzające wiedzę o położeniu.

Maskowanie przy generowaniu

Model autoregresyjny nie powinien widzieć przyszłych tokenów podczas przewidywania kolejnego elementu. Maska blokuje dostęp do pozycji, które nie powinny być dostępne.

Koszt pamięci

Klasyczny mechanizm uwagi może wymagać dużej ilości pamięci wraz ze wzrostem długości sekwencji. Dlatego rozwijane są optymalizacje jąder, alternatywne mechanizmy i techniki dzielenia obliczeń.

PyTorch i modele językowe

Duże modele językowe mogą być trenowane, dostrajane i uruchamiane przy użyciu PyTorch oraz bibliotek rozwijanych wokół jego ekosystemu.

Tokenizacja

Tekst jest dzielony na tokeny, którym przypisuje się identyfikatory. Token nie zawsze odpowiada całemu słowu. Może być fragmentem wyrazu, znakiem albo inną jednostką.

Embedding

Warstwa embedding zamienia identyfikator tokenu na gęsty wektor. Podczas treningu model uczy się reprezentacji przydatnych w danym zadaniu.

Pretraining

Podczas wstępnego treningu model uczy się na dużym zbiorze danych, najczęściej poprzez przewidywanie brakującego lub kolejnego tokenu. Taki etap wymaga ogromnych zasobów w przypadku dużych modeli.

Fine-tuning

Dostrajanie polega na dalszym treningu gotowego modelu na mniejszym, bardziej wyspecjalizowanym zbiorze. Może obejmować wszystkie parametry albo tylko ich wybraną część.

Efektywne dostrajanie

Metody oszczędzające parametry pozwalają zmieniać małe moduły lub niskowymiarowe reprezentacje zamiast całej sieci. Ogranicza to zapotrzebowanie na pamięć i ułatwia przechowywanie wielu wariantów.

Inferencja

Uruchamianie dużego modelu wymaga zarządzania pamięcią, precyzją, buforami uwagi i sposobem generowania. Sam model może działać poprawnie, ale osiągać zbyt małą przepustowość do zastosowania produkcyjnego.

Transfer learning

Transfer learning wykorzystuje wiedzę zdobytą przez model podczas wcześniejszego treningu. Zamiast rozpoczynać od losowych wag, można użyć modelu wytrenowanego na dużym zbiorze i dostosować go do nowego problemu.

Ekstrakcja cech

Część modelu może zostać zamrożona i pełnić funkcję ekstraktora cech. Trenowana jest wtedy tylko nowa warstwa wyjściowa.

Rozwiązanie jest przydatne przy małym zbiorze danych i ograniczonych zasobach.

Pełne dostrajanie

W pełnym fine-tuningu wszystkie lub większość parametrów może być aktualizowana. Zwykle stosuje się mniejsze tempo uczenia niż podczas treningu od początku.

Zamrażanie parametrów

Parametr można wyłączyć z obliczania gradientu. Należy również upewnić się, że optymalizator otrzymuje właściwy zestaw wag.

Stopniowe odmrażanie

Niektóre strategie rozpoczynają trening od warstw końcowych, a następnie stopniowo odblokowują wcześniejsze części modelu. Może to ograniczać gwałtowne niszczenie wcześniej poznanych reprezentacji.

Zapisywanie i wczytywanie modeli

Wytrenowany model powinien zostać zapisany w sposób umożliwiający późniejsze odtworzenie.

State dict

Najczęściej zapisuje się state_dict, czyli słownik parametrów i buforów modelu.

torch.save(model.state_dict(), \"model_weights.pth\")

Podczas wczytywania trzeba utworzyć instancję tej samej architektury, a następnie załadować stan.

model = SimpleNetwork(input_size, hidden_size, classes)
model.load_state_dict(torch.load(\"model_weights.pth\"))
model.eval()

Checkpoint

Checkpoint może zawierać nie tylko wagi, ale też stan optymalizatora, numer epoki, ustawienia harmonogramu i metryki.

torch.save(
    {
        \"epoch\": epoch,
        \"model_state\": model.state_dict(),
        \"optimizer_state\": optimizer.state_dict(),
        \"loss\": loss_value,
    },
    \"checkpoint.pth\",
)

Tak zapisany stan pozwala kontynuować przerwany trening.

Najlepszy model

Nie zawsze warto zapisywać wyłącznie ostatnią epokę. Model z najlepszym wynikiem walidacyjnym może pojawić się wcześniej.

Mechanizm checkpointów powinien przechowywać wersję spełniającą wybrane kryterium.

Bezpieczeństwo wczytywania

Pliki modeli powinny pochodzić z zaufanego źródła. Mechanizmy serializacji mogą wiązać się z ryzykiem, jeżeli użytkownik otwiera niezweryfikowane artefakty.

PyTorch na GPU

Akceleracja GPU jest jedną z najważniejszych zalet frameworka. Operacje macierzowe i tensorowe mogą być wykonywane równolegle, co znacznie skraca czas treningu dużych modeli.

Przenoszenie modelu i danych

Model oraz dane muszą znajdować się na tym samym urządzeniu. Częstym błędem jest przeniesienie modelu na GPU przy pozostawieniu etykiet lub części danych w pamięci CPU.

Pamięć GPU

Pamięć karty jest ograniczona. Najwięcej miejsca zajmują zwykle:

  • parametry modelu,
  • gradienty,
  • stan optymalizatora,
  • aktywacje potrzebne do propagacji wstecznej,
  • partie danych.

Zmniejszenie batch size jest najprostszą metodą ograniczenia zużycia pamięci, lecz nie zawsze jedyną.

Mixed precision

Trening mieszanej precyzji wykorzystuje typy liczb o mniejszej liczbie bitów tam, gdzie jest to bezpieczne. Może zmniejszać zużycie pamięci i przyspieszać obliczenia.

Wymaga jednak kontroli stabilności numerycznej. Niektóre operacje powinny pozostać w wyższej precyzji.

Akumulacja gradientów

Gdy duża partia nie mieści się w pamięci, można wykonać kilka mniejszych kroków forward i backward, a aktualizację parametrów przeprowadzić dopiero po zgromadzeniu gradientów.

Należy wtedy odpowiednio przeskalować stratę i pamiętać o rzadszym zerowaniu gradientów.

Gradient checkpointing

Checkpointing aktywacji ogranicza pamięć przez nieprzechowywanie części wyników pośrednich. Brakujące aktywacje są ponownie obliczane podczas propagacji wstecznej.

Jest to wymiana pamięci na dodatkowy czas obliczeń.

torch.compile

torch.compile umożliwia kompilowanie fragmentów programu PyTorch w celu poprawy wydajności. Funkcja analizuje wykonywany kod, przechwytuje grafy operacji i przekazuje je do mechanizmów optymalizujących.

Przykładowe użycie jest proste:

compiled_model = torch.compile(model)

Nie oznacza to jednak, że każdy program automatycznie przyspieszy w takim samym stopniu.

Dlaczego kompilacja może przyspieszać?

Wykonywanie wielu małych operacji jedna po drugiej wiąże się z narzutem. Kompilator może łączyć działania, optymalizować przepływ danych i generować wydajniejsze jądra obliczeniowe.

Koszt pierwszego uruchomienia

Kompilacja wymaga czasu. Pierwsze wykonanie może być wolniejsze, ponieważ framework analizuje program i przygotowuje zoptymalizowaną wersję.

Korzyść pojawia się wtedy, gdy ten sam lub podobny graf jest później wykonywany wielokrotnie.

Graph breaks

Nie wszystkie fragmenty dynamicznego kodu można łatwo ująć w jeden graf. Przerwanie grafu powoduje powrót do zwykłego wykonania dla części programu i może ograniczać przyspieszenie.

Zmienny kształt danych

Zmiany kształtu tensorów mogą prowadzić do dodatkowych kompilacji, zależnie od kodu i konfiguracji. W aplikacji obsługującej bardzo różne długości sekwencji warto analizować wpływ dynamicznych wymiarów.

Kiedy używać torch.compile?

Funkcja jest szczególnie interesująca, gdy:

  • model wykonuje wiele powtarzalnych operacji,
  • trening lub inferencja trwa wystarczająco długo,
  • narzut kompilacji może się zwrócić,
  • kod jest zgodny z mechanizmem przechwytywania,
  • wydajność została zmierzona na rzeczywistym obciążeniu.

Nie należy zakładać poprawy bez benchmarku.

Trening rozproszony

Gdy jeden akcelerator jest niewystarczający, trening można rozdzielić pomiędzy wiele urządzeń lub maszyn.

Data parallelism

W równoległości danych każda jednostka obliczeniowa posiada kopię modelu, ale przetwarza inną część partii. Gradienty są następnie synchronizowane.

DistributedDataParallel

DistributedDataParallel jest standardowym rozwiązaniem do synchronicznego treningu rozproszonego. Najczęściej każdemu urządzeniu odpowiada osobny proces.

DDP zwykle lepiej skaluje się niż proste opakowania używające wielu GPU w jednym procesie.

DistributedSampler

Przy równoległości danych należy dopilnować, aby procesy otrzymywały różne fragmenty zbioru. Sampler rozproszony dzieli przykłady między jednostki.

Równoległość modelu

Jeżeli model nie mieści się na jednym urządzeniu, jego warstwy lub tensory można podzielić. Wymaga to bardziej złożonego zarządzania komunikacją.

Sharding parametrów

Techniki shardingu dzielą parametry, gradienty i stan optymalizatora pomiędzy urządzenia. Pozwala to trenować większe modele, ale zwiększa zależność od przepustowości komunikacji.

Trening wielowęzłowy

Wiele maszyn musi uzgodnić sposób dołączenia do wspólnego zadania, liczbę procesów, adres koordynatora i backend komunikacyjny.

Konfiguracja sieci, sterowników i wersji środowiska ma wtedy równie duże znaczenie jak sam kod modelu.

Eksport i wdrażanie modeli

Wytrenowanie modelu jest tylko jednym etapem. W zastosowaniu praktycznym trzeba jeszcze uruchomić go w usłudze, aplikacji, urządzeniu brzegowym albo innym środowisku.

Inferencja w Pythonie

Najprostsza aplikacja może bezpośrednio wczytać model PyTorch i wykonywać predykcje. Rozwiązanie jest wygodne, gdy środowisko produkcyjne korzysta z Pythona i obsługuje wymagane zależności.

torch.export

Eksport pozwala przechwycić obliczeniową reprezentację modelu i oddzielić ją od części dynamicznego kodu Pythona. Jest to istotne w scenariuszach, w których model ma zostać zoptymalizowany lub uruchomiony w innym środowisku.

ONNX

ONNX jest otwartym formatem reprezentacji modeli. Eksport może umożliwić wykorzystanie silników i urządzeń niezależnych od typowego środowiska treningowego.

Nie każdy model można wyeksportować bez zmian. Dynamiczny przepływ sterowania, niestandardowe operatory i nietypowe warstwy mogą wymagać dostosowania.

Test zgodności

Po eksporcie należy porównać wyniki oryginalnego i docelowego modelu na zestawie reprezentatywnych danych. Sam sukces operacji eksportowania nie gwarantuje identycznego zachowania.

Serwowanie modelu

Model może działać za interfejsem API. Usługa odbiera dane, wykonuje preprocessing, uruchamia inferencję i zwraca wynik.

Należy kontrolować nie tylko czas samego modelu, ale cały przepływ: serializację, sieć, kolejki, przygotowanie danych i późniejsze przetwarzanie.

Batch inference

W przetwarzaniu wsadowym wyniki są obliczane dla większego zbioru bez wymogu natychmiastowej odpowiedzi. Można wtedy lepiej wykorzystać sprzęt i ograniczyć koszt jednostkowy.

Inferencja czasu rzeczywistego

System czasu rzeczywistego musi zachować niskie opóźnienie. Czasem ważniejsze od maksymalnej przepustowości jest szybkie przetwarzanie pojedynczego żądania.

Optymalizacja modeli

Duży model może być dokładny, ale zbyt wolny lub kosztowny. Optymalizacja ma dostosować go do konkretnego środowiska.

Kwantyzacja

Kwantyzacja wykorzystuje reprezentacje o mniejszej precyzji. Może zmniejszać rozmiar i przyspieszać inferencję, szczególnie na sprzęcie obsługującym odpowiednie instrukcje.

Obniżenie precyzji może jednak wpływać na jakość. Wynik należy zweryfikować na rzeczywistych danych.

Pruning

Pruning usuwa lub wygasza mniej istotne parametry. Samo uzyskanie wielu zer nie zawsze daje przyspieszenie, ponieważ sprzęt i biblioteka muszą wykorzystywać rzadką strukturę.

Knowledge distillation

Destylacja wiedzy polega na trenowaniu mniejszego modelu przy użyciu sygnałów generowanych przez większy model nauczycielski. Uczeń próbuje odtworzyć nie tylko końcowe etykiety, lecz także rozkład predykcji lub reprezentacje.

Łączenie operacji

Fuzja zmniejsza liczbę osobnych uruchomień i transferów pamięci. Kompilatory mogą wykonywać część takich optymalizacji automatycznie.

Profilowanie

Optymalizację należy rozpoczynać od pomiaru. Profilowanie pokazuje, które operacje rzeczywiście zajmują najwięcej czasu lub pamięci.

Bez pomiaru łatwo poświęcić wiele pracy na fragment, który nie ogranicza całej aplikacji.

Debugowanie w PyTorch

Elastyczność frameworka ułatwia analizę, ale modele nadal mogą zawierać błędy logiczne, które nie zawsze prowadzą do wyjątku.

Kontrola kształtów

Wiele problemów wynika z nieprawidłowych wymiarów. Warto sprawdzać kształty danych po kluczowych warstwach.

print(inputs.shape)
print(outputs.shape)

W kodzie produkcyjnym można stosować asercje i jawne sprawdzanie danych.

Kontrola wartości

Wartości NaN lub nieskończoności mogą pojawić się z powodu niestabilności numerycznej, zbyt wysokiego learning rate albo błędnego przetwarzania.

Należy kontrolować stratę, gradienty i rozkłady aktywacji.

Sprawdzanie gradientów

Brak gradientu może wynikać z odłączenia tensora od grafu, użycia operacji niediferencjowalnej albo nieprawidłowego ustawienia parametrów.

Z kolei bardzo duże gradienty mogą prowadzić do niestabilności. W części modeli stosuje się ich przycinanie.

Test na małym zbiorze

Model powinien często potrafić niemal zapamiętać bardzo małą próbkę. Jeśli nie jest w stanie obniżyć na niej straty, przyczyną może być błąd w danych, architekturze lub pętli treningowej.

Powtarzalność

Ustawienie ziarna generatora losowego ułatwia porównywanie eksperymentów. Pełna deterministyczność może jednak zależeć od sprzętu, operatorów i konfiguracji.

Anomaly detection

Mechanizmy wykrywania anomalii w autograd mogą pomóc ustalić, która operacja generuje nieprawidłowy gradient. Włączają dodatkowe kontrole i mogą spowalniać program, dlatego są używane głównie podczas debugowania.

Najczęstsze błędy początkujących

Brak model.eval()

Użytkownik wyłącza gradienty, ale pozostawia model w trybie treningowym. Dropout i normalizacja mogą wtedy działać inaczej niż podczas docelowej inferencji.

Niewyzerowane gradienty

Gradienty akumulują się pomiędzy krokami, prowadząc do niezamierzonej aktualizacji.

Różne urządzenia

Model znajduje się na GPU, a dane lub etykiety na CPU. Operacja kończy się błędem dotyczącym niezgodności urządzeń.

Nieprawidłowy format etykiet

Funkcja straty może oczekiwać indeksów klas, a otrzymywać wektory albo niewłaściwy typ liczbowy.

Podwójna aktywacja

Programista stosuje softmax lub sigmoid, mimo że funkcja straty już uwzględnia odpowiednią transformację.

Uczenie na zbiorze testowym

Wyniki testowe są wielokrotnie wykorzystywane do podejmowania decyzji, przez co zbiór przestaje być niezależną oceną.

Zbyt duży model

Architektura ma znacznie większą pojemność niż uzasadnia to ilość danych. Model szybko zapamiętuje trening i słabo generalizuje.

Brak normalizacji

Dane wejściowe mają bardzo różne skale, co utrudnia optymalizację. Sposób normalizacji powinien zależeć od problemu i architektury.

Ocena wyłącznie jedną metryką

W niezrównoważonej klasyfikacji wysoka dokładność może ukrywać całkowitą nieskuteczność wobec rzadkiej, ale ważnej klasy.

Instalacja PyTorch

Sposób instalacji zależy od systemu operacyjnego, środowiska Pythona i dostępnego sprzętu. Najbezpieczniej korzystać z oficjalnego konfiguratora, ponieważ zgodność wersji frameworka, sterowników i środowiska akceleratora może się zmieniać.

Środowisko wirtualne

Warto utworzyć osobne środowisko dla projektu. Ogranicza to konflikty zależności i ułatwia odtworzenie konfiguracji.

Można korzystać między innymi z venv, narzędzi opartych na Condzie lub innych menedżerów środowisk.

Instalacja CPU

Wersja przeznaczona wyłącznie dla CPU wystarcza do nauki podstaw, testowania małych modeli i części zastosowań produkcyjnych.

Instalacja z akceleracją

Instalacja obsługująca GPU musi być dopasowana do platformy i sterownika. Nie należy losowo kopiować komendy znalezionej w starym poradniku.

Sprawdzenie instalacji

Po instalacji warto sprawdzić wersję i dostępność urządzenia:

import torch

print(torch.__version__)
print(torch.cuda.is_available())

Samo zwrócenie wartości False nie oznacza błędu biblioteki. Przyczyną może być brak zgodnego urządzenia, sterownika lub właściwego pakietu.

Ekosystem PyTorch

Wokół frameworka rozwinęły się biblioteki przeznaczone do różnych typów danych i procesów.

Torchvision

Torchvision dostarcza narzędzia dla computer vision, w tym zbiory danych, transformacje i modele związane z obrazem.

Torchaudio

Torchaudio wspiera przetwarzanie dźwięku i mowy. Udostępnia operacje, komponenty i rozwiązania przydatne w projektach audio.

TorchData

Narzędzia danych pomagają budować skalowalne potoki wejściowe, szczególnie gdy dane pochodzą z wielu plików, strumieni lub usług.

TorchMetrics i narzędzia metryczne

Zewnętrzne biblioteki ekosystemu mogą ułatwiać obliczanie metryk, agregowanie wyników i pracę rozproszoną.

Biblioteki wysokiego poziomu

Istnieją frameworki upraszczające organizację treningu, konfigurację eksperymentów i obsługę wielu urządzeń. Mogą ograniczać ilość powtarzalnego kodu, ale nie zastępują rozumienia podstaw PyTorch.

Biblioteki modeli

Wiele projektów udostępnia gotowe architektury, wagi i narzędzia korzystające z PyTorch jako silnika obliczeniowego. Pozwala to budować rozwiązania bez trenowania wszystkiego od zera.

PyTorch a TensorFlow

PyTorch i TensorFlow są popularnymi frameworkami uczenia maszynowego. Oba umożliwiają tworzenie sieci neuronowych, korzystanie z akceleratorów i wdrażanie modeli.

Styl programowania

PyTorch jest często ceniony za naturalne powiązanie z Pythonem i przejrzyste wykonywanie modeli. TensorFlow również oferuje interfejsy wysokiego poziomu oraz wykonywanie dynamiczne i grafowe.

Różnice są mniejsze niż w początkowych etapach rozwoju obu ekosystemów, dlatego wybór powinien wynikać z konkretnych potrzeb.

Ekosystem

Ważne są dostępne biblioteki, sprzęt, kompetencje zespołu, istniejący kod i wymagania wdrożeniowe. Framework nie funkcjonuje w oderwaniu od całego środowiska.

Migracja

Przeniesienie modelu nie polega zwykle na automatycznej zamianie nazw funkcji. Trzeba odtworzyć architekturę, przekształcanie danych, inicjalizację, funkcję straty i sposób działania warstw.

Wybór rozwiązania

PyTorch może być dobrym wyborem, gdy zespół ceni elastyczność, intensywnie eksperymentuje, korzysta z jego ekosystemu lub rozwija modele dostępne właśnie w tym formacie.

TensorFlow może być atrakcyjny w organizacji posiadającej istniejącą infrastrukturę, kompetencje i narzędzia oparte na tym środowisku.

PyTorch a NumPy

NumPy jest podstawową biblioteką obliczeń tablicowych w Pythonie. PyTorch przypomina ją pod względem wielu operacji, ale dodaje funkcje kluczowe dla uczenia głębokiego.

Podobieństwa

Oba narzędzia obsługują wielowymiarowe tablice, indeksowanie, broadcasting, algebrę liniową i redukcje.

Różnice

PyTorch oferuje automatyczne różniczkowanie, moduły sieci neuronowych i obsługę akceleratorów. NumPy jest natomiast prostszym i niezwykle dojrzałym narzędziem do ogólnych obliczeń numerycznych.

Konwersja

Dane można przekazywać pomiędzy tablicami NumPy i tensorami PyTorch. W pewnych warunkach obiekty mogą współdzielić pamięć, dlatego modyfikacja jednego wpływa na drugi.

Zalety PyTorch

Do najważniejszych zalet frameworka należą:

  • elastyczny styl programowania,
  • czytelna integracja z Pythonem,
  • automatyczne obliczanie gradientów,
  • obsługa CPU i akceleratorów,
  • bogaty zestaw warstw i optymalizatorów,
  • możliwość tworzenia własnych operacji,
  • rozwinięty ekosystem,
  • wsparcie treningu rozproszonego,
  • narzędzia kompilacji i eksportu,
  • duża społeczność użytkowników.

Szczególnie ważna jest możliwość stopniowego zwiększania poziomu złożoności. Początkujący może zbudować prosty model w kilku klasach, a zaawansowany zespół rozwijać własne operatory, kompilatory i systemy wielowęzłowe.

Wady i ograniczenia PyTorch

Framework nie rozwiązuje automatycznie wszystkich problemów projektu.

Duża swoboda

Elastyczność może prowadzić do nieuporządkowanego kodu. Bez przyjęcia standardów eksperymenty stają się trudne do odtworzenia.

Wysokie wymagania sprzętowe

Duże modele potrzebują kosztownych akceleratorów, znacznej pamięci i szybkiej komunikacji. PyTorch umożliwia wykorzystanie takiej infrastruktury, ale jej nie zastępuje.

Złożoność produkcyjna

Kod badawczy nie zawsze nadaje się do bezpośredniego wdrożenia. Trzeba uwzględnić wersjonowanie, monitoring, bezpieczeństwo i skalowanie.

Zależności

Zgodność sterowników, bibliotek systemowych i wersji pakietów może sprawiać problemy. Środowisko powinno być dokładnie dokumentowane.

Koszt uczenia się

Podstawy API są stosunkowo przystępne, lecz skuteczne trenowanie modeli wymaga wiedzy z algebry liniowej, rachunku różniczkowego, statystyki, programowania i inżynierii danych.

PyTorch dla początkujących

Najlepsza nauka nie polega na zapamiętywaniu nazw wszystkich modułów. Warto przejść przez cały proces na małym zbiorze.

Etap pierwszy – Python i tablice

Przed rozpoczęciem dobrze znać funkcje, klasy, pętle, moduły i podstawowe operacje na tablicach.

Etap drugi – tensory

Należy przećwiczyć tworzenie tensorów, zmianę kształtu, indeksowanie, broadcasting i przenoszenie między urządzeniami.

Etap trzeci – autograd

Warto samodzielnie obliczyć prostą funkcję i sprawdzić gradient. Ułatwia to zrozumienie późniejszej pętli treningowej.

Etap czwarty – prosty model

Dobrym ćwiczeniem jest klasyfikator małego zbioru obrazów lub regresja na danych tabelarycznych.

Etap piąty – własna pętla treningowa

Początkujący powinien przynajmniej raz napisać pętlę bez frameworka wysokiego poziomu. Pozwoli to zrozumieć rolę każdego kroku.

Etap szósty – walidacja i checkpoint

Następnie warto dodać obliczanie metryk, zapis najlepszej wersji i odtwarzanie treningu.

Etap siódmy – gotowy model

Transfer learning pokazuje, jak wykorzystywać wcześniej wytrenowane reprezentacje i rozwiązywać praktyczne zadania przy mniejszym zbiorze danych.

Organizacja projektu PyTorch

Rosnący projekt powinien mieć przejrzystą strukturę.

Można oddzielić:

  • konfigurację,
  • kod modelu,
  • przygotowanie danych,
  • trening,
  • ewaluację,
  • inferencję,
  • narzędzia pomocnicze,
  • testy.

Nie istnieje jedna obowiązkowa struktura, ale należy unikać umieszczania całej logiki w jednym notebooku.

Konfiguracja eksperymentu

Hiperparametry powinny być zapisane w konfiguracji, a nie rozproszone po kodzie. Dotyczy to learning rate, batch size, liczby epok, ścieżek danych i ustawień modelu.

Logowanie

Należy zapisywać stratę, metryki, czas, wykorzystanie zasobów i identyfikator wersji kodu. Bez tego trudno porównać eksperymenty.

Wersjonowanie danych

Ten sam kod może dać inne wyniki na zmodyfikowanym zbiorze. Wersjonowanie danych i sposobu ich przetwarzania jest równie ważne jak wersjonowanie modelu.

Testy

Warto testować kształty, zakresy wartości, zachowanie warstw oraz poprawność ładowania checkpointów. Test jednostkowy nie potwierdzi jakości modelu, ale może wykryć wiele błędów implementacyjnych.

Monitorowanie treningu

Długie eksperymenty wymagają obserwacji.

Krzywe uczenia

Porównanie straty treningowej i walidacyjnej pomaga ocenić, czy model się uczy i czy zaczyna się przeuczać.

Gradienty i parametry

Rozkłady gradientów mogą wskazać zanikanie, eksplozję lub brak aktualizacji części modelu.

Wykorzystanie sprzętu

Niskie użycie GPU może oznaczać wolne ładowanie danych, zbyt małą partię albo wiele operacji wykonywanych na CPU.

Czas kroków

Pomiar czasu ładowania, forward, backward i aktualizacji pozwala znaleźć wąskie gardło.

Wczesne zatrzymanie

Early stopping przerywa trening, gdy wynik walidacyjny nie poprawia się przez określony czas. Pomaga ograniczyć koszt i przeuczenie.

PyTorch w zastosowaniach biznesowych

Framework może być wykorzystywany w wielu branżach, ale powodzenie zależy od połączenia modelu z rzeczywistym procesem.

Handel internetowy

Modele mogą wspierać rekomendacje, prognozowanie popytu, klasyfikowanie produktów i analizę treści ofert.

Przemysł

PyTorch może służyć do analizy obrazu z kamer, wykrywania wad, przewidywania awarii i optymalizacji procesów.

Finanse

Zastosowania obejmują analizę dokumentów, wykrywanie anomalii, ocenę ryzyka i modele szeregów czasowych. Decyzje o wysokim znaczeniu wymagają szczególnej kontroli, wyjaśnialności i zgodności regulacyjnej.

Medycyna

Modele mogą analizować obrazy, sygnały i tekst dokumentacji. Nie powinny być jednak traktowane jako automatyczny zamiennik oceny specjalisty. System medyczny wymaga walidacji klinicznej, bezpieczeństwa i odpowiedzialnego zarządzania danymi.

Marketing

Możliwe jest przewidywanie rezygnacji klientów, segmentacja, klasyfikacja treści i analiza reakcji. Należy unikać wykorzystywania danych w sposób naruszający prywatność.

Edukacja

Modele mogą wspierać wyszukiwanie materiałów, analizę odpowiedzi i personalizację. Trzeba kontrolować błędy oraz zapobiegać niesprawiedliwemu ocenianiu.

Bezpieczeństwo i etyka

Techniczna poprawność nie wystarcza do stworzenia odpowiedzialnego systemu.

Jakość danych

Dane mogą zawierać błędy, nierówną reprezentację grup i historyczne uprzedzenia. Model często odtwarza te wzorce.

Prywatność

Dane osobowe powinny być zbierane i przetwarzane zgodnie z prawem oraz rzeczywistą potrzebą. Zespół powinien kontrolować dostęp, retencję i bezpieczeństwo.

Wyjaśnialność

W części zastosowań konieczne jest uzasadnienie decyzji modelu. Sama wysoka trafność może być niewystarczająca.

Odporność

Model powinien być testowany na danych różniących się od treningowych, brakach, zakłóceniach i nietypowych przypadkach.

Monitoring produkcyjny

Rozkład danych może się zmieniać. Jakość modelu należy kontrolować również po wdrożeniu.

Nadzór człowieka

W decyzjach wpływających na zdrowie, bezpieczeństwo, zatrudnienie lub finanse powinien istnieć odpowiedni proces kontroli, odwołania i odpowiedzialności.

PyTorch a MLOps

MLOps obejmuje praktyki pozwalające rozwijać, wdrażać i utrzymywać modele w sposób powtarzalny.

Śledzenie eksperymentów

Każdy eksperyment powinien być powiązany z konfiguracją, kodem, danymi, metrykami i artefaktem modelu.

Rejestr modeli

Rejestr przechowuje wersje modeli, ich status i informacje o pochodzeniu. Ułatwia kontrolowane promowanie wersji do środowiska produkcyjnego.

Automatyczne testy

Pipeline może sprawdzać poprawność danych, uruchamiać testy kodu, trenować model i oceniać go przed wdrożeniem.

Ciągłe trenowanie

Nie każdy system wymaga ciągłego treningu. Nowa wersja powinna być tworzona, gdy dostępne są lepsze dane albo model traci jakość.

Rollback

Organizacja powinna móc szybko wrócić do wcześniejszej wersji, jeżeli nowe wdrożenie powoduje problemy.

Jak wybrać PyTorch do projektu?

Wybór frameworka powinien uwzględniać cały cykl życia rozwiązania.

PyTorch jest szczególnie uzasadniony, gdy:

  • zespół zna Pythona,
  • projekt wymaga eksperymentowania,
  • potrzebne modele są dostępne w jego ekosystemie,
  • planowane jest wykorzystanie GPU,
  • konieczne są własne architektury,
  • zespół potrzebuje kontroli nad pętlą treningową,
  • istnieje plan wdrożenia i monitorowania.

Przed rozpoczęciem warto odpowiedzieć na kilka pytań:

  • Czy problem rzeczywiście wymaga uczenia głębokiego?
  • Czy dostępne są wystarczające dane?
  • Jaki jest koszt błędnej predykcji?
  • Na jakim sprzęcie będzie działał model?
  • Jak szybko musi odpowiadać?
  • Kto będzie utrzymywał rozwiązanie?
  • Jak zostanie oceniona jakość biznesowa?
  • Czy istnieją ograniczenia prawne lub etyczne?

PyTorch jest potężnym narzędziem, ale nie powinien być wybierany wyłącznie dlatego, że deep learning jest popularny.

Przyszłość PyTorch

Rozwój frameworka zmierza w stronę łączenia elastyczności Pythona z coraz większą wydajnością wykonania. Kompilacja, automatyczna fuzja operacji, rozproszone tensory, eksport oraz obsługa różnych akceleratorów sprawiają, że granica pomiędzy kodem eksperymentalnym i produkcyjnym stopniowo się zmniejsza.

Rosnące modele zwiększają znaczenie optymalizacji pamięci, komunikacji i precyzji numerycznej. Jednocześnie coraz więcej projektów koncentruje się na uruchamianiu mniejszych modeli lokalnie, na urządzeniach brzegowych i w środowiskach o ograniczonych zasobach.

PyTorch pozostaje frameworkiem pozwalającym pracować na wielu poziomach abstrakcji. Użytkownik może korzystać z gotowych modułów, budować własne warstwy albo rozwijać rozszerzenia niskopoziomowe. Ta możliwość dopasowania narzędzia do skali projektu jest jedną z jego największych wartości.

PyTorch łączy obliczenia tensorowe, automatyczne różniczkowanie, moduły sieci neuronowych i narzędzia skalowania w jednym ekosystemie. Dzięki temu może służyć zarówno do nauki, szybkiego prototypowania, badań naukowych, jak i tworzenia systemów wykorzystujących modele sztucznej inteligencji w praktycznych zastosowaniach.

Opublikuj komentarz