Module 5 · Lesson 2
Matrix Multiplication
For 2-D arrays, @ performs real matrix multiplication: given
A of shape (m, n) and B of shape (n, p), A @ B has shape
(m, p), where each entry is the dot product of a row of A and a
column of B. The inner dimensions (n) must match.
This is completely different from A * B, which is the elementwise
(Hadamard) product and requires A and B to have the same shape (or be
broadcastable) — there’s no “inner dimension” concept at all.
A = np.array([[1, 2], [3, 4], [5, 6]]) # shape (3, 2)
B = np.array([[1, 0], [0, 1]]) # shape (2, 2)
print("A @ B shape:", (A @ B).shape) # (3, 2)
print(A @ B)
C = np.array([[1, 2], [3, 4], [5, 6]]) # same shape as A
print("A * C (elementwise):")
print(A * C)
Output:
A @ B shape: (3, 2)
[[1 2]
[3 4]
[5 6]]
A * C (elementwise):
[[ 1 4]
[ 9 16]
[25 36]]
Weighted row sums
Write weighted_sums(matrix, weights) that takes a (m, n) matrix and a
length-n weights vector, and returns a length-m vector where each
entry is the weighted sum of the corresponding row. Use a single matrix
multiplication — no loop.
💡 Hint
matrix @ weights does exactly this: a (m, n) @ (n,) product gives a length-m vector.
✅ Solution
def weighted_sums(matrix, weights):
return matrix @ weights
Matmul vs. Hadamard
Write both_products(A, B) that takes two same-shape square matrices and
returns a tuple (matmul_result, hadamard_result): the true matrix product
A @ B and the elementwise product A * B.
💡 Hint
Literally return (A @ B, A * B).
✅ Solution
def both_products(A, B):
return A @ B, A * B