Machine Learning Academy · Lekcja

Tworzenie sieci jednokierunkowej za pomocą nn.Module

Uczą się Państwo dziedziczyć po nn.Module, układać warstwy Linear i ReLU w __init__, implementować przebieg w przód oraz sprawdzać kształty wyjścia za pomocą przykładowych danych wejściowych.

Lekcja 3 z 413 kroki

Tworzenie sieci jednokierunkowej za pomocą nn.Module to bezpłatna lekcja Machine Learning Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Machine Learning Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Machine Learning Academy zawiera 4 lekcji w sumie.

Czym jest nn.Module?

nn.Module to bazowa klasa PyTorch dla wszystkich komponentów sieci neuronowych. Każda warstwa, funkcja aktywacji, funkcja straty i kompletny model w PyTorch dziedziczą po nn.Module. Klasa ta zapewnia między innymi zarządzanie parametrami, przenoszenie na urządzenie, serializację oraz przełączanie między trybem trenowania i ewaluacji. Dziedzicząc po niej, otrzymuje Pan / otrzymuje Pani całą tę funkcjonalność bez dodatkowej pracy i musi jedynie zdefiniować architekturę oraz przebieg w przód.

import torch.nn as nn

# Inspect what nn.Module gives you
model = nn.Linear(4, 2)
print(type(model))               # <class 'torch.nn.modules.linear.Linear'>
print(isinstance(model, nn.Module))  # True
print(list(model.parameters()))  # weight and bias tensors

Dziedziczenie po nn.Module: __init__ i forward

Utworzenie własnej sieci wymaga zdefiniowania dwóch metod. W __init__ należy wywołać super().__init__() i zdefiniować wszystkie uczone warstwy jako atrybuty. W forward opisuje się przepływ danych przez te warstwy. PyTorch śledzi każdy obiekt nn.Module lub nn.Parameter przypisany do self jako komponent podlegający trenowaniu. Wywołanie modelu jak funkcji (model(x)) automatycznie uruchamia forward i wykonuje wszystkie zarejestrowane hooki.

import torch
import torch.nn as nn

class SimpleNet(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super().__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

model = SimpleNet(4, 16, 3)
print(model)

Warstwy liniowe: nn.Linear

nn.Linear(in_features, out_features) stosuje transformację y = x @ W.T + b, gdzie W jest macierzą wag, a b wektorem biasu. Warstwa automatycznie inicjalizuje wagi za pomocą rozkładu jednostajnego Kaiminga, a biasy za pomocą rozkładu jednostajnego. Jest podstawowym elementem sieci jednokierunkowych; warstwy te nazywa się także warstwami w pełni połączonymi lub gęstymi.

import torch
import torch.nn as nn

layer = nn.Linear(5, 3)  # 5 inputs, 3 outputs

print('Weight shape:', layer.weight.shape)  # (3, 5)
print('Bias shape:',   layer.bias.shape)    # (3,)

# Forward pass with a batch of 8 samples
x = torch.randn(8, 5)
out = layer(x)
print('Output shape:', out.shape)   # (8, 3)

Funkcje aktywacji: ReLU, Sigmoid, Tanh

Funkcje aktywacji wprowadzają nieliniowość, dzięki czemu sieć może uczyć się złożonych wzorców, których nie potrafi reprezentować stos warstw liniowych. ReLU (max(0, x)) jest domyślną funkcją dla warstw ukrytych — działa szybko i ogranicza problem zanikających gradientów. Sigmoid sprowadza wynik do przedziału [0, 1] i jest używana dla wyników klasyfikacji binarnej. Tanh sprowadza wynik do przedziału [-1, 1] i jest często używana w sieciach RNN. Wszystkie te funkcje są dostępne jako moduły w nn.

import torch
import torch.nn as nn

x = torch.tensor([-2.0, -0.5, 0.0, 0.5, 2.0])

print('ReLU:   ', nn.ReLU()(x))
# tensor([0.0, 0.0, 0.0, 0.5, 2.0])

print('Sigmoid:', nn.Sigmoid()(x))
# tensor([0.12, 0.38, 0.50, 0.62, 0.88])

print('Tanh:   ', nn.Tanh()(x))
# tensor([-0.96, -0.46,  0.00,  0.46,  0.96])

Łączenie warstw za pomocą nn.Sequential

nn.Sequential to wygodny kontener, który przekazuje wynik każdego modułu jako dane wejściowe do następnego. Idealnie nadaje się do prostych architektur jednokierunkowych, w których dane przepływają liniowo. W przypadku bardziej złożonych sieci z połączeniami pomijającymi, wieloma wejściami lub rozgałęzionymi ścieżkami należy zastosować pełne podejście oparte na podklasie nn.Module. Sieci Sequential można nadal rozszerzać przez dziedziczenie i używanie Sequential jako podbloku.

import torch
import torch.nn as nn

# Build with nn.Sequential
model = nn.Sequential(
    nn.Linear(10, 64),
    nn.ReLU(),
    nn.Linear(64, 32),
    nn.ReLU(),
    nn.Linear(32, 1)
)

x = torch.randn(16, 10)    # batch of 16
out = model(x)
print(out.shape)            # torch.Size([16, 1])

Weryfikowanie kształtów wyników za pomocą przykładowych danych wejściowych

Jedną z kluczowych technik debugowania podczas budowania sieci jest przepuszczenie przykładowego tensora przez model przed rozpoczęciem trenowania. Pozwala to sprawdzić zgodność wymiarów wszystkich warstw i natychmiast wykryć niezgodności kształtów. Przykładowy tensor ma taki sam kształt jak rzeczywiste dane, ale zawiera losowe wartości — służy jedynie do przejścia ścieżką w przód. Należy zawsze wykonać ten test po zdefiniowaniu nowej architektury.

import torch
import torch.nn as nn

class MLP(nn.Module):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(784, 256),
            nn.ReLU(),
            nn.Linear(256, 128),
            nn.ReLU(),
            nn.Linear(128, 10)
        )
    def forward(self, x):
        return self.net(x)

model = MLP()
dummy = torch.randn(32, 784)   # batch of 32 MNIST images
out = model(dummy)
print(out.shape)                # torch.Size([32, 10]) -- correct!

Wyświetlanie i zliczanie parametrów

Znajomość całkowitej liczby uczonych parametrów modelu pozwala ocenić jego możliwości oraz wymagania dotyczące pamięci. model.parameters() zwraca iterator po wszystkich uczonych tensorach, a model.named_parameters() łączy każdy tensor z jego nazwą w celu ułatwienia analizy. Zwięzłe narzędzie do zliczania parametrów jest jednym z pierwszych narzędzi, które tworzy większość osób pracujących z PyTorch.

import torch
import torch.nn as nn

model = nn.Sequential(
    nn.Linear(784, 256),
    nn.ReLU(),
    nn.Linear(256, 10)
)

total_params = sum(p.numel() for p in model.parameters())
trainable = sum(p.numel() for p in model.parameters()
                if p.requires_grad)

print(f'Total params:     {total_params:,}')   # 203,530
print(f'Trainable params: {trainable:,}')       # 203,530

for name, p in model.named_parameters():
    print(name, p.shape)

Przenoszenie modelu na GPU

Przeniesienie modelu na GPU jest tak proste jak wywołanie model.to(device). Operacja ta przenosi wszystkie parametry i bufory zarejestrowane w module na wskazane urządzenie. Po jej wykonaniu wszystkie obliczenia przebiegu w przód są automatycznie wykonywane na GPU — pod warunkiem że tensory wejściowe również znajdują się na tym samym urządzeniu. Łączenie tensorów z CPU i GPU powoduje błąd wykonania.

import torch
import torch.nn as nn

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

model = nn.Sequential(
    nn.Linear(4, 8),
    nn.ReLU(),
    nn.Linear(8, 2)
).to(device)   # move entire model to device

# Input must be on the same device
x = torch.randn(5, 4).to(device)
out = model(x)
print(out.device)   # cuda:0 (or cpu)

Tryb trenowania a tryb ewaluacji

Niektóre warstwy (Dropout, BatchNorm) zachowują się inaczej podczas trenowania i wnioskowania. Wywołanie model.train() włącza zachowanie stochastyczne (losowy dropout, statystyki partii), a model.eval() przełącza model na deterministyczne zachowanie podczas wnioskowania. Pominięcie wywołania model.eval() przed ewaluacją prowadzi do niespójnych wyników, ponieważ Dropout losowo wyzerowuje aktywacje. Podczas wnioskowania należy zawsze łączyć te wywołania z torch.no_grad(), aby uzyskać maksymalną wydajność.

import torch
import torch.nn as nn

model = nn.Sequential(
    nn.Linear(4, 8),
    nn.Dropout(p=0.5),
    nn.Linear(8, 2)
)

# Training mode: dropout is active
model.train()
x = torch.randn(4, 4)
print(model(x))   # some activations zeroed randomly

# Eval mode: dropout is disabled
model.eval()
with torch.no_grad():
    print(model(x))   # deterministic output

Własna sieć: perceptron wielowarstwowy

Łącząc wszystkie elementy: perceptron wielowarstwowy (MLP) to sieć jednokierunkowa z co najmniej jedną warstwą ukrytą między wejściem a wyjściem. Każda warstwa ukryta stosuje transformację liniową, a następnie nieliniową funkcję aktywacji. Funkcja aktywacji warstwy wyjściowej zależy od zadania — w regresji nie stosuje się funkcji aktywacji, w klasyfikacji wieloklasowej używa się softmax, a w klasyfikacji binarnej sigmoid. Poniższy przykład tworzy trójwarstwowy MLP do klasyfikacji na 10 klas.

import torch
import torch.nn as nn

class MLP(nn.Module):
    def __init__(self, in_dim, hidden_dims, out_dim):
        super().__init__()
        layers = []
        prev = in_dim
        for h in hidden_dims:
            layers.append(nn.Linear(prev, h))
            layers.append(nn.ReLU())
            prev = h
        layers.append(nn.Linear(prev, out_dim))
        self.net = nn.Sequential(*layers)

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

model = MLP(784, [256, 128, 64], 10)
dummy = torch.randn(32, 784)
print(model(dummy).shape)  # torch.Size([32, 10])

Zapisywanie i wczytywanie stanu sieci

Trenowanie sieci neuronowej jest kosztowne, dlatego po jego zakończeniu model należy zapisać. Konwencja PyTorch zakłada zapisywanie wyłącznie obiektu state_dict — słownika tensorów parametrów — zamiast całego obiektu modelu. Pozwala to uniknąć zależności pickle od definicji klasy. Aby odtworzyć model, należy utworzyć nową instancję z taką samą architekturą, a następnie wczytać słownik stanu za pomocą load_state_dict. Po wczytaniu modelu do wnioskowania należy zawsze ustawić model.eval().

import torch
import torch.nn as nn

model = nn.Linear(4, 2)

# Save only parameters (recommended)
torch.save(model.state_dict(), '/tmp/model.pt')

# Restore
new_model = nn.Linear(4, 2)  # same architecture
new_model.load_state_dict(torch.load('/tmp/model.pt'))
new_model.eval()

x = torch.randn(3, 4)
print(new_model(x))   # same output as original model

Szybkie sprawdzenie

Sprawdź swoje zrozumienie zagadnień związanych z uczeniem maszynowym w Pythonie omówionych w tej lekcji.

Podsumowanie lekcji

W tej lekcji dowiedział się Pan / dowiedziała się Pani, że: nn.Module jest klasą bazową wszystkich sieci neuronowych PyTorch; metoda __init__ służy do definiowania warstw, a forward do określania przepływu danych; nn.Sequential zapewnia prosty kontener dla liniowych stosów warstw; natomiast model.train() / model.eval() przełączają zachowanie warstw takich jak Dropout i BatchNorm. Następnie napiszemy kompletną pętlę trenowania obejmującą funkcję straty, optymalizator i wiele epok.

Bezpłatny start

Ucz się Python dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
30
Lekcje
120

Często zadawane pytania

Czy lekcja „Tworzenie sieci jednokierunkowej za pomocą nn.Module” jest bezpłatna?

Tak — pełny tekst „Tworzenie sieci jednokierunkowej za pomocą nn.Module” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Machine Learning Academy, przejdź na CoddyKit PRO. Kurs Machine Learning Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Tworzenie sieci jednokierunkowej za pomocą nn.Module”?

Uczą się Państwo dziedziczyć po nn.Module, układać warstwy Linear i ReLU w __init__, implementować przebieg w przód oraz sprawdzać kształty wyjścia za pomocą przykładowych danych wejściowych. Ćwiczysz Machine Learning Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Machine Learning Academy?

Nie wymagamy żadnego doświadczenia. Machine Learning Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Tworzenie sieci jednokierunkowej za pomocą nn.Module”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Machine Learning Academy?

Tak. Każda lekcja Machine Learning Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Tensory PyTorch: tworzenie, operacje i przenoszenie na GPU
  2. Autograd: automatyczne różniczkowanie na potrzeby propagacji wstecznej
  3. Tworzenie sieci jednokierunkowej za pomocą nn.Module
  4. Pętla trenowania: funkcja straty, optymalizator i epoki
← Powrót do Machine Learning Academy