[Nhập môn Machine Learning] Bài 8: Giới thiệu các thư viện Numpy, Matplotlib, Pandas (P1: Numpy)
Trước khi có thể cài đặt thuật toán Machine Learning, chúng ta cần tìm hiểu về các công cụ trước đã. Trong bài viết này, mình muốn giới thiệu với các bạn "bộ ba quyền lực" trong các thư viện Machine Learning của ngôn ngữ Python đó là:
- Numpy: thư viện hỗ trợ tính toán ma trận
- Matplotlib: thư viện hỗ trợ biểu diễn đồ thị
- Pandas: thư viện giúp thao tác với dữ liệu bảng biểu (hay còn có tên gọi khác là Excel của lập trình viên).
Python và pip
Trong bài viết này, mình sử dụng Python 3.7 . Để kiểm tra máy bạn đã có Python chưa, hãy mở cmd/Terminal lên và gõpython --version
hoặc
python3 --version
nếu lệnh trên không hoạt động. Nếu máy bạn đã có Python thì sẽ được trả lại kết quả như bên dưới.
Nếu kết quả khác thì bạn có thể tới trang chủ của Python và tải về.
Khi bạn tải Python về, đồng thời bạn cũng sẽ được cài đặt luôn pip. Pip là trình quản lý thư viện của Python và chúng ta sẽ sử dụng pip để cài đặt 3 thư viện trên. Tuy nhiên, để chắc chắc bạn cũng nên kiểm tra xem pip có được cài hay không. Tùy thuộc vào lệnh bạn gõ ở trên để kiểm tra là
python
hay python3
thì bạn cũng có thể sử dụng các lệnh tương ứng để gọi pip là pip
hoặc pip3
. Do trên máy của mình sử dụng python3
nên mình sẽ sử dụng lệnh dưới để kiểm tra.pip3 --version
Và mình được kết quả:
Về cơ bản, chúng ta đã có thể bắt đầu nhưng để việc viết code dễ dàng, bạn có thể download thêm một text editor hoặc một IDE như PyCharm.
Cài đặt
Việc cài đặt 3 thư viện cùng một lúc được thực hiện bằng cách gọi pip cùng với lệnhpip3 install numpy matplotlib pandas
hoặc có thể cài đặt từng thư viện một
pip3 install numpy
pip3 install matplotlib
pip3 install pandas
Chúc mừng, vậy là bạn đã cài đặt được 3 thư viện cần thiết để bắt đầu.Một lưu ý nhỏ cho những bạn sử dụng Text Editor: Để có thể chạy chương trình python, bạn cần phải bật terminal tại vị trí file .py muốn chạy và gõ
python3 <filename>.py
hoặcpython <filename>.py
Giới thiệu về Numpy
Tạo mảng đa chiều ndarray
Numpy là một thư viện quan trọng để tương tác với mảng nhiều chiều. Thư viện này lưu trữ dữ liệu trong mảng dưới dạng mảng đặc biệt gọi là ndarray. Để bắt đầu, hãy lấy một text editor/IDE bạn thích và tạo một file "basic.py" sau đó thêm vàoimport numpy as np
để tải thư viện Numpy và gọi nó thông qua cái tên "np". Lúc này, bạn có thể tạo một mảng trong numpy bằng
a = np.array([1,2,3])
print(a)
"""
Output: [1 2 3]
"""
print(type(a))
"""
Output: <type 'numpy.ndarray'>
"""
b = np.array([[1,2,3],
[4,5,6]])
print(b)
"""
Output:
[[1 2 3]
[4 5 6]]
"""
c = np.array([[[1,2,3], [4,5,6]],
[[7,8,9], [10,11,12]]])
print(c)
"""
Output:
[[[ 1 2 3]
[ 4 5 6]]
[[ 7 8 9]
[10 11 12]]]
"""
print(a.shape) # Output: (3,)
print(b.shape) # Output: (2, 3)
print(c.shape) # Output: (2, 2, 3)
Có một lỗi mình hay gặp khi thao tác với numpy đó là không để ý số chiều của mảng. Ví dụ như trong đoạn code sau
d = np.array([[1,2,3]])
a
chúng ta đã tạoa = np.array([1,2,3])
d
là mảng 2 chiều (hãy đếm số ký tự '[') còn a
là mảng một chiều. Chúng ta cũng có thể kiểm chứng điều này bằng cách in ra kích thước của chúng.print(a.shape) # Output: (3,)
print(d.shape) # Output: (1, 3)
Các ma trận khác
Numpy cũng cung cấp cho chúng ta những hàm để tạo một vài ma trận cụ thể như:# Tạo một ma trận 2x2 với toàn 1
print(np.ones((2,2)))
"""
Output:
[[1. 1.]
[1. 1.]]
"""
# Tạo một ma trận 2x2 với toàn 0
print(np.zeros((2,2)))
"""
Output:
[[0. 0.]
[0. 0.]]
"""
# Tạo một ma trận đơn vị 3x3
print(np.eye(3))
"""
Output:
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
"""
# Tạo một ma trận ngẫu nhiên với kích thước 3x2
print(np.random.rand(3,2))
"""
Output:
[[0.96600899 0.04178217]
[0.94935854 0.90623781]
[0.72550038 0.23328825]]
"""
Các phép toán trên ma trận
Nếu chúng ta có 2 ma trận cùng kích thước với nhau, ta có thể thực hiện cộng, trừ, nhân, chia theo phần tử giữa 2 ma trận này. Giả sử với tính cộng, phần tử ở vị trí (1,1) ở ma trậna
sẽ được cộng với phần tử ở vị trí (1,1) ở ma trận b
và cứ thế cho tới phần tử ở vị trí cuối cùng.a = np.array([[1,0,2],
[2,3,0]])
b = np.array([[2,1,-1],
[2,1,2]])
print(a+b) # Output: [[3 1 1]
# [4 4 2]]
print(a-b) # Output: [[-1 -1 3]
# [ 0 2 -2]]
print(a*b) # Output: [[ 2 0 -2]
# [ 4 3 0]]
print(a/b) # Output: [[ 0.5 0. -2. ]
# [ 1. 3. 0. ]]
Broadcasting
Tuy nhiên, không chỉ dừng ở đó, numpy còn hỗ trợ một tính năng gọi là broadcasting. Broadcasting giúp chúng ta có thể cộng, trừ, nhân, chia một ma trận với một số nguyên hoặc một ma trận khác mà kích thước của nó có ít nhất một chiều bằng với ma trận kia. Để hiểu rõ hơn, cách tốt nhất là đưa ra một ví dụ.a = np.array([[1,0,2],
[2,3,0]]) # shape: (2,3)
b = np.array([[1,2,1]]) # shape: (1,3)
c = np.array([[1],
[2]]) # shape: (2,1)
print(a-1) # Output: [[ 0 -1 1]
# [ 1 2 -1]]
print(a-b) # Output: [[ 0 -2 1]
# [ 1 1 -1]]
print(a-c) # Output: [[ 0 -1 1]
# [ 0 1 -2]]
c
ở trên có kích thước (2x2) thì chúng ta không thể làm điều tương tự. Để hiểu sâu hơn về broadcasting, bạn có thể đọc thêm tại trang chính thức của Numpy.Chuyển vị ma trận
b = np.array([[2,1,-1],
[2,1,2]])
print(b) # Output: [[ 2 1 -1]
# [ 2 1 2]]
print(b.T) # Output: [[ 2 2]
# [ 1 1]
# [-1 2]]
Nhân ma trận
a = np.array([[1,0,2],
[2,3,0]])
b = np.array([[2,1,-1],
[2,1,2]])
mul = np.matmul(a, b.T)
print(mul) # Output: [[0 6]
# [7 7]]
Truy cập một phần tử trong ma trận
Giống như với mảng 2 chiều thông thường, ta có thể truy cập phần tử trong mảng bằng cú pháparr[nrow][ncol]
"""
nrow: index của dòng cần truy cập
ncol: index của cột cần truy cập
"""
arr[nrow, ncol]
"""
nrow: index của dòng cần truy cập
ncol: index của cột cần truy cập
"""
a = np.array([[1,0,2],
[2,3,0]])
# Truy cập ----^
print(a[1,0]) # Output: 2
Slicing
Slicing là cách để truy cập nhiều phần tử trong mảng cùng một lúc được hỗ trợ bởi mảng trong numpy. Cú pháp slice như sau:start_index : end_index:step
"""
lấy từ start_index đến end_index-1 (không bao gồm end_index) với mỗi bước
khoảng cách là step
"""
start_index
hay end_index
được bỏ trống thì mặc định là lấy hết từ đầu (với start_index
) hoặc đến cuối (với end_index
). step
nếu không đề cập thì mặc định là 1.Ví dụ:
a = np.array([[1,0,2],
[2,3,0]])
# Lấy nguyên dòng 2
print(a[1,:]) # Output: [2 3 0]
# Lấy nguyên cột 2
print(a[:,1]) # Output: [0 3]
# Lấy đến dòng 2 và đến cột 2
print(a[:2, :2]) # Output: [[1 0]
# [2 3]]
Masking
Một cách để truy cập những phần tử trong numpy đó chính là sử dụng một mảng boolean với để xác định những phần tử cần lấy. Việc này rất có ích khi chúng ta có thể sử dụng masking để lấy ra những giá trị thỏa những tiêu chí cụ thể trong mảng.Giả sử mình muốn lấy những phần tử lớn hơn hoặc bằng 2 trong mảng, mình có thể làm như sau:
a = np.array([[1,0,2],
[2,3,0]])
mask = a>=2
print(a[mask]) # Output: [2 2 3]
mask
, bạn sẽ thấy mask
chỉ là một mảng boolean có kích thước bằng với a
và những vị trí (0,2), (1,0) và (1,1) đều có giá trị True
tương ứng với vị trí các giá trị thỏa yêu cầu.Thay đổi giá trị và kích thước của mảng
Thay đổi giá trị
a = np.array([[1,0,2],
[2,3,0]])
# Normal
a[0,1] = 5
print(a) # Output: [[1 5 2]
# [2 3 0]]
# Slicing
a[:,0] = np.zeros((2,)) # Kích thước mảng mới phải trùng với kích thước trả về
# Ở đây bạn có thể chỉ gán giá trị 0 cũng được,
# broadcasting sẽ làm nhiện vụ của nó
print(a) # Output: [[0 5 2]
# [0 3 0]]
# Masking
a = np.array([[1,0,2],
[2,3,0]])
a[mask] = -1
print(a) # Output: [[ 1 0 -1]
# [-1 -1 0]]
Thay đổi kích thước
Mỗi ndarray đều có một hàmreshape
để thay đổi kích thước của mảng, hàm này lấy một giá trị là 2 kích thước mới. Hàm reshape
này cũng có thể lấy 1 giá trị đặc biệt là -1 tức là "sao cũng được, tôi không quan tâm giá trị của nó là bao nhiêu".a = np.array([[1,0,2],
[2,3,0]])
print(a.reshape((3,2))) # Output: [[1 0]
# [2 2]
# [3 0]]
# Ta chỉ cần biết ta muốn 1 dòng và ta không quan tâm đến chiều còn lại
print(a.reshape((1,-1))) # Output: [[1 0 2 2 3 0]]
Tạm kết
Do bài viết đã dài (và mình đã mỏi tay) nên chúng ta sẽ tìm hiểu matplotlib và pandas ở bài sau. Nếu các bạn có ý kiến hoặc góp ý gì về bài viết của mình, mong các bạn để lại bình luận bên dưới để mình có thể phát triển bài viết hơn.Mã nguồn đầy đủ
import numpy as np
# Tạo mảng
a = np.array([1,2,3])
print("1D array")
print(a)
# Xác định kiểu của mảng
print("Type: ", type(a))
# Tạo mảng 2 chiều (ma trận)
b = np.array([[1,2,3],
[4,5,6]])
print("2D array")
print(b)
# Tạo mảng 3 chiều (tensor)
c = np.array([[[1,2,3], [4,5,6]],
[[7,8,9], [10,11,12]]])
print("3D array")
print(c)
# Mảng 2 chiều chứa 1 dòng, nhưng không phải mảng 1 chiều
d = np.array([[1,2,3]])
# In ra kích thước các mảng
print("Shape of a: ", a.shape)
print("Shape of a: ", b.shape)
print("Shape of a: ", c.shape)
print("Shape of a: ", d.shape)
# Các ma trận khác
print("Matrix of ones")
print(np.ones((2,2)))
print("Matrix of zeros")
print(np.zeros((2,2)))
print("Identity matrix")
print(np.eye(3))
print("Random matrix")
print(np.random.rand(3,2))
# Các toán tử cơ bản
a = np.array([[1,0,2],
[2,3,0]])
b = np.array([[2,1,-1],
[2,1,2]])
print("a+b: ", a+b)
print("a-b: ", a-b)
print("a*b: ", a*b)
print("a/b: ", a/b)
# Broadcasting
a = np.array([[1,0,2],
[2,3,0]])
b = np.array([[1,2,1]])
c = np.array([[1],
[2]])
print("Broadcasting")
print(a-1)
print(a-b)
print(a-c)
# Chuyển vị ma trận
b = np.array([[2,1,-1],
[2,1,2]])
print("b: ", b)
print("b transpose: ", b.T)
# Nhân ma trận
mul = np.matmul(a, b.T)
print("a.bT: ", mul)
# Truy cập mảng
a = np.array([[1,0,2],
[2,3,0]])
print(a[1,0])
print(a[1,:])
print(a[:,1])
print(a[:2, :2])
# Masking
a = np.array([[1,0,2],
[2,3,0]])
mask = a>=2
print("Elements that greater than or equal 2")
print(a[mask])
# Thay đổi phần tử trong mảng
a = np.array([[1,0,2],
[2,3,0]])
print("Changed (0,1)")
a[0,1] = 5
print(a)
print("Changed column 0")
a[:,0] = np.zeros((2,))
print(a)
print("Change with masking")
a = np.array([[1,0,2],
[2,3,0]])
a[mask] = -1
print(a)
# Thay đổi kích thước mảng
a = np.array([[1,0,2],
[2,3,0]])
print("Reshape to 3x2")
print(a.reshape((3,2)))
print("Reshape to one row (still 2D)")
print(a.reshape((1,-1)))
Nhận xét
Đăng nhận xét