Benutzer-Werkzeuge

Webseiten-Werkzeuge


torch

Torch ist eine Bibliothek zum Erstellen und Trainieren von neuronalen Netzwerken.

Arten von Modellen

Sequential

Das Sequential-Modell ist eine einfache Möglichkeit, sequenzielle Modelle in PyTorch zu definieren. Es erlaubt uns, eine sequentielle Kette von Schichten zu erstellen, in der die Ausgabe einer Schicht als Eingabe für die nächste Schicht verwendet wird.

import torch
import torch.nn as nn
 
model = nn.Sequential(
    nn.Linear(784, 256),
    nn.ReLU(),
    nn.Linear(256, 10),
    nn.Softmax(dim=1)
)

In diesem Beispiel wird ein Sequential-Modell mit zwei linearen Schichten, einer ReLU-Aktivierungsfunktion und einer Softmax-Aktivierungsfunktion erstellt. Die Eingabe des Modells hat eine Größe von 784, und die Ausgabe hat eine Größe von 10.

Module

Das Module-Modell ist eine flexiblere Art, Modelle in PyTorch zu definieren. Es ermöglicht uns, eigene Schichten und komplexe Modelle zu erstellen, indem wir die nn.Module-Klasse erweitern.

import torch
import torch.nn as nn
 
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.fc1 = nn.Linear(784, 256)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(256, 10)
        self.softmax = nn.Softmax(dim=1)
 
    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        x = self.softmax(x)
        return x
 
model = MyModel()

In diesem Beispiel wird ein Module-Modell erstellt, das den gleichen Aufbau wie das Sequential-Modell hat. Die Schichten werden jedoch als Attribute der Modellklasse definiert, und die Vorwärtsfunktion wird durch die Methode forward festgelegt. Dadurch haben wir mehr Flexibilität bei der Gestaltung und Steuerung des Modells.

Functional

Das Functional-Modell ist eine weitere Möglichkeit, Modelle in PyTorch zu definieren. Es basiert auf der Verwendung von Funktionen aus dem torch.nn.functional-Modul, anstatt Schichtenobjekte zu erstellen.

import torch
import torch.nn.functional as F
 
def my_model(x):
    x = F.linear(x, 784, 256)
    x = F.relu(x)
    x = F.linear(x, 256, 10)
    x = F.softmax(x, dim=1)
    return x
 
input = torch.randn(1, 784)
output = my_model(input)

In diesem Beispiel wird das Modell als eine Funktion definiert, die die Funktionen aus dem torch.nn.functional-Modul verwendet. Das Functional-Modell ist nützlich, wenn Sie ein einfaches Modell ohne interne Zustände oder trainierbare Parameter erstellen möchten.

Convolutional

Convolutional Neural Networks sind besonders gut geeignet für die Verarbeitung von Bildern. Sie verwenden spezielle Schichten wie Convolutional Layers und Pooling Layers, um die räumliche Struktur der Eingabedaten zu berücksichtigen.

import torch
import torch.nn as nn
 
class MyCNN(nn.Module):
    def __init__(self):
        super(MyCNN, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1)
        self.relu = nn.ReLU()
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
        self.fc = nn.Linear(16 * 14 * 14, 10)
 
    def forward(self, x):
        x = self.conv1(x)
        x = self.relu(x)
        x = self.pool(x)
        x = x.view(-1, 16 * 14 * 14)
        x = self.fc(x)
        return x
 
model = MyCNN()

In diesem Beispiel wird ein CNN-Modell erstellt, das eine Convolutional Layer, eine ReLU-Aktivierungsfunktion, eine Max-Pooling-Layer und eine Fully Connected Layer enthält. Das Modell wird für die Klassifikation von Bildern verwendet.

Recurrent

Recurrent Neural Networks sind gut geeignet für die Verarbeitung von sequenziellen Daten wie Texten oder Zeitreihen. Sie haben die Fähigkeit, Informationen über vergangene Zustände beizubehalten.

import torch
import torch.nn as nn
 
class MyRNN(nn.Module):
    def __init__(self):
        super(MyRNN, self).__init__()
        self.rnn = nn.RNN(input_size=100, hidden_size=128, num_layers=2, batch_first=True)
        self.fc = nn.Linear(128, 10)
 
    def forward(self, x):
        _, h = self.rnn(x)
        x = self.fc(h[-1])
        return x
 
model = MyRNN()

In diesem Beispiel wird ein RNN-Modell erstellt, das aus einer RNN-Schicht und einer Fully Connected Layer besteht. Das Modell nimmt Eingaben mit einer Sequenzlänge von 100 und gibt eine Ausgabe der Größe 10 zurück.

Transformer

Transformer-Modelle haben in den letzten Jahren an Beliebtheit gewonnen und sind besonders gut für die Verarbeitung von natürlicher Sprache geeignet. Sie verwenden Aufmerksamkeitsmechanismen, um die Beziehungen zwischen den Elementen einer Sequenz zu modellieren.

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn import TransformerEncoder, TransformerEncoderLayer
 
class MyTransformer(nn.Module):
    def __init__(self):
        super(MyTransformer, self).__init__()
        self.embedding = nn.Embedding(10000, 256)
        self.transformer_layer = TransformerEncoderLayer(256, 8)
        self.transformer = TransformerEncoder(self.transformer_layer, num_layers=4)
        self.fc = nn.Linear(256, 10)
 
    def forward(self, x):
        x = self.embedding(x)
        x = x.permute(1, 0, 2)
        x = self.transformer(x)
        x = x.mean(dim=0)
        x = self.fc(x)
        return x
 
model = MyTransformer()

In diesem Beispiel wird ein Transformer-Modell erstellt, das eine Embedding-Schicht, einen TransformerEncoder und eine Fully Connected Layer enthält. Das Modell nimmt Sequenzeingaben, z.B. Token-IDs, und gibt eine Ausgabe der Größe 10 zurück.

Pattern Recognition Example

# Pattern Recognition
 
import torch
import torch.nn as nn
import torch.optim as optim
 
# Daten vorbereiten (Beispiel)
sequences = [
    [1,0,1,1,0],
    [0,1,1,0,0],
    [0,1,0,0,0],
    [1,0,1,0,1],
    [1,0,0,0,1],
    [0,1,0,1,0],
    [1,1,0,1,1],
    [0,0,1,0,0]
]
labels = [1,1,0,1,0,0,0,1]  # Beispieldaten fur die Musterklassifizierung
 
# Hyperparameter
input_size = 1
hidden_size = 5*5
output_size = 2
num_layers = 3
num_epochs = 100
learning_rate = 0.1
 
# Daten in Tensoren umwandeln
input_sequences = torch.tensor(sequences, dtype=torch.float32).unsqueeze(-1)
target_labels = torch.tensor(labels, dtype=torch.long)
 
# Modell definieren
class RNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size, num_layers):
        super(RNN, self).__init__()
        self.hidden_size = hidden_size
        self.rnn = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)
 
    def forward(self, x):
        h0 = torch.zeros(num_layers, x.size(0), self.hidden_size).to(x.device)
        c0 = torch.zeros(num_layers, x.size(0), self.hidden_size).to(x.device)
        out, _ = self.rnn(x, (h0, c0))
        out = self.fc(out[:, -1, :])
        return out
 
model = RNN(input_size, hidden_size, output_size, num_layers)
 
# Verlustfunktion und Optimierungsalgorithmus definieren
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
 
# Modell trainieren
for epoch in range(num_epochs):
    optimizer.zero_grad()
    outputs = model(input_sequences)
    loss = criterion(outputs, target_labels)
    loss.backward()
    optimizer.step()
    print(f'Epoch: {epoch+1}/{num_epochs}, Loss: {loss.item()}')
 
# Modell evaluieren
with torch.no_grad():
    test_input = torch.tensor([[1,0,0,1,1]], dtype=torch.float32).unsqueeze(-1)
    predicted = model(test_input)
    _, predicted_labels = torch.max(predicted.data, 1)
    print(f'Predicted Label: {predicted_labels.item()} {predicted.data}')
 
 
'''
torch.save(model.state_dict(), "test.pt")
model.load_state_dict(torch.load("test.pt"))
'''

Bigram Model

Erweitertes Bigram Model

import torch
import torch.nn as nn
from torch.nn import functional as F
 
# hyperparameters
batch_size = 16 # how many independent sequences will we process in parallel?
block_size = 32 # what is the maximum context length for predictions?
max_iters = 15000
eval_interval = 1000
learning_rate = 1e-3
device = 'cuda' if torch.cuda.is_available() else 'cpu'
eval_iters = 200
n_embd = 64
n_head = 4
n_layer = 4
dropout = 0.0
# ------------
 
torch.manual_seed(1337)
 
!wget https://raw.githubusercontent.com/karpathy/char-rnn/master/data/tinyshakespeare/input.txt
with open('input.txt', 'r', encoding='utf-8') as f:
    text = f.read()
 
# here are all the unique characters that occur in this text
chars = sorted(list(set(text)))
vocab_size = len(chars)
# create a mapping from characters to integers
stoi = { ch:i for i,ch in enumerate(chars) }
itos = { i:ch for i,ch in enumerate(chars) }
encode = lambda s: [stoi[c] for c in s] # encoder: take a string, output a list of integers
decode = lambda l: ''.join([itos[i] for i in l]) # decoder: take a list of integers, output a string
 
# Train and test splits
data = torch.tensor(encode(text), dtype=torch.long)
n = int(0.9*len(data)) # first 90% will be train, rest val
train_data = data[:n]
val_data = data[n:]
 
# data loading
def get_batch(split):
    # generate a small batch of data of inputs x and targets y
    data = train_data if split == 'train' else val_data
    ix = torch.randint(len(data) - block_size, (batch_size,))
    x = torch.stack([data[i:i+block_size] for i in ix])
    y = torch.stack([data[i+1:i+block_size+1] for i in ix])
    x, y = x.to(device), y.to(device)
    return x, y
 
@torch.no_grad()
def estimate_loss():
    out = {}
    model.eval()
    for split in ['train', 'val']:
        losses = torch.zeros(eval_iters)
        for k in range(eval_iters):
            X, Y = get_batch(split)
            logits, loss = model(X, Y)
            losses[k] = loss.item()
        out[split] = losses.mean()
    model.train()
    return out
 
class Head(nn.Module):
    """ one head of self-attention """
 
    def __init__(self, head_size):
        super().__init__()
        self.key = nn.Linear(n_embd, head_size, bias=False)
        self.query = nn.Linear(n_embd, head_size, bias=False)
        self.value = nn.Linear(n_embd, head_size, bias=False)
        self.register_buffer('tril', torch.tril(torch.ones(block_size, block_size)))
 
        self.dropout = nn.Dropout(dropout)
 
    def forward(self, x):
        B,T,C = x.shape
        k = self.key(x)   # (B,T,C)
        q = self.query(x) # (B,T,C)
        # compute attention scores ("affinities")
        wei = q @ k.transpose(-2,-1) * C**-0.5 # (B, T, C) @ (B, C, T) -> (B, T, T)
        wei = wei.masked_fill(self.tril[:T, :T] == 0, float('-inf')) # (B, T, T)
        wei = F.softmax(wei, dim=-1) # (B, T, T)
        wei = self.dropout(wei)
        # perform the weighted aggregation of the values
        v = self.value(x) # (B,T,C)
        out = wei @ v # (B, T, T) @ (B, T, C) -> (B, T, C)
        return out
 
class MultiHeadAttention(nn.Module):
    """ multiple heads of self-attention in parallel """
 
    def __init__(self, num_heads, head_size):
        super().__init__()
        self.heads = nn.ModuleList([Head(head_size) for _ in range(num_heads)])
        self.proj = nn.Linear(n_embd, n_embd)
        self.dropout = nn.Dropout(dropout)
 
    def forward(self, x):
        out = torch.cat([h(x) for h in self.heads], dim=-1)
        out = self.dropout(self.proj(out))
        return out
 
class FeedFoward(nn.Module):
    """ a simple linear layer followed by a non-linearity """
 
    def __init__(self, n_embd):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(n_embd, 4 * n_embd),
            nn.ReLU(),
            nn.Linear(4 * n_embd, n_embd),
            nn.Dropout(dropout),
        )
 
    def forward(self, x):
        return self.net(x)
 
class Block(nn.Module):
    """ Transformer block: communication followed by computation """
 
    def __init__(self, n_embd, n_head):
        # n_embd: embedding dimension, n_head: the number of heads we'd like
        super().__init__()
        head_size = n_embd // n_head
        self.sa = MultiHeadAttention(n_head, head_size)
        self.ffwd = FeedFoward(n_embd)
        self.ln1 = nn.LayerNorm(n_embd)
        self.ln2 = nn.LayerNorm(n_embd)
 
    def forward(self, x):
        x = x + self.sa(self.ln1(x))
        x = x + self.ffwd(self.ln2(x))
        return x
 
# super simple bigram model
class BigramLanguageModel(nn.Module):
 
    def __init__(self):
        super().__init__()
        # each token directly reads off the logits for the next token from a lookup table
        self.token_embedding_table = nn.Embedding(vocab_size, n_embd)
        self.position_embedding_table = nn.Embedding(block_size, n_embd)
        self.blocks = nn.Sequential(*[Block(n_embd, n_head=n_head) for _ in range(n_layer)])
        self.ln_f = nn.LayerNorm(n_embd) # final layer norm
        self.lm_head = nn.Linear(n_embd, vocab_size)
 
    def forward(self, idx, targets=None):
        B, T = idx.shape
 
        # idx and targets are both (B,T) tensor of integers
        tok_emb = self.token_embedding_table(idx) # (B,T,C)
        pos_emb = self.position_embedding_table(torch.arange(T, device=device)) # (T,C)
        x = tok_emb + pos_emb # (B,T,C)
        x = self.blocks(x) # (B,T,C)
        x = self.ln_f(x) # (B,T,C)
        logits = self.lm_head(x) # (B,T,vocab_size)
 
        if targets is None:
            loss = None
        else:
            B, T, C = logits.shape
            logits = logits.view(B*T, C)
            targets = targets.view(B*T)
            loss = F.cross_entropy(logits, targets)
 
        return logits, loss
 
    def generate(self, idx, max_new_tokens):
        # idx is (B, T) array of indices in the current context
        for _ in range(max_new_tokens):
            # crop idx to the last block_size tokens
            idx_cond = idx[:, -block_size:]
            # get the predictions
            logits, loss = self(idx_cond)
            # focus only on the last time step
            logits = logits[:, -1, :] # becomes (B, C)
            # apply softmax to get probabilities
            probs = F.softmax(logits, dim=-1) # (B, C)
            # sample from the distribution
            idx_next = torch.multinomial(probs, num_samples=1) # (B, 1)
            # append sampled index to the running sequence
            idx = torch.cat((idx, idx_next), dim=1) # (B, T+1)
        return idx
 
 
model = BigramLanguageModel()
m = model.to(device)
# print the number of parameters in the model
print(sum(p.numel() for p in m.parameters())/1e6, 'M parameters')
 
# create a PyTorch optimizer
optimizer = torch.optim.AdamW(model.parameters(), lr=learning_rate)
 
for iter in range(max_iters):
 
    # every once in a while evaluate the loss on train and val sets
    if iter % eval_interval == 0 or iter == max_iters - 1:
        losses = estimate_loss()
        print(f"step {iter}: train loss {losses['train']:.4f}, val loss {losses['val']:.4f}")
 
    # sample a batch of data
    xb, yb = get_batch('train')
 
    # evaluate the loss
    logits, loss = model(xb, yb)
    optimizer.zero_grad(set_to_none=True)
    loss.backward()
    optimizer.step()
 
 
# random
#context = torch.zeros((1, 1), dtype=torch.long, device=device)
#print(decode(m.generate(context, max_new_tokens=100)[0].tolist()))
 
# prompt
#context = torch.tensor([encode("Who is the king?")], dtype=torch.long, device=device)
#print(decode(m.generate(context, max_new_tokens=100)[0].tolist()))
 
# completion
def complete(prompt, max_new_tokens=200, temperature=1.0):
    idx = torch.tensor([encode(prompt)], dtype=torch.long, device=device)
    with torch.no_grad():
        for _ in range(max_new_tokens):
            idx_cond = idx[:, -block_size:]
            logits, _ = m(idx_cond)
            logits = logits[:, -1, :] / temperature
            probs = F.softmax(logits, dim=-1)
            idx_next = torch.multinomial(probs, num_samples=1)
            idx = torch.cat((idx, idx_next), dim=1)
 
    full = decode(idx[0].tolist())
    return full # full[len(prompt):] 
print(complete("To be, or not to be: ", max_new_tokens=100, temperature=0.8))
torch.txt · Zuletzt geändert: 2025/11/28 09:52 von jango