Broadcasting lets NumPy perform arithmetic between arrays of different but compatible shapes without copying data. A smaller array is virtually stretched along dimensions of size 1 to match the larger array.
equal or either is 1.1, broadcasting fails.# Example A: (3, 4) +/- (4,) -> OK
# Align from right: (3, 4)
# ( 4) <-- 1D treated as (1,4), row-wise
# Result: (3,4)
# Example B: (3, 1) + (1, 4) -> OK
# Align: (3, 1)
# (1, 4)
# Result: (3,4) (each 1 expands)
# Example C: (2, 3) + (2,) -> FAIL
# Align: (2, 3)
# ( 2)
# 3 != 2 and neither is 1 -> ValueError
import numpy as np
A = np.arange(12).reshape(3,4)
row = np.array([10, 20, 30, 40]) # shape (4,)
col = np.array([[100],[200],[300]]) # shape (3,1)
print(A + row) # adds to each row
print(A + col) # adds to each column group
NumPy 1D arrays have shape (N,) (no row/col). Use np.newaxis or reshape to make explicit row/column vectors:
v = np.array([1, 2, 3, 4]) # shape (4,)
row_v = v[np.newaxis, :] # (1,4) row vector
col_v = v[:, np.newaxis] # (4,1) column vector
M = np.arange(8).reshape(2,4)
print(M + row_v) # OK: (2,4) + (1,4) -> (2,4)
print(M + col_v) # ValueError: (2,4) + (4,1) -- incompatible
# To add col-wise properly:
print(M + col_v[:2]) # (2,4) + (2,1) -> (2,4)
T = np.arange(2*3*4).reshape(2,3,4) # (depth=2, rows=3, cols=4)
bias_row = np.array([1,2,3,4]) # (4,)
bias_depth = np.array([100, 200]) # (2,)
print(T + bias_row) # (2,3,4) + (4,) -> (2,3,4)
print(T + bias_depth[:, None, None]) # (2,3,4) + (2,1,1) -> (2,3,4)
print(arr.shape), then align dimensions using np.newaxis or reshape.(1,N) or (N,1) depending on whether you want row-wise or column-wise broadcasting.# Standardize columns: (N, D) array -> subtract column means, divide by std
X = np.array([[1.0, 2.0, 3.0],
[2.0, 3.0, 4.0],
[3.0, 4.0, 5.0]])
mu = X.mean(axis=0) # (D,)
sigma = X.std(axis=0) # (D,)
Xz = (X - mu) / sigma # (N,D) - (D,) -> (N,D)
# Distance matrix between two sets: (N, d) and (M, d)
A = np.array([[0,0],[1,1],[2,2]]) # (3,2)
B = np.array([[0,1],[1,2]]) # (2,2)
diff = A[:, None, :] - B[None, :, :] # (3,1,2) - (1,2,2) -> (3,2,2)
D = np.sqrt((diff**2).sum(axis=-1)) # (3,2)
a = np.arange(6).reshape(2,3) # (2,3)
b = np.array([10,20]) # (2,)
# a + b -> ValueError (because 3 != 2, neither is 1)
# Fix 1: treat b as column vector (2,1)
b_col = b[:, None]
print(a + b_col) # (2,3) + (2,1) -> (2,3)
# Fix 2: repeat/expand if truly needed (use with care)
b_tiled = np.tile(b[:, None], (1, 3)) # explicit (2,3)
print(a + b_tiled)
tile/repeat: use broadcasting first; materialize only when required by APIs.%timeit and observe peak memory when broadcasting to very large shapes.# 1) Add a column bias [100, 200, 300] to a (3,4) matrix using broadcasting
M = np.arange(12).reshape(3,4)
bias = np.array([100, 200, 300])[:, None]
print(M + bias)
# 2) Scale each column of (5,3) by [1.0, 0.5, 2.0] without loops
X = np.arange(15).reshape(5,3)
scale = np.array([1.0, 0.5, 2.0])
print(X * scale)
# 3) Given (2,3,4) tensor T, add depth-wise bias [10, 20] correctly
T = np.arange(24).reshape(2,3,4)
depth_bias = np.array([10, 20])[:, None, None]
print(T + depth_bias)
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.