Communitygithub.com

pytorch-patterns

PyTorch-Entwicklungsmuster und Best Practices für robuste, effiziente und reproduzierbare Trainingspipelines, Modellarchitekturen und Datenladeprozesse.

Was ist pytorch-patterns?

Diese Skill-Anleitung bietet einen umfassenden Satz an idiomatischen PyTorch-Mustern und Best Practices für die Entwicklung zuverlässiger, effizienter und reproduzierbarer Deep-Learning-Anwendungen. Sie behandelt zentrale Prinzipien wie geräteunabhängigen Code, Reproduzierbarkeit durch Seed-Setzung und explizites Shape-Management. Die Anleitung enthält detaillierte Codebeispiele für Modellarchitekturen (saubere nn.Module-Struktur, Gewichtsinitialisierung), Trainings- und Validierungsschleifen (mit Mixed-Precision-Training, Gradienten-Clipping und Gradienten-Checkpointing) sowie effiziente Datenpipelines (benutzerdefinierte Datasets, optimierte DataLoader mit pin_memory, persistant_workers und benutzerdefinierten Collate-Funktionen). Außerdem werden Checkpointing-Strategien, Performance-Optimierungen (torch.compile, AMP mit GradScaler) und häufige Anti-Patterns behandelt. Die Skill ist für Entwickler gedacht, die PyTorch-Modelle schreiben oder überprüfen, Trainingsschleifen debuggen oder die GPU-Auslastung optimieren möchten.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/pytorch-patterns

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

PyTorch-Entwicklungsmuster (PyTorch Development Patterns)

Idiomatische PyTorch-Muster und Best Practices für die Entwicklung robuster, effizienter und reproduzierbarer Deep-Learning-Anwendungen.

Wann aktivieren

  • Schreiben neuer PyTorch-Modelle oder Trainingsskripte
  • Überprüfen von Deep-Learning-Code
  • Debuggen von Trainingsschleifen oder Datenpipelines
  • Optimieren der GPU-Speichernutzung oder Trainingsgeschwindigkeit
  • Einrichten reproduzierbarer Experimente

Kernprinzipien

1. Geräteunabhängiger Code (Device-Agnostic Code)

Schreiben Sie stets Code, der sowohl auf CPU als auch auf GPU funktioniert, ohne Geräte fest zu kodieren.

# Gut: Geräteunabhängig
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = MyModel().to(device)
data = data.to(device)

# Schlecht: Fest kodiertes Gerät
model = MyModel().cuda()  # Absturz, wenn keine GPU vorhanden
data = data.cuda()

2. Reproduzierbarkeit zuerst

Setzen Sie alle Zufalls-Seeds für reproduzierbare Ergebnisse.

# Gut: Vollständige Reproduzierbarkeitseinrichtung
def set_seed(seed: int = 42) -> None:
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    np.random.seed(seed)
    random.seed(seed)
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False

# Schlecht: Keine Seed-Kontrolle
model = MyModel()  # Unterschiedliche Gewichte bei jedem Durchlauf

3. Explizites Shape-Management

Dokumentieren und überprüfen Sie stets die Tensor-Shapes.

# Gut: Shape-annotierter Forward-Durchlauf
def forward(self, x: torch.Tensor) -> torch.Tensor:
    # x: (batch_size, channels, height, width)
    x = self.conv1(x)    # -> (batch_size, 32, H, W)
    x = self.pool(x)     # -> (batch_size, 32, H//2, W//2)
    x = x.view(x.size(0), -1)  # -> (batch_size, 32*H//2*W//2)
    return self.fc(x)    # -> (batch_size, num_classes)

# Schlecht: Keine Shape-Verfolgung
def forward(self, x):
    x = self.conv1(x)
    x = self.pool(x)
    x = x.view(x.size(0), -1)  # Welche Größe hat das?
    return self.fc(x)           # Wird das überhaupt funktionieren?

Muster für Modellarchitekturen

Saubere nn.Module-Struktur

# Gut: Gut organisierter Modul
class ImageClassifier(nn.Module):
    def __init__(self, num_classes: int, dropout: float = 0.5) -> None:
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=3, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2),
        )
        self.classifier = nn.Sequential(
            nn.Dropout(dropout),
            nn.Linear(64 * 16 * 16, num_classes),
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x = self.features(x)
        x = x.view(x.size(0), -1)
        return self.classifier(x)

# Schlecht: Alles in forward
class ImageClassifier(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, x):
        x = F.conv2d(x, weight=self.make_weight())  # Erzeugt Gewichte bei jedem Aufruf!
        return x

Korrekte Gewichtsinitialisierung

# Gut: Explizite Initialisierung
def _init_weights(self, module: nn.Module) -> None:
    if isinstance(module, nn.Linear):
        nn.init.kaiming_normal_(module.weight, mode="fan_out", nonlinearity="relu")
        if module.bias is not None:
            nn.init.zeros_(module.bias)
    elif isinstance(module, nn.Conv2d):
        nn.init.kaiming_normal_(module.weight, mode="fan_out", nonlinearity="relu")
    elif isinstance(module, nn.BatchNorm2d):
        nn.init.ones_(module.weight)
        nn.init.zeros_(module.bias)

model = MyModel()
model.apply(model._init_weights)

Muster für Trainingsschleifen

Standard-Trainingsschleife

# Gut: Vollständige Trainingsschleife mit Best Practices
def train_one_epoch(
    model: nn.Module,
    dataloader: DataLoader,
    optimizer: torch.optim.Optimizer,
    criterion: nn.Module,
    device: torch.device,
    scaler: torch.amp.GradScaler | None = None,
) -> float:
    model.train()  # Immer Trainingsmodus setzen
    total_loss = 0.0

    for batch_idx, (data, target) in enumerate(dataloader):
        data, target = data.to(device), target.to(device)

        optimizer.zero_grad(set_to_none=True)  # Effizienter als zero_grad()

        # Mixed-Precision-Training
        with torch.amp.autocast("cuda", enabled=scaler is not None):
            output = model(data)
            loss = criterion(output, target)

        if scaler is not None:
            scaler.scale(loss).backward()
            scaler.unscale_(optimizer)
            torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
            scaler.step(optimizer)
            scaler.update()
        else:
            loss.backward()
            torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
            optimizer.step()

        total_loss += loss.item()

    return total_loss / len(dataloader)

Validierungsschleife

# Gut: Korrekte Evaluation
@torch.no_grad()  # Effizienter als das Einwickeln in einen torch.no_grad()-Block
def evaluate(
    model: nn.Module,
    dataloader: DataLoader,
    criterion: nn.Module,
    device: torch.device,
) -> tuple[float, float]:
    model.eval()  # Immer Evaluierungsmodus setzen – deaktiviert Dropout, verwendet laufende BN-Stats
    total_loss = 0.0
    correct = 0
    total = 0

    for data, target in dataloader:
        data, target = data.to(device), target.to(device)
        output = model(data)
        total_loss += criterion(output, target).item()
        correct += (output.argmax(1) == target).sum().item()
        total += target.size(0)

    return total_loss / len(dataloader), correct / total

Muster für Datenpipelines

Benutzerdefiniertes Dataset

# Gut: Sauberes Dataset mit Typannotationen
class ImageDataset(Dataset):
    def __init__(
        self,
        image_dir: str,
        labels: dict[str, int],
        transform: transforms.Compose | None = None,
    ) -> None:
        self.image_paths = list(Path(image_dir).glob("*.jpg"))
        self.labels = labels
        self.transform = transform

    def __len__(self) -> int:
        return len(self.image_paths)

    def __getitem__(self, idx: int) -> tuple[torch.Tensor, int]:
        img = Image.open(self.image_paths[idx]).convert("RGB")
        label = self.labels[self.image_paths[idx].stem]

        if self.transform:
            img = self.transform(img)

        return img, label

Effiziente DataLoader-Konfiguration

# Gut: Optimierter DataLoader
dataloader = DataLoader(
    dataset,
    batch_size=32,
    shuffle=True,            # Mischen für Training
    num_workers=4,           # Paralleles Datenladen
    pin_memory=True,         # Schnellere CPU->GPU-Übertragung
    persistent_workers=True, # Arbeiter am Leben halten zwischen Epochen
    drop_last=True,          # Konsistente Batch-Größen für BatchNorm
)

# Schlecht: Langsame Standardwerte
dataloader = DataLoader(dataset, batch_size=32)  # num_workers=0, kein pin_memory

Benutzerdefinierte Collate für Daten mit variabler Länge

# Gut: Sequenzen in collate_fn auffüllen
def collate_fn(batch: list[tuple[torch.Tensor, int]]) -> tuple[torch.Tensor, torch.Tensor]:
    sequences, labels = zip(*batch)
    # Auf maximale Länge im Batch auffüllen
    padded = nn.utils.rnn.pad_sequence(sequences, batch_first=True, padding_value=0)
    return padded, torch.tensor(labels)

dataloader = DataLoader(dataset, batch_size=32, collate_fn=collate_fn)

Muster für Checkpointing

Checkpoints speichern und laden

# Gut: Vollständiger Checkpoint mit allen Trainingszuständen
def save_checkpoint(
    model: nn.Module,
    optimizer: torch.optim.Optimizer,
    epoch: int,
    loss: float,
    path: str,
) -> None:
    torch.save({
        "epoch": epoch,
        "model_state_dict": model.state_dict(),
        "optimizer_state_dict": optimizer.state_dict(),
        "loss": loss,
    }, path)

def load_checkpoint(
    path: str,
    model: nn.Module,
    optimizer: torch.optim.Optimizer | None = None,
) -> dict:
    checkpoint = torch.load(path, map_location="cpu", weights_only=True)
    model.load_state_dict(checkpoint["model_state_dict"])
    if optimizer:
        optimizer.load_state_dict(checkpoint["optimizer_state_dict"])
    return checkpoint

# Schlecht: Nur Modellgewichte speichern (Training kann nicht fortgesetzt werden)
torch.save(model.state_dict(), "model.pt")

Leistungsoptimierung

Mixed-Precision-Training

# Gut: AMP mit GradScaler
scaler = torch.amp.GradScaler("cuda")
for data, target in dataloader:
    with torch.amp.autocast("cuda"):
        output = model(data)
        loss = criterion(output, target)
    scaler.scale(loss).backward()
    scaler.step(optimizer)
    scaler.update()
    optimizer.zero_grad(set_to_none=True)

Gradienten-Checkpointing für große Modelle

# Gut: Rechenleistung gegen Speicher tauschen
from torch.utils.checkpoint import checkpoint

class LargeModel(nn.Module):
    def forward(self, x: torch.Tensor) -> torch.Tensor:
        # Aktivierungen während des Rückwärtsdurchlaufs neu berechnen, um Speicher zu sparen
        x = checkpoint(self.block1, x, use_reentrant=False)
        x = checkpoint(self.block2, x, use_reentrant=False)
        return self.head(x)

torch.compile für Geschwindigkeit

# Gut: Modell für schnellere Ausführung kompilieren (PyTorch 2.0+)
model = MyModel().to(device)
model = torch.compile(model, mode="reduce-overhead")

# Modi: "default" (sicher), "reduce-overhead" (schneller), "max-autotune" (am schnellsten)

Kurzreferenz: PyTorch-Idiome

IdiomBeschreibung
model.train() / model.eval()Immer den Modus vor Training/Evaluation setzen
torch.no_grad()Gradienten für Inferenz deaktivieren
optimizer.zero_grad(set_to_none=True)Effizienteres Gradienten-Löschen
.to(device)Geräteunabhängige Platzierung von Tensoren/Modellen
torch.amp.autocastMixed-Precision für 2x Geschwindigkeit
pin_memory=TrueSchnellere CPU→GPU-Datenübertragung
torch.compileJIT-Kompilierung für Geschwindigkeit (2.0+)
weights_only=TrueSicheres Modellladen
torch.manual_seedReproduzierbare Experimente
gradient_checkpointingRechenleistung gegen Speicher tauschen

Anti-Patterns, die vermieden werden sollten

# Schlecht: Vergessen von model.eval() während der Validierung
model.train()
with torch.no_grad():
    output = model(val_data)  # Dropout noch aktiv! BatchNorm verwendet Batch-Stats!

# Gut: Immer Evaluierungsmodus setzen
model.eval()
with torch.no_grad():
    output = model(val_data)

# Schlecht: In-Place-Operationen, die Autograd unterbrechen
x = F.relu(x, inplace=True)  # Kann die Gradientenberechnung unterbrechen
x += residual                  # In-Place-Add unterbricht den Autograd-Graphen

# Gut: Out-of-Place-Operationen
x = F.relu(x)
x = x + residual

# Schlecht: Daten wiederholt innerhalb der Trainingsschleife auf GPU verschieben
for data, target in dataloader:
    model = model.cuda()  # Verschiebt das Modell bei JEDER Iteration!

# Gut: Modell einmal vor der Schleife verschieben
model = model.to(device)
for data, target in dataloader:
    data, target = data.to(device), target.to(device)

# Schlecht: Verwendung von .item() vor backward
loss = criterion(output, target).item()  # Trennt vom Graphen!
loss.backward()  # Fehler: Kann nicht durch .item() zurückpropagieren

# Gut: .item() nur für Logging verwenden
loss = criterion(output, target)
loss.backward()
print(f"Loss: {loss.item():.4f}")  # .item() nach backward ist in Ordnung

# Schlecht: torch.save nicht korrekt verwenden
torch.save(model, "model.pt")  # Speichert das gesamte Modell (zerbrechlich, nicht portierbar)

# Gut: state_dict speichern
torch.save(model.state_dict(), "model.pt")

Denken Sie daran: PyTorch-Code sollte geräteunabhängig, reproduzierbar und speicherbewusst sein. Im Zweifelsfall mit torch.profiler profilieren und den GPU-Speicher mit torch.cuda.memory_summary() überprüfen.

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Verwandte Skills