NumPy Cơ bản — Phần 2

Hao Phu Phan
6 min readJul 25, 2019

--

Trong phần 1, chúng ta đã tìm hiểu sơ lược về thư viện NumPy, các tính chất chính của NumPy arrays và cách khởi tạo chúng thông qua các hàm của thư viện.

Series NumPy Cơ bản sẽ tiếp tục trong bài viết này với các nội dung về Array Indexing và các phép toán với NumPy arrays

Array Indexing

NumPy cung cấp một số cách để truy xuất phần tử trong mảng

Indexing và slicing: Mỗi thành phần trong mảng 1 chiều tương ứng với một chỉ số. Chỉ số trong NumPy, cũng giống như chỉ số trong python, bắt đầu bằng 0. Nếu mảng 1 chiều có n phần tử thì các chỉ số chạy từ 0 đến n - 1. Và tương tự như list trong python, NumPy arrays cũng có thể được cắt (slicing).

# Khởi tạo numpy array có shape = (3, 4) như sau:
a = np.array([[1,2,3,4],
[5,6,7,8],
[9,10,11,12]]
# Dùng chỉ số để lấy phần tử hàng 1, cột 2
print(a[1][2]) # 7
print(a[1, 2]) # 7
# Dùng slicing để lấy 2 hàng đầu tiên của 2 cột đầu tiên
print(a[:2][:2])
# [[1 2]
[5 6]]
# Kết hợp dùng slicing và indexing
# Chú ý: sẽ tạo ra mảng có rank thấp hơn mảng cũ
r1 = a[1, :] # Rank 1, hàng 1 của a
print(r1, r1.shape) # [[5 6 7 8]] (4,)

Boolean array indexing: Cho phép bạn chọn ra các phần tử tùy ý của một mảng, thường được sử dụng để chọn ra các phần tử thỏa mãn điều kiện nào đó

a = np.array([[1,2], [3, 4], [5, 6]])
bool_idx = (a > 2) # Tìm các phần tử lớn hơn 2;
# Trả về 1 numpy array of Booleans có shape như mảng a
# và giá trị tại mỗi phần tử là
# True nếu phần tử của a tại đó > 2,
# False cho trường hợp ngược lại.
print(bool_idx)
# [[False False]
# [True True]
# [True True]]”

Đọc thêm: Numpy Indexing and Slicing

Các phép toán với NumPy arrays

Phép cộng, trừ, nhân, chia, lũy thừa, căn bậc 2 chỉ với một dòng code. Dưới đây là một số ví dụ về các phép toán số học và nhân khác nhau với các mảng Numpy

x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.array([[5,6],[7,8]], dtype=np.float64)
# Tổng của 2 mảng, cả 2 cách cho cùng một kết quả
# [[ 6.0 8.0]
# [10.0 12.0]]
print(x + y)
print(np.add(x, y))
# Hiệu 2 mảng
# [[-4.0 -4.0]
# [-4.0 -4.0]]
print(x - y)
print(np.subtract(x, y))
# Tính tích từng phần tử của x nhân với từng phần tử của y
# [[ 5.0 12.0]
# [21.0 32.0]]
print(x * y)
print(np.multiply(x, y))
# Thương của từng phần tử trong x chia với từng phần tử y
# [[ 0.2 0.33333333]
# [ 0.42857143 0.5 ]]
print(x / y)
print(np.divide(x, y))
# a mũ b với a là các phần tử trong x và b là các phần tử trong y
# [[1.0000e+00 6.4000e+01]
# [2.1870e+03 6.5536e+0prints “4]]
print(x ** y)
# Căn bậc 2 từng phần tử trong x
# [[ 1. 1.41421356]
# [ 1.73205081 2. ]]
print(np.sqrt(x))

Để nhân 2 ma trận hoặc nhân vector với ma trận trong NumPy, chúng ta sử dụng hàm dot

x = np.array([[1,2],[3,4]])
y = np.array([[5,6],[7,8]])
v = np.array([9,10])
w = np.array([11, 12])
# Tích trong của 2 vector; Cả 2 đều cho kết quả là 219
print(v.dot(w))
print(np.dot(v, w))
# Nhân ma trận với vector; cả 2 đều cho mảng rank 1: [29 67]
print(x.dot(v))
print(np.dot(x, v))
# Ma trận với ma trận; cả 2 đều cho mảng rank 2
# [[19 22]
# [43 50]]
print(x.dot(y))
print(np.dot(x, y))

Các hàm toán học như np.sum ,np.abs, np.log, np.exp, np.sin, np.cos, np.tan cũng áp dụng lên từng phần tử của mảng. Hàm np.log là logarit tự nhiên, hàm np.exp là hàm e^x. Ví dụ sử dụng hàm np.sum như sau:

x = np.array([[1,2],[3,4]]) 
print(np.sum(x)) # Tổng các phần tử của mảng; # 10
print(np.sum(x, axis=0)) # Tính tổng theo từng cột; # [4 6] print(np.sum(x, axis=1)) # Tính tổng theo từng hàng; # [3 7]

Để tìm giá trị lớn nhất hay nhỏ nhất của mảng một chiều, chúng ta đơn giản sử dụng hàm np.min hoặc np.max. Ví dụ:

a = np.arange(10)
a[-1] = -2
np.min(a) # -2
np.max(a) # 8

hoặc:

a.min() # -2
a.max() # 8

Để tìm chỉ số mà tại đó mảng một chiều đạt giá trị nhỏ nhất hay lớn nhất, ta có thể sử dụng np.argmin, hoặc np.argmax:

np.argmin(a) # 9
np.argmax(a) # 8

hoặc:

a.argmin() # 9
a.argmax() # 8

Broadcasting

Broadcasting là một cơ chế mạnh mẽ cho phép thực thi các phép toán số học trên các NumPy arrays có kích thước khác nhau. Chúng ta thường có một mảng nhỏ hơn và một mảng lớn hơn và chúng ta muốn sử dụng mảng nhỏ hơn nhiều lần để thực hiện một số thao tác trên mảng lớn hơn.

Ví dụ: Giả sử rằng chúng ta muốn cộng một vector không đổi vào mỗi hàng của ma trận. Chúng ta có thể làm như thế này

# Cộng vector v vào mỗi hàng của ma trận x,
# Lưu trữ kết quả trong ma trận y
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
y = np.empty_like(x) # Tạo một ma trận rỗng có shape như x
# Thêm vector v vào mỗi hàng của ma trận x bằng một vòng lặp
for i in range(4):
y[i, :] = x[i, :] + v
# Ma trận y sẽ như sau
# [[ 2 2 4]
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]
print(y)

Cách này có thể chạy được nhưng khi ma trận x có kích thước quá lớn, việc sử dụng vòng lặp của Python sẽ rất chậm. Dễ thấy, việc thêm vector v vào mỗi hàng của ma trận x tương đương với việc tạo một ma trận từ vector v (vv) bằng cách xếp chồng nhiều bản sao của v theo chiều dọc, sau đó thực hiện phép tính tổng của x và ma trận này. Cụ thể như sau:

# Chúng ta sẽ thêm vector v vào mỗi hàng của ma trận x,
# Lưu trữ kết quả trong ma trận y
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
vv = np.tile(v, (4, 1)) # Xếp chồng 4 bản sao của v lên nhau
print(vv) # Prints "[[1 0 1]
# [1 0 1]
# [1 0 1]
# [1 0 1]]"
y = x + vv # Thực hiện phép cộng
print(y) # [[ 2 2 4
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]"

NumPy broadcasting cho phép chúng ta thực thi tính toán theo cách như trên mà không cần phải tạo ra nhiều bản sao của v:

# Chúng ta sẽ thêm vector v vào mỗi hàng của ma trận x,
# Lưu trữ kết quả trong ma trận y
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
y = x + v # Tự động cộng v vào từng hàng của x sử dụng broadcasting
print(y) # [[ 2 2 4]
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]

Về nguyên tắc thực thi của broadcasting bạn có thể tham khảo tại đây

Kết luận

Những kiến thức từ 2 bài viết NumPy Cơ bản đã cung cấp những hiểu biết sơ lược cần thiết về NumPy. Tuy nhiên, NumPy là một thư viện lớn và phức tạp, hãy đọc tài liệu này để tìm hiểu thêm.

Tài liệu tham khảo

Python NumPy Tutorial
Machine Learning cơ bản: FundaML 1

Để thực hành sử dụng numpy, download file jupyter notebook tại đây

--

--