NumPy's linalg module and the @ operator cover the linear algebra behind machine learning, graphics and engineering: dot products, matrix multiplication, inverses and solving equations.
Dot product
Example
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(np.dot(a, b))
print(a @ b)
Output
32
32
1×4 + 2×5 + 3×6 = 32.
Matrix multiplication
Example
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(A @ B)
print(A * B)
Output
[[19 22]
[43 50]]
[[ 5 12]
[21 32]]
@ is true matrix multiplication; * multiplies element by element. Mixing them up is one of the most common NumPy mistakes.
Transpose
Example
import numpy as np
M = np.array([[1, 2, 3], [4, 5, 6]])
print(M.T)
print(M.T.shape)
Output
[[1 4]
[2 5]
[3 6]]
(3, 2)
Determinant and inverse
Example
import numpy as np
A = np.array([[4, 7], [2, 6]])
print(round(np.linalg.det(A), 2))
A_inv = np.linalg.inv(A)
print(A_inv)
print(np.allclose(A @ A_inv, np.eye(2)))
Output
10.0
[[ 0.6 -0.7]
[-0.2 0.4]]
True
Multiplying a matrix by its inverse gives the identity matrix. np.allclose() checks that while allowing for tiny floating-point differences.
Solve a system of equations
Suppose 2 pens and 3 notebooks cost 120, and 4 pens and 1 notebook cost 90. What does each cost?
Example
import numpy as np
# 2x + 3y = 120
# 4x + 1y = 90
coefficients = np.array([[2, 3], [4, 1]])
totals = np.array([120, 90])
print(np.linalg.solve(coefficients, totals))
Output
[15. 30.]
A pen costs 15 and a notebook 30. solve() is faster and more accurate than computing the inverse and multiplying.