6. NumpyΒΆ
Very powerful python tool for handling matrices and higher dimensional arrays
import numpy as np
# create arrays
a = np.array([[1,2],[3,4],[5,6]])
print(a)
print(a.shape)
# create all-zero/one arrays
b = np.ones((3,4)) # np.zeros((3,4))
print(b)
print(b.shape)
# create identity matrix
c = np.eye(5)
print(c)
print(c.shape)
[[1 2]
[3 4]
[5 6]]
(3, 2)
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
(3, 4)
[[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]]
(5, 5)
# reshaping arrays
a = np.arange(8) # [8,] similar range() you use in for-loops
b = a.reshape((4,2)) # shape [4,2]
c = a.reshape((2,2,-1)) # shape [2,2,2] -- -1 for auto-fill
d = c.flatten() # shape [8,]
e = np.expand_dims(a, 0) # [1,8]
f = np.expand_dims(a, 1) # [8,1]
g = e.squeeze() # shape[8, ] -- remove all unnecessary dimensions
print(a)
print(b)
[0 1 2 3 4 5 6 7]
[[0 1]
[2 3]
[4 5]
[6 7]]
# concatenating arrays
a = np.ones((4,3))
b = np.ones((4,3))
c = np.concatenate([a,b], 0)
print(c.shape)
d = np.concatenate([a,b], 1)
print(d.shape)
(8, 3)
(4, 6)
# one application is to create a batch for NN
x1 = np.ones((32,32,3))
x2 = np.ones((32,32,3))
x3 = np.ones((32,32,3))
# --> to create a batch of shape (3,32,32,3)
x = [x1, x2, x3]
x = [np.expand_dims(xx, 0) for xx in x] # xx shape becomes (1,32,32,3)
x = np.concatenate(x, 0)
print(x.shape)
(3, 32, 32, 3)
# access array slices by index
a = np.zeros([10, 10])
a[:3] = 1
a[:, :3] = 2
a[:3, :3] = 3
rows = [4,6,7]
cols = [9,3,5]
a[rows, cols] = 4
print(a)
[[3. 3. 3. 1. 1. 1. 1. 1. 1. 1.]
[3. 3. 3. 1. 1. 1. 1. 1. 1. 1.]
[3. 3. 3. 1. 1. 1. 1. 1. 1. 1.]
[2. 2. 2. 0. 0. 0. 0. 0. 0. 0.]
[2. 2. 2. 0. 0. 0. 0. 0. 0. 4.]
[2. 2. 2. 0. 0. 0. 0. 0. 0. 0.]
[2. 2. 2. 4. 0. 0. 0. 0. 0. 0.]
[2. 2. 2. 0. 0. 4. 0. 0. 0. 0.]
[2. 2. 2. 0. 0. 0. 0. 0. 0. 0.]
[2. 2. 2. 0. 0. 0. 0. 0. 0. 0.]]
# transposition
a = np.arange(24).reshape(2,3,4)
print(a.shape)
print(a)
a = np.transpose(a, (2,1,0)) # swap 0th and 2nd axes
print(a.shape)
print(a)
(2, 3, 4)
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]
(4, 3, 2)
[[[ 0 12]
[ 4 16]
[ 8 20]]
[[ 1 13]
[ 5 17]
[ 9 21]]
[[ 2 14]
[ 6 18]
[10 22]]
[[ 3 15]
[ 7 19]
[11 23]]]
c = np.array([[1,2],[3,4]])
# pinv is pseudo inversion for stability
print(np.linalg.pinv(c))
# l2 norm by default, read documentation for more options
print(np.linalg.norm(c))
# summing a matrix
print(np.sum(c))
# the optional axis parameter
print(c)
print(np.sum(c, axis=0)) # sum along axis 0
print(np.sum(c, axis=1)) # sum along axis 1
[[-2. 1. ]
[ 1.5 -0.5]]
5.477225575051661
10
[[1 2]
[3 4]]
[4 6]
[3 7]
# dot product
c = np.array([1,2])
d = np.array([3,4])
print(np.dot(c,d))
11
# matrix multiplication
a = np.ones((4,3)) # 4,3
b = np.ones((3,2)) # 3,2 --> 4,2
print(a @ b) # same as a.dot(b)
c = a @ b # (4,2)
# automatic repetition along axis
d = np.array([1,2,3,4]).reshape(4,1)
print(c + d)
# handy for batch operation
batch = np.ones((3,32))
weight = np.ones((32,10))
bias = np.ones((1,10))
print((batch @ weight + bias).shape)
[[3. 3.]
[3. 3.]
[3. 3.]
[3. 3.]]
[[4. 4.]
[5. 5.]
[6. 6.]
[7. 7.]]
(3, 10)
# speed test: numpy vs list
a = np.ones((100,100))
b = np.ones((100,100))
def matrix_multiplication(X, Y):
result = [[0]*len(Y[0]) for _ in range(len(X))]
for i in range(len(X)):
for j in range(len(Y[0])):
for k in range(len(Y)):
result[i][j] += X[i][k] * Y[k][j]
return result
import time
# run numpy matrix multiplication for 10 times
start = time.time()
for _ in range(10):
a @ b
end = time.time()
print("numpy spends {} seconds".format(end-start))
# run list matrix multiplication for 10 times
start = time.time()
for _ in range(10):
matrix_multiplication(a,b)
end = time.time()
print("list operation spends {} seconds".format(end-start))
# the difference gets more significant as matrices grow in size!
numpy spends 0.001990079879760742 seconds
list operation spends 8.681961059570312 seconds
# element-wise operations, for examples
np.log(a)
np.exp(a)
np.sin(a)
# operation with scalar is interpreted as element-wise
a * 3
array([[3., 3., 3., ..., 3., 3., 3.],
[3., 3., 3., ..., 3., 3., 3.],
[3., 3., 3., ..., 3., 3., 3.],
...,
[3., 3., 3., ..., 3., 3., 3.],
[3., 3., 3., ..., 3., 3., 3.],
[3., 3., 3., ..., 3., 3., 3.]])