Table of Contents
One-Hot Encoding
Use the identity matrix trick — clean and handles batches naturally:
n_classes = 5one_hot = np.eye(n_classes)[class_idx] # single vectorone_hot_batch = np.eye(n_classes)[indices] # batch, shape (N, n_classes)For large n_classes, avoid the intermediate matrix:
one_hot = np.zeros(n_classes)one_hot[class_idx] = 1.0
# batch versionone_hot_batch = np.zeros((len(indices), n_classes))one_hot_batch[np.arange(len(indices)), indices] = 1.0argmax
Returns the index of the maximum value:
np.argmax(a) # global max indexnp.argmax(a, axis=1) # per-row max index (batch of logits)Complement: np.argmin for minimum index.
Rounding Floats
round(3.14159265, 6) # Python built-in → 3.141593f"{3.14159265:.6f}" # string formattingnp.round(arr, 6) # numpy arrayConverting Array Types
arr.tolist() # numpy array → Python list of floats (for JSON etc.)arr.astype(float) # stays ndarray, ensures float64arr.astype(int) # float → intarr.astype(np.int32)Array ↔ Python List
Array → list:
arr.tolist() # ✓ recursive; casts elements to NATIVE Python types (int/float)list(arr) # ✗ iterates only the first axis; elements stay numpy scalars (np.float64)Use .tolist() — handles any dimensionality and produces native types (needed for json.dumps,
which chokes on numpy scalars):
np.array([[1, 2], [3, 4]]).tolist() # [[1, 2], [3, 4]] — nestedlist(np.array([1.0, 2.0])) # [np.float64(1.0), np.float64(2.0)] — not Python floatsList → array:
np.array([1, 2, 3]) # infers dtype (int64)np.array([[1, 2], [3, 4]]) # nested → 2Dnp.array([1, 2, 3], dtype=float) # force dtypenp.asarray(my_list) # skips copy if already an ndarraynp.arrayalways copies by default;np.asarrayavoids the copy when the input is already an ndarray of the right dtype — prefer it for “array-like” function inputs.- Ragged lists (unequal sublengths) → error in modern numpy (older: object array — avoid):
np.array([[1, 2], [3]]) # ERROR
Initializing a 2D Matrix with Random Values
Standard normal:
np.random.randn(rows, cols) # legacyrng = np.random.default_rng(seed=42)W = rng.standard_normal((rows, cols)) # modernScale for neural network weights:
W = np.random.randn(rows, cols) * 0.01Uniform distribution:
np.random.rand(rows, cols) # [0, 1) — legacynp.random.uniform(0, 1, (rows, cols)) # explicit range — legacy
# Modern approachrng = np.random.default_rng(seed=42)rng.uniform(0, 1, (rows, cols)) # [0, 1)rng.uniform(-1, 1, (rows, cols)) # [-1, 1)rng.random((rows, cols)) # [0, 1) — shorthandnp.random.default_rng
Modern random number generator (NumPy 1.17+). Preferred over legacy np.random.*.
rng = np.random.default_rng(seed=42) # reproduciblerng = np.random.default_rng() # random each runWhy preferred:
- Explicit seed on the object — no global state interference
- Higher quality algorithm (PCG64 vs Mersenne Twister)
Common methods:
rng.standard_normal((3, 4))rng.random((3, 4)) # uniform [0, 1)rng.integers(0, 10, (3, 4))rng.choice([1, 2, 3], size=5)rng.shuffle(arr)Transpose / Permute Dimensions
A.transpose(0, 2, 1, 3) # pass new order of axesnp.transpose(A, (0, 2, 1, 3)) # same(0, 2, 1, 3) means: keep axis 0, swap axes 1 and 2, keep axis 3.
PyTorch equivalent:
A.permute(0, 2, 1, 3) # arbitrary reorderingA.transpose(1, 2) # swaps only two dims at a timeApplying a Function Element-wise
vf = np.vectorize(my_func)vf(A) # applies my_func to each scalar elementnp.vectorize is syntactic sugar over a Python loop — not truly fast. Prefer native numpy ops:
A ** 2 + 1 # C-level vectorized — much fasternp.maximum(A, 0)Use np.vectorize only when the function can’t be expressed with native numpy ops.
If the function needs the row index, build an index matrix or loop over rows:
# index matrix approachrows, cols = A.shapei_matrix = np.repeat(np.arange(rows).reshape(-1, 1), cols, axis=1)vf(A, i_matrix)
# loop approach — cleanerresult = np.stack([my_func(row, i) for i, row in enumerate(A)])Broadcasting
NumPy broadcasts automatically when dimensions are equal or 1:
row = np.ones((1, d)) # (1, d)A = np.ones((m, d)) # (m, d)A + row # (1, d) → repeated m times automaticallyExplicit broadcasting:
np.broadcast_to(row, (m, d)) # read-only viewPyTorch:
row + A # same automatic broadcastingrow.expand(m, d) # explicitVector (i,) → Column Vector (i,1)
v.reshape(-1, 1) # numpy and pytorch — most portablev[:, None] # slicing with None adds a dimv[:, np.newaxis] # numpy — same as None, explicitv.unsqueeze(1) # pytorchnp.expand_dims(v, 1) # numpy function formReshape
A.reshape(3, 4) # explicit dims — total elements must stay the sameA.reshape(3, -1) # -1 infers the missing dim automaticallyA.reshape(-1) # flatten to 1D
A.flatten() # always returns a copyA.ravel() # returns view when possible (faster)PyTorch equivalent:
A.reshape(3, 4) # same APIA.view(3, 4) # faster but requires contiguous memoryMean and Variance
np.mean(x) # global meannp.var(x) # variance (1/N by default)np.std(x) # standard deviation
np.mean(x, axis=-1, keepdims=True) # across features — keepdims for broadcastingnp.var(x, axis=-1, keepdims=True)PyTorch:
x.mean(dim=-1, keepdim=True)x.var(dim=-1, keepdim=True, unbiased=False) # unbiased=False → 1/N (matches LayerNorm)np.var uses 1/N (population variance) by default. PyTorch torch.var defaults to unbiased=True (1/(N-1)) — set unbiased=False to match numpy/LayerNorm.
Reduction Along an Axis
np.max(A, axis=0) # max along rows → shape (cols,)np.max(A, axis=1) # max along cols → shape (rows,)np.max(A) # global max → scalar
np.max(A, axis=1, keepdims=True) # shape (rows,1) — preserves dim for broadcastingSame API applies to: np.min, np.sum, np.mean, np.argmax, np.argmin.
NumPy vs PyTorch: NumPy uses axis, PyTorch uses dim — same concept, different keyword.
np.max(A, axis=1) # numpytorch.max(A, dim=1) # pytorchMultiplication Operations
a * b # element-wisenp.multiply(a, b) # same
np.dot(a, b) # 1D vectors: inner product → scalara @ b # dot product or matmul depending on shape (preferred)
np.matmul(A, B) # matrix multiplication (m,k)@(k,n) → (m,n)np.outer(a, b) # outer product (m,)×(n,) → (m,n)| Operation | Inputs | Output |
|---|---|---|
| Element-wise | (n,) × (n,) | (n,) |
| Dot product | (n,) × (n,) | scalar |
| Matrix × vector | (m,n) × (n,) | (m,) |
| Matrix × matrix | (m,k) × (k,n) | (m,n) |
| Outer product | (m,) × (n,) | (m,n) |
| Batched matmul | (b,m,k) × (b,k,n) | (b,m,n) |
@ is preferred for matrix/vector multiplication — works for 2D and batched cases. Use * only for element-wise.
Computing Norms
NumPy:
np.linalg.norm(v) # L2 norm (default)np.linalg.norm(v, ord=1) # L1 normnp.linalg.norm(v, ord=np.inf) # L∞ normPyTorch:
torch.linalg.norm(v) # L2 norm (default)torch.norm(v) # older API, same resulttorch.linalg.norm(v, ord=1)ReLU
No built-in in NumPy — use:
np.maximum(x, 0) # recommendedx * (x > 0) # alternativenp.clip(x, 0, None) # alternativePyTorch:
torch.relu(x)torch.nn.functional.relu(x)Numerically Stable Sigmoid
NumPy has no built-in sigmoid. Options:
from scipy.special import expit # recommendedexpit(x)
# Manual stable implementation:def sigmoid(x): return np.where(x >= 0, 1 / (1 + np.exp(-x)), np.exp(x) / (1 + np.exp(x)))