Dimensionen, Rang, Tensorprodukt – die formale Grundlage
SerieTensoren verstehen
Teil 2 von 8
Im ersten Teil dieser Serie haben wir Tensoren als mehrdimensionale Arrays kennengelernt – Skalare, Vektoren, Matrizen, und dann immer mehr Dimensionen. Das reicht für den praktischen Einstieg in PyTorch oder TensorFlow.
Aber hinter dem Begriff steckt mehr. Mathematiker und Physiker meinen mit “Tensor” etwas Präziseres als “mehrdimensionales Array”. Dieser Teil erklärt, was das ist – und warum der Unterschied manchmal wichtig ist.
Wie viele Fragen braucht man, um eine Zahl zu finden?
Eine einfache Art, den Rang eines Tensors zu verstehen: Wie viele Fragen muss man beantworten, um auf eine einzelne Zahl im Tensor zu zeigen?
Bei einem Skalar – einer einzelnen Zahl – braucht man keine Frage. Die Zahl ist einfach da. Rang 0.
Bei einem Vektor mit zehn Einträgen braucht man eine Frage: “Welche Position?” Rang 1.
Bei einer Matrix braucht man zwei Fragen: “Welche Zeile?” und “Welche Spalte?” Rang 2.
Bei einem 3D-Tensor braucht man drei: “Welcher Block, welche Zeile, welche Spalte?” Rang 3.
import torch
s = torch.tensor(3.14) # 0 Fragen → Rang 0
v = torch.tensor([1.0, 2.0]) # 1 Frage → Rang 1
m = torch.randn(4, 4) # 2 Fragen → Rang 2
t = torch.randn(3, 4, 5) # 3 Fragen → Rang 3
print(s.ndim, v.ndim, m.ndim, t.ndim) # 0 1 2 3 In PyTorch heißt das ndim. In der Mathematik nennt man es Rang, Stufe oder Ordnung – alles dasselbe Konzept.
Rang ist nicht dasselbe wie Größe
Ein häufiges Missverständnis: Rang 2 bedeutet nicht “zwei Einträge”. Es bedeutet: zwei Achsen, egal wie groß.
Eine (2, 1000)-Matrix hat Rang 2 – genauso wie eine (3, 3)-Matrix. Der Rang sagt, wie viele Achsen existieren. Die Form (Shape) sagt, wie groß jede Achse ist.
Ein Tensor der Form (32, 10, 768) hat Rang 3 – und 32 × 10 × 768 = 245.760 Elemente insgesamt. Zwei Tensoren können denselben Rang haben und trotzdem völlig unterschiedlich groß sein.
Wie entsteht ein höherdimensionaler Tensor aus einfacheren?
Stell dir vor, du hast eine Liste von Zutaten und eine Liste von Gerichten. Du willst wissen, wie gut jede Zutat zu jedem Gericht passt – eine Tabelle mit allen Kombinationen.
Genau das macht das Tensorprodukt: Es kombiniert zwei Tensoren so, dass jede Möglichkeit aus dem ersten mit jeder Möglichkeit aus dem zweiten verknüpft wird.
import torch
zutaten = torch.tensor([0.8, 0.3, 0.9]) # 3 Zutaten, Rang 1
gerichte = torch.tensor([0.6, 0.4]) # 2 Gerichte, Rang 1
tabelle = torch.outer(zutaten, gerichte)
# Ergebnis: (3, 2)-Matrix, Rang 2
# [[0.48, 0.32],
# [0.18, 0.12],
# [0.54, 0.36]] Aus zwei Rang-1-Tensoren (Listen) wird ein Rang-2-Tensor (Tabelle). Das Tensorprodukt addiert die Ränge: zwei Rang-1 ergibt Rang 2, Rang-2 plus Rang-2 ergibt Rang 4 – und so weiter.
Das klingt abstrakt, ist aber die formale Grundlage dafür, wie komplexe Datenstrukturen aus einfacheren aufgebaut werden.
Den Rang wieder reduzieren: Kontraktion
Die umgekehrte Operation heißt Kontraktion: Man summiert über eine Achse und verliert dabei eine Dimension.
Das klingt kompliziert, aber jeder kennt ein Beispiel: Matrizenmultiplikation ist eine Kontraktion. Man nimmt eine (3, 4)-Matrix und eine (4, 5)-Matrix, summiert über die gemeinsame Achse der Größe 4, und erhält eine (3, 5)-Matrix.
A = torch.randn(3, 4)
B = torch.randn(4, 5)
C = A @ B # Kontraktion → Rang bleibt 2, Form wird (3, 5) Tensorprodukt und Kontraktion sind die zwei Grundbewegungen in der Tensoralgebra – aufbauen und zusammenfassen. In neuronalen Netzen passiert genau das, Schicht für Schicht – welche Operationen dabei konkret ablaufen, zeigt ein späterer Teil der Serie.
Was ein Tensor wirklich ist – und was ihn von einem Array unterscheidet
Hier kommt der Unterschied, den Mathematiker und Physiker meinen, wenn sie “Tensor” sagen.
Ein Array ist einfach eine Tabelle mit Zahlen. Ein Tensor ist mehr: Es ist ein Objekt, das sich bei einem Wechsel des Koordinatensystems auf eine vorhersagbare, festgelegte Weise verhält.
Das Kompass-Beispiel
Stell dir vor, du beschreibst die Lage eines Ortes: “3 Kilometer nach Osten, 2 Kilometer nach Norden.” Das sind die Koordinaten in einem bestimmten System – mit Norden als Referenz.
Jetzt dreht jemand die Karte um 45 Grad. Die Zahlen ändern sich. “3 Kilometer Ost, 2 Kilometer Nord” wird zu anderen Werten in dem gedrehten System. Aber der Ort selbst hat sich nicht bewegt.
Genau das ist der Kerngedanke: Die Zahlen ändern sich, das beschriebene Objekt bleibt dasselbe. Und die Regel, wie sich die Zahlen beim Drehen ändern, ist nicht beliebig – sie folgt einer festen Formel. Ein Tensor ist ein Objekt, das diese Regel respektiert.
Ein einfaches Array von Zahlen hat diese Eigenschaft nicht. Es ist nur eine Tabelle. Ein Tensor dagegen “weiß”, wie er sich bei Koordinatenwechseln verhalten muss.
Warum das in der Praxis selten auffällt
In ML-Frameworks wie PyTorch arbeitet man fast immer in einem festen Koordinatensystem. Koordinatentransformationen kommen selten vor, und wenn, dann stecken sie versteckt in Schichten wie Batch-Normalisierung oder Attention-Mechanismen.
Trotzdem ist das Konzept nützlich: Es erklärt, warum bestimmte Operationen “erlaubt” sind und andere nicht – und warum Physiker und Mathematiker denselben Begriff für sehr unterschiedliche Dinge verwenden.
Der Ursprung: Physik des 19. Jahrhunderts
Tensoren wurden nicht für Machine Learning erfunden. Sie entstanden, weil Physiker ein konkretes Problem hatten: Naturgesetze sollten unabhängig davon gelten, wie man das Koordinatensystem wählt.
Gregorio Ricci-Curbastro und Tullio Levi-Civita entwickelten Ende des 19. Jahrhunderts eine systematische Sprache dafür – den Ricci-Kalkül. Albert Einstein nutzte genau dieses Werkzeug für die Allgemeine Relativitätstheorie.
Einsteins Feldgleichungen lassen sich in einer einzigen Zeile schreiben:
Gμν = (8πG / c⁴) · Tμν Links steht, wie die Raumzeit gekrümmt ist. Rechts steht, wie Materie und Energie verteilt sind. Beide Seiten sind Rang-2-Tensoren. Diese eine Gleichung enthält alles, was die Gravitation beschreibt – komprimiert in Tensornotation.
Die Einsteinsche Summenkonvention
Aus der Physik stammt eine Schreibkonvention, die direkt in modernem ML-Code auftaucht: Wenn ein Buchstaben-Index zweimal im selben Ausdruck vorkommt, wird automatisch über ihn summiert. Man schreibt die Summe nicht aus – sie ist implizit.
PyTorch und NumPy haben dafür einsum, das genau diese Notation übernimmt. Das j in diesem Beispiel ist so ein doppelter Index – über ihn wird summiert:
import torch
A = torch.randn(3, 4)
B = torch.randn(4, 5)
# 'ij,jk->ik': j kommt zweimal vor → wird summiert (= Matrixmultiplikation)
C = torch.einsum('ij,jk->ik', A, B)
# Skalarprodukt: i kommt zweimal vor → wird summiert
a = torch.randn(3)
b = torch.randn(3)
s = torch.einsum('i,i->', a, b) einsum ist die direkte Brücke zwischen dem Formalismus aus dem 19. Jahrhundert und modernem ML-Code.
Warum das alles nützlich ist
Für den Alltag in PyTorch reicht das Bild aus Teil 1 – mehrdimensionale Arrays mit Formen und Achsen. Die formale Mathematik braucht man dafür nicht.
Aber zwei Situationen, in denen sie hilft:
ML-Paper lesen: Viele Paper aus der Forschung – besonders zu geometrischem Deep Learning, physikbasierten Modellen oder Transformer-Architekturen – verwenden Indexnotation und Kontraktionen. Wer das Grundprinzip kennt, liest sie flüssiger.
Shape-Fehler verstehen: Wer weiß, dass einsum Kontraktionen ausdrückt und Matrizenmultiplikation eine Kontraktion ist, debuggt Shape-Mismatch-Fehler schneller – weil man sieht, welche Achsen “zusammenpassen” müssen.
Der nächste Teil dieser Serie zeigt, wie Tensoren konkret durch ein neuronales Netz fließen – von der Eingabe bis zur Ausgabe, Schicht für Schicht.