6.10. Broadcasting¶
När en binär operator får två arrayer vars former inte matchar exakt ger numpy inte upphov till ett fel – den broadcastar. Broadcasting är en liten uppsättning regler som avgör om två former är kompatibla och, om de är det, hur den mindre virtuellt sträcks ut för att matcha den större.
6.10.1. Reglerna¶
När de två operanderna har formerna A och B arbetar numpy igenom dem i två steg.
Matcha rangerna. Om en operand har färre axlar än den andra fyller
numpyvirtuellt på framsidan av dess form med axlar av storlek 1 tills båda formerna har samma antal axlar. En 1D-operand med form(3,)parad med en 2D-operand med form(2, 3)blir(1, 3)mot(2, 3).Kontrollera varje axel. Genom att gå igenom de nu lika långa formerna axel för axel måste varje par av storlekar uppfylla ett av två villkor: storlekarna är lika, eller en av dem är 1. En axel av storlek 1 sträcks virtuellt ut till den andra sidans storlek för operationen. Paret
(1, 3)mot(2, 3)är kompatibelt eftersom den första axeln har en 1:a (sträcks ut till 2) och den andra axeln matchar (3 == 3); resultatet har formen(2, 3).
Om något axelpar inte uppfyller något av villkoren är formerna inkompatibla och operatorn ger upphov till ValueError.
6.10.2. Exempel¶
Skalär mot vilken array som helst. Skalären agerar som form (1,) och sträcks ut till vad som helst:
a = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float)
a + 10 # (2, 3) + scalar -> (2, 3)
1D-vektor över en 2D-matris. Regel 1 lägger till en axel av storlek 1 framtill för att göra (3,) till (1, 3); regel 2 sträcker sedan ut den raden nedför varje kolumn i a
row = np.array([100, 200, 300], dtype=np.float)
a + row # (2, 3) + (3,) -> (2, 3)
Två 1D-arrayer av lika längd adderas elementvis – ingen broadcasting behövs:
np.arange(4) + np.arange(4)
Kolumnvektor mot en radvektor producerar en 2D-”yttre”-form: (4, 1) parad med (3,) blir (4, 1) mot (1, 3) efter rangpåfyllningen, och regel 2 sträcker ut varje operand längs sin axel av storlek 1:
x = np.array([1, 2, 3, 4]).reshape((4, 1)) # column
y = np.array([10, 20, 30]) # row
x + y # (4, 3) matrix
Samma formregler gäller för vilken tvåargumentsufunc som helst, arctan2() inkluderat:
np.arctan2(y, 1.0)
np.arctan2(y, x)
6.10.3. Vad broadcasting inte allokerar¶
Utsträckningen är virtuell. numpy går igenom båda operanderna tillsammans och läser om den mindre längs dess broadcastaxel istället för att kopiera den. Den kortare arrayens data replikeras aldrig i minnet.
Storleken på utdata-arrayen är vad som spelar roll för minnet. a + row allokerar en utdata med formen hos a, inte formen hos a plus formen hos row. Långa broadcastingkedjor kan ändå producera stora mellanresultat.
6.10.4. När broadcasting går fel¶
Det klassiska felet är två former där ingen har en axel av storlek 1 att sträcka ut och storlekarna inte stämmer överens – (3, 4) mot (4, 3), till exempel. Regel 2 kan inte matcha en 3:a mot en 4:a, så numpy ger upphov till ValueError.
Ett mer subtilt problem är en broadcast som lyckas, men inte på det sätt applikationen avsåg. (5,) mot (5, 1) är det kanoniska fallet: rangpåfyllningen gör (5,) till (1, 5), vilket broadcastar mot (5, 1) för att producera en (5, 5)-matris – den yttre kombinationen av de två vektorerna, inte det elementvisa resultatet av längd 5 som applikationen förmodligen ville ha. Vid tveksamhet, skriv ut shape på båda sidor och gå igenom reglerna steg för steg innan du tar till reshape() eller transpose().