-
Tuần 1 - Ngày 10 tháng 7 năm 2019
- Giới thiệu về khóa học
- Hướng dẫn viết chương trình Python trên web
- Hướng dẫn sử dụng PyCharm
- Tổng quan về Python
- Kỹ năng sử dụng Google search
- Viết tài liệu kỹ thuật dùng Markdown
- Hàm xây dựng sẵn trong Python – math và random
- Cài đặt các công thức toán cơ bản
- Xây dựng hàm trong python
- Điều kiện if-else
- Những lỗi thường gặp trong Python
- Reading assignment
-
Tuần 2 - Ngày 17 tháng 7 năm 2019
-
Tuần 3 - Ngày 24 tháng 7 năm 2019
-
Tuần 4 - Ngày 31 tháng 7 năm 2019
-
Tuần 5 - Ngày 7 tháng 8 năm 2019
-
Advanced Python
-
Tuần 6 - Ngày 14 tháng 8 năm 2019
-
Tuần 7 - Ngày 28 tháng 8 năm 2019
-
Tuần 8
-
Tuần 9
Softmax Regression
Ở bài học trước, chúng ta dùng logistic regression cho bài toán phân loại nhị phân (binary classification). Hàm sigmoid được dùng để ánh xạ giá trị output o (\(o = X \cdot W\)) về (0,1).
Trong bài này, chúng ta sẽ học các phương pháp phân loại cho bài toán có nhiều loại (multi-class classification). Ví dụ, chúng ta muốn cài đặt chương trình để phân loại các loài hoa Iris dựa vào IRIS dataset. IRIS dataset có 3 loài hoa, và mỗi loài hoa có 4 đặc trưng.
Sepal_Length | Sepal_Width | Petal_Length | Petal_Width | Label |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | 0.0 |
4.9 | 3.0 | 1.4 | 0.2 | 0.0 |
4.7 | 3.2 | 1.3 | 0.2 | 0.0 |
4.6 | 3.1 | 1.5 | 0.2 | 0.0 |
5.0 | 3.6 | 1.4 | 0.2 | 0.0 |
5.4 | 3.9 | 1.7 | 0.4 | 0.0 |
4.6 | 3.4 | 1.4 | 0.3 | 0.0 |
5.0 | 3.4 | 1.5 | 0.2 | 0.0 |
4.4 | 2.9 | 1.4 | 0.2 | 0.0 |
4.9 | 3.1 | 1.5 | 0.1 | 0.0 |
5.4 | 3.7 | 1.5 | 0.2 | 0.0 |
4.8 | 3.4 | 1.6 | 0.2 | 0.0 |
4.8 | 3.0 | 1.4 | 0.1 | 0.0 |
4.3 | 3.0 | 1.1 | 0.1 | 0.0 |
5.8 | 4.0 | 1.2 | 0.2 | 0.0 |
5.7 | 4.4 | 1.5 | 0.4 | 0.0 |
5.4 | 3.9 | 1.3 | 0.4 | 0.0 |
5.1 | 3.5 | 1.4 | 0.3 | 0.0 |
5.7 | 3.8 | 1.7 | 0.3 | 0.0 |
5.1 | 3.8 | 1.5 | 0.3 | 0.0 |
5.4 | 3.4 | 1.7 | 0.2 | 0.0 |
5.1 | 3.7 | 1.5 | 0.4 | 0.0 |
4.6 | 3.6 | 1.0 | 0.2 | 0.0 |
5.1 | 3.3 | 1.7 | 0.5 | 0.0 |
4.8 | 3.4 | 1.9 | 0.2 | 0.0 |
5.0 | 3.0 | 1.6 | 0.2 | 0.0 |
5.0 | 3.4 | 1.6 | 0.4 | 0.0 |
5.2 | 3.5 | 1.5 | 0.2 | 0.0 |
5.2 | 3.4 | 1.4 | 0.2 | 0.0 |
4.7 | 3.2 | 1.6 | 0.2 | 0.0 |
4.8 | 3.1 | 1.6 | 0.2 | 0.0 |
5.4 | 3.4 | 1.5 | 0.4 | 0.0 |
5.2 | 4.1 | 1.5 | 0.1 | 0.0 |
5.5 | 4.2 | 1.4 | 0.2 | 0.0 |
4.9 | 3.1 | 1.5 | 0.1 | 0.0 |
5.0 | 3.2 | 1.2 | 0.2 | 0.0 |
5.5 | 3.5 | 1.3 | 0.2 | 0.0 |
4.9 | 3.1 | 1.5 | 0.1 | 0.0 |
4.4 | 3.0 | 1.3 | 0.2 | 0.0 |
5.1 | 3.4 | 1.5 | 0.2 | 0.0 |
5.0 | 3.5 | 1.3 | 0.3 | 0.0 |
4.5 | 2.3 | 1.3 | 0.3 | 0.0 |
4.4 | 3.2 | 1.3 | 0.2 | 0.0 |
5.0 | 3.5 | 1.6 | 0.6 | 0.0 |
5.1 | 3.8 | 1.9 | 0.4 | 0.0 |
4.8 | 3.0 | 1.4 | 0.3 | 0.0 |
5.1 | 3.8 | 1.6 | 0.2 | 0.0 |
4.6 | 3.2 | 1.4 | 0.2 | 0.0 |
5.3 | 3.7 | 1.5 | 0.2 | 0.0 |
5.0 | 3.3 | 1.4 | 0.2 | 0.0 |
7.0 | 3.2 | 4.7 | 1.4 | 1.0 |
6.4 | 3.2 | 4.5 | 1.5 | 1.0 |
6.9 | 3.1 | 4.9 | 1.5 | 1.0 |
5.5 | 2.3 | 4.0 | 1.3 | 1.0 |
6.5 | 2.8 | 4.6 | 1.5 | 1.0 |
5.7 | 2.8 | 4.5 | 1.3 | 1.0 |
6.3 | 3.3 | 4.7 | 1.6 | 1.0 |
4.9 | 2.4 | 3.3 | 1.0 | 1.0 |
6.6 | 2.9 | 4.6 | 1.3 | 1.0 |
5.2 | 2.7 | 3.9 | 1.4 | 1.0 |
5.0 | 2.0 | 3.5 | 1.0 | 1.0 |
5.9 | 3.0 | 4.2 | 1.5 | 1.0 |
6.0 | 2.2 | 4.0 | 1.0 | 1.0 |
6.1 | 2.9 | 4.7 | 1.4 | 1.0 |
5.6 | 2.9 | 3.6 | 1.3 | 1.0 |
6.7 | 3.1 | 4.4 | 1.4 | 1.0 |
5.6 | 3.0 | 4.5 | 1.5 | 1.0 |
5.8 | 2.7 | 4.1 | 1.0 | 1.0 |
6.2 | 2.2 | 4.5 | 1.5 | 1.0 |
5.6 | 2.5 | 3.9 | 1.1 | 1.0 |
5.9 | 3.2 | 4.8 | 1.8 | 1.0 |
6.1 | 2.8 | 4.0 | 1.3 | 1.0 |
6.3 | 2.5 | 4.9 | 1.5 | 1.0 |
6.1 | 2.8 | 4.7 | 1.2 | 1.0 |
6.4 | 2.9 | 4.3 | 1.3 | 1.0 |
6.6 | 3.0 | 4.4 | 1.4 | 1.0 |
6.8 | 2.8 | 4.8 | 1.4 | 1.0 |
6.7 | 3.0 | 5.0 | 1.7 | 1.0 |
6.0 | 2.9 | 4.5 | 1.5 | 1.0 |
5.7 | 2.6 | 3.5 | 1.0 | 1.0 |
5.5 | 2.4 | 3.8 | 1.1 | 1.0 |
5.5 | 2.4 | 3.7 | 1.0 | 1.0 |
5.8 | 2.7 | 3.9 | 1.2 | 1.0 |
6.0 | 2.7 | 5.1 | 1.6 | 1.0 |
5.4 | 3.0 | 4.5 | 1.5 | 1.0 |
6.0 | 3.4 | 4.5 | 1.6 | 1.0 |
6.7 | 3.1 | 4.7 | 1.5 | 1.0 |
6.3 | 2.3 | 4.4 | 1.3 | 1.0 |
5.6 | 3.0 | 4.1 | 1.3 | 1.0 |
5.5 | 2.5 | 4.0 | 1.3 | 1.0 |
5.5 | 2.6 | 4.4 | 1.2 | 1.0 |
6.1 | 3.0 | 4.6 | 1.4 | 1.0 |
5.8 | 2.6 | 4.0 | 1.2 | 1.0 |
5.0 | 2.3 | 3.3 | 1.0 | 1.0 |
5.6 | 2.7 | 4.2 | 1.3 | 1.0 |
5.7 | 3.0 | 4.2 | 1.2 | 1.0 |
5.7 | 2.9 | 4.2 | 1.3 | 1.0 |
6.2 | 2.9 | 4.3 | 1.3 | 1.0 |
5.1 | 2.5 | 3.0 | 1.1 | 1.0 |
5.7 | 2.8 | 4.1 | 1.3 | 1.0 |
6.3 | 3.3 | 6.0 | 2.5 | 2.0 |
5.8 | 2.7 | 5.1 | 1.9 | 2.0 |
7.1 | 3.0 | 5.9 | 2.1 | 2.0 |
6.3 | 2.9 | 5.6 | 1.8 | 2.0 |
6.5 | 3.0 | 5.8 | 2.2 | 2.0 |
7.6 | 3.0 | 6.6 | 2.1 | 2.0 |
4.9 | 2.5 | 4.5 | 1.7 | 2.0 |
7.3 | 2.9 | 6.3 | 1.8 | 2.0 |
6.7 | 2.5 | 5.8 | 1.8 | 2.0 |
7.2 | 3.6 | 6.1 | 2.5 | 2.0 |
6.5 | 3.2 | 5.1 | 2.0 | 2.0 |
6.4 | 2.7 | 5.3 | 1.9 | 2.0 |
6.8 | 3.0 | 5.5 | 2.1 | 2.0 |
5.7 | 2.5 | 5.0 | 2.0 | 2.0 |
5.8 | 2.8 | 5.1 | 2.4 | 2.0 |
6.4 | 3.2 | 5.3 | 2.3 | 2.0 |
6.5 | 3.0 | 5.5 | 1.8 | 2.0 |
7.7 | 3.8 | 6.7 | 2.2 | 2.0 |
7.7 | 2.6 | 6.9 | 2.3 | 2.0 |
6.0 | 2.2 | 5.0 | 1.5 | 2.0 |
6.9 | 3.2 | 5.7 | 2.3 | 2.0 |
5.6 | 2.8 | 4.9 | 2.0 | 2.0 |
7.7 | 2.8 | 6.7 | 2.0 | 2.0 |
6.3 | 2.7 | 4.9 | 1.8 | 2.0 |
6.7 | 3.3 | 5.7 | 2.1 | 2.0 |
7.2 | 3.2 | 6.0 | 1.8 | 2.0 |
6.2 | 2.8 | 4.8 | 1.8 | 2.0 |
6.1 | 3.0 | 4.9 | 1.8 | 2.0 |
6.4 | 2.8 | 5.6 | 2.1 | 2.0 |
7.2 | 3.0 | 5.8 | 1.6 | 2.0 |
7.4 | 2.8 | 6.1 | 1.9 | 2.0 |
7.9 | 3.8 | 6.4 | 2.0 | 2.0 |
6.4 | 2.8 | 5.6 | 2.2 | 2.0 |
6.3 | 2.8 | 5.1 | 1.5 | 2.0 |
6.1 | 2.6 | 5.6 | 1.4 | 2.0 |
7.7 | 3.0 | 6.1 | 2.3 | 2.0 |
6.3 | 3.4 | 5.6 | 2.4 | 2.0 |
6.4 | 3.1 | 5.5 | 1.8 | 2.0 |
6.0 | 3.0 | 4.8 | 1.8 | 2.0 |
6.9 | 3.1 | 5.4 | 2.1 | 2.0 |
6.7 | 3.1 | 5.6 | 2.4 | 2.0 |
6.9 | 3.1 | 5.1 | 2.3 | 2.0 |
5.8 | 2.7 | 5.1 | 1.9 | 2.0 |
6.8 | 3.2 | 5.9 | 2.3 | 2.0 |
6.7 | 3.3 | 5.7 | 2.5 | 2.0 |
6.7 | 3.0 | 5.2 | 2.3 | 2.0 |
6.3 | 2.5 | 5.0 | 1.9 | 2.0 |
6.5 | 3.0 | 5.2 | 2.0 | 2.0 |
6.2 | 3.4 | 5.4 | 2.3 | 2.0 |
5.9 | 3.0 | 5.1 | 1.8 | 2.0 |
Để thuận tiện cho việc minh họa trực quan, chúng ta sẽ chỉ dùng 2 đặc trưng đầu từ IRIS dataset. Phương pháp đơn giản để giải quyết bài toán multi-class classification là dùng softmax regression. Softmax regression và logistic regression tương đối giống nhau, ngoại trừ hai điểm sau.
– Softmax regression có số node output bằng với số class của bài toán
– Softmax regression dùng hàm softmax (thay vì hàm sigmoid trong logistic regression)
Hàm softmax
Đầu vào của hàm softmax là một vector các giá trị số thực và cho ra các giá trị thuộc khoảng (0,1). Tổng các giá trị đầu ra của hàm softmax là 1. Gọi o là giá trị output (\(o = X \cdot W\); o là vector có độ dài N) được tính tương tự theo bài toán linear regression, giá trị softmax cho output \(o_i\) được tính như sau
$$
p_i = softmax(o_i) = \frac{e^{o_i}}{\sum_{k=1}^N e^{o_k} }
$$
Sau khi tính softmax cho output o, softmax regression trả về một vector các giá trị nằm trong khoảng (0, 1). Input X được phân loại vào class \(i\) có giá trị p_i lớn nhất.
Đạo hàm của hàm softmax có dạng sau
$$
\frac{\partial p_i}{\partial o_j} = \left\{\begin{matrix}
p_i(1 – p_j) & i = j\\
– p_j\cdot p_i & i \neq j
\end{matrix}\right.
$$
Source code cho hàm softmax
def softmax(X): exps = np.exp(X) return exps / np.sum(exps)
Cross Entropy Loss
Cross entropy thường đi cùng với hàm softmax để tính loss. Gọi p là vector được tình từ hàm softmax và y là label ở dạng one-hot encoding. Giá trị loss L được tính như sau
$$
L = H(y,p) = -\sum_i y_ilog(p_i)
$$
Đạo hàm của L theo \(o_i\) có dạng sau
$$
\frac{\partial L}{\partial o_i} = p_i – y_i
$$
Chứng minh công thức đạo hàm của L theo \(o_i\) như sau
$$
\frac{\partial L}{\partial o_i}=-\sum_ky_k\frac{\partial \log p_k}{\partial o_i}\\
\,\,\,\,\,\,=-\sum_ky_k\frac{1}{p_k}\frac{\partial p_k}{\partial o_i}\\
\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,=-y_i(1-p_i)-\sum_{k\neq i}y_k\frac{1}{p_k}({-p_kp_i})\\
\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,=-y_i(1-p_i)+\sum_{k\neq i}y_k({p_i})\\
\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,=-y_i+y_ip_i+\sum_{k\neq i}y_k({p_i})\\
\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,=p_i\left(\sum_ky_k\right)-y_i=p_i-y_i
$$
Source code cho hàm cross entropy
def cross_entropy(X,y): m = y.shape[0] p = softmax(X) log_likelihood = -np.log(p[range(m),y]) loss = np.sum(log_likelihood) / m return loss
Áp dụng softmax regression cho bài toán phân loại hoa Iris
Bộ dữ liệu Iris có 150 mẫu dữ liệu cho 3 loài hoa, và có 4 đặc trưng. Trong phần này, chúng ta sẽ sử dụng 2 đặc trưng ở cột 3 và 4 để phân loại 3 loài hoa Iris. Source code để đọc bộ dữ liệu Iris và hiển thị như sau
import numpy as np import matplotlib.pyplot as plt from sklearn import preprocessing iris = np.genfromtxt('iris_full.csv', dtype=None, delimiter=',', skip_header=1) X = iris[:, 2:4] y = iris[:, 4] X = preprocessing.scale(X) y = y.astype('uint8') plt.figure(figsize=(10, 6)) plt.scatter(X[y == 0][:, 0], X[y == 0][:, 1], color='b', label='0') plt.scatter(X[y == 1][:, 0], X[y == 1][:, 1], color='r', label='1') plt.scatter(X[y == 2][:, 0], X[y == 2][:, 1], color='g', label='2') plt.legend()
Chú ý là chúng ta chỉ dùng 2 đặc trưng ở cột dữ liệu thứ 3 và 4. Do đó, vector đặc trưng X
có shape là (150, 2)
. Sau đó, X được chuẩn hóa dùng hàm scale()
.
Kết quả hiện thị dữ liệu Iris sau khi được chuẩn hóa như sau.
Source code để huấn luyện softmax regression như sau
N = 50 # number of points per class D = 2 # dimensionality K = 3 # number of classes # initialize parameters randomly W = 0.01 * np.random.randn(D,K) b = np.zeros((1,K)) # gradient descent loop num_examples = X.shape[0] learning_rate = 0.05 losses = [] for i in range(1000): # evaluate class scores scores = np.dot(X, W) + b # compute the class probabilities exp_scores = np.exp(scores) probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True) # compute the loss: average cross-entropy loss and regularization corect_logprobs = -np.log(probs[range(num_examples),y]) loss = np.sum(corect_logprobs)/num_examples if i % 5 == 0: losses.append(loss) # compute the gradient on scores dscores = probs dscores[range(num_examples),y] -= 1 dscores /= num_examples # backpropate the gradient to the parameters (W,b) dW = np.dot(X.T, dscores) db = np.sum(dscores, axis=0, keepdims=True) # perform a parameter update W += -learning_rate * dW b += -learning_rate * db
Ở đây, softmax regression được huấn luyện với 1000 epoch
và learning_rate = 0.05
. Giá trị loss được lưu sau 5 epoch. Hình sau hiển thị giá trị loss giảm qua quá trình huấn luyện
Chúng ta có thể tính độ chính xác bằng cách so sánh kết quả phân loại với label y như sau
Để có cái nhìn trực quan hơn về kết quả phân loại, chúng ta có thể hiển thị miền phân loại như sau
h = 0.01 x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) Z = np.dot(np.c_[xx.ravel(), yy.ravel()], W) + b Z = np.argmax(Z, axis=1) Z = Z.reshape(xx.shape) fig = plt.figure() plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral, alpha=0.8) plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.Spectral) plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max())
Kết quả miền phân loại