Broadcasting lets NumPy combine arrays of different shapes element-wise — without copying data or writing a loop. The smaller array is virtually stretched to fit the larger one, so a + b just works even when a and b aren't the same shape.
Where you meet it
- Adding a bias vector to every row of a batch in a neural net.
- Normalizing data: subtract the per-column mean, divide by the per-column std.
- Scaling a whole image by a 3-element RGB vector, or an array by a scalar.
- Building a grid or table from two 1-D vectors (the outer-sum trick).
What it does
When you apply an element-wise operation to two arrays whose shapes differ, NumPy doesn't raise an error straight away. Instead it checks whether the shapes are compatible under a fixed set of rules and, if so, treats the smaller array as if it had been repeated to match — then runs the operation cell by cell.
A size-1 axis is an invitation to stretch — which is why two tiny arrays can quietly explode into a giant one.
How it works
Line the two shapes up from the right (trailing dimensions first). If one shape is shorter, pad it on the left with 1s. Now compare each dimension pair:
- If the two sizes are equal → fine.
- If one of them is 1 → that axis is virtually stretched to the other size. No data is actually copied; NumPy just reuses the same value.
- Otherwise →
ValueError.
One example. A column (3, 1) plus a row (1, 4):
a.shape = (3, 1) # a column
b.shape = (1, 4) # a row
3 1
1 4
align right → 3 4 # each pair: equal, or one is 1
result = (3, 4)
a + b # a full 3x4 grid — every column entry meets every row entry
The size-1 axes are the ones that stretch: a's columns fan out to 4, b's rows fan out to 3. Same idea for higher rank — e.g. (8,1,6,1) + (7,1,5) → (8,7,6,5).
Watch out
- Incompatible shapes throw.
(2,3) + (2,)aligns to3vs2on the right — neither equal nor 1 →ValueError. - Accidental broadcasting is silent.
(3,) + (3,1)doesn't give(3,)— it gives a full(3,3). Shapes that "feel" the same can produce a matrix. - Memory blows up fast. The result is fully materialized:
(10000,1) + (1,10000)is a 100-million-cell array, even though the inputs are tiny. - Shape your axes on purpose. Use
reshapeorarr[:, np.newaxis]to turn a vector into a column (or row) so it broadcasts the way you intend, not by accident.
Go deeper
Broadcasting lässt NumPy Arrays unterschiedlicher Form elementweise kombinieren — ohne Daten zu kopieren und ohne Schleife. Das kleinere Array wird virtuell gestreckt, bis es passt, sodass a + b auch dann funktioniert, wenn a und b nicht dieselbe Shape haben.
Wo es vorkommt
- Einen Bias-Vektor auf jede Zeile eines Batches im neuronalen Netz addieren.
- Daten normieren: spaltenweise den Mittelwert abziehen, durch die Standardabweichung teilen.
- Ein ganzes Bild mit einem 3-elementigen RGB-Vektor skalieren oder ein Array mit einem Skalar.
- Aus zwei 1-D-Vektoren ein Gitter oder eine Tabelle bauen (der Outer-Sum-Trick).
Was es tut
Wendest du eine elementweise Operation auf zwei Arrays mit verschiedenen Shapes an, wirft NumPy nicht sofort einen Fehler. Stattdessen prüft es nach festen Regeln, ob die Shapes kompatibel sind, und behandelt das kleinere Array dann so, als wäre es passend wiederholt worden — danach läuft die Operation Zelle für Zelle.
Eine Größe-1-Achse ist eine Einladung zum Strecken — darum können zwei winzige Arrays lautlos zu einem riesigen werden.
Wie es funktioniert
Richte die beiden Shapes von rechts aus (hintere Dimensionen zuerst). Ist eine Shape kürzer, fülle sie links mit 1en auf. Vergleiche nun jedes Dimensionspaar:
- Sind beide Größen gleich → passt.
- Ist eine davon 1 → diese Achse wird virtuell auf die andere Größe gestreckt. Es werden keine Daten kopiert; NumPy nutzt denselben Wert mehrfach.
- Sonst →
ValueError.
Ein Beispiel. Eine Spalte (3, 1) plus eine Zeile (1, 4):
a.shape = (3, 1) # eine Spalte
b.shape = (1, 4) # eine Zeile
3 1
1 4
rechts aus. → 3 4 # jedes Paar: gleich, oder eine ist 1
Ergebnis = (3, 4)
a + b # ein volles 3x4-Gitter — jeder Spaltenwert trifft jeden Zeilenwert
Gestreckt werden die Größe-1-Achsen: as Spalten fächern auf 4 auf, bs Zeilen auf 3. Dasselbe Prinzip auch bei höherem Rang — z.B. (8,1,6,1) + (7,1,5) → (8,7,6,5).
Worauf achten
- Unpassende Shapes werfen.
(2,3) + (2,)richtet rechts3gegen2aus — weder gleich noch 1 →ValueError. - Ungewolltes Broadcasting passiert lautlos.
(3,) + (3,1)gibt nicht(3,), sondern ein volles(3,3). Shapes, die sich "gleich anfühlen", erzeugen eine Matrix. - Der Speicher explodiert schnell. Das Ergebnis wird voll materialisiert:
(10000,1) + (1,10000)ist ein Array mit 100 Millionen Zellen, obwohl die Eingaben winzig sind. - Forme deine Achsen bewusst. Mit
reshapeoderarr[:, np.newaxis]machst du aus einem Vektor eine Spalte (oder Zeile), damit er so broadcastet, wie du es willst — nicht zufällig.