01/10/2018, 12:36

Thắc mắc về Code Hiển thị dữ liệu trên đồ thị (K-Means)

Mình đang học về K-Means, và thắc mắc code một tí, mong anh em giải thích giúp:

#Trước tiên, chúng ta cần khai báo các thư viện cần dùng. Chúng ta cần numpy và matplotlib như trong bài Linear Regression cho việc tính toán ma trận và hiển thị dữ liệu. Chúng ta cũng cần thêm thư viện scipy.spatial.distance để tính khoảng cách giữa các cặp điểm trong hai tập hợp một cách hiệu quả.

import numpy as np 
import matplotlib.pyplot as plt
from scipy.spatial.distance import cdist
np.random.seed(11)

#Tiếp theo, ta tạo dữ liệu bằng cách lấy các điểm theo phân phối chuẩn có kỳ vọng tại các điểm có tọa độ (2, 2), (8, 3) và (3, 6), ma trận hiệp phương sai giống nhau và là ma trận đơn vị. Mỗi cluster có 500 điểm. (Chú ý rằng mỗi điểm dữ liệu là một hàng của ma trận dữ liệu.

means = [[2, 2], [8, 3], [3, 6]]
cov = [[1, 0], [0, 1]]
N = 500
X0 = np.random.multivariate_normal(means[0], cov, N)
X1 = np.random.multivariate_normal(means[1], cov, N)
X2 = np.random.multivariate_normal(means[2], cov, N)
X = np.concatenate((X0, X1, X2), axis = 0)
K = 3
original_label = np.asarray([0]*N + [1]*N + [2]*N).T

#Hiển thị dữ liệu trên đồ thị
#Chúng ta cần một hàm kmeans_display để hiển thị dữ liệu. Sau đó hiển thị dữ liệu theo nhãn ban đầu.

def kmeans_display(X, label):
    K = np.amax(label) + 1
    X0 = X[label == 0, :]#Ý nghĩa của dòng này là gì?
    X1 = X[label == 1, :]#Ý nghĩa của dòng này là gì?
    X2 = X[label == 2, :]#Ý nghĩa của dòng này là gì?
    
    plt.plot(X0[:, 0], X0[:, 1], 'b^', markersize = 4, alpha = .8)
    plt.plot(X1[:, 0], X1[:, 1], 'go', markersize = 4, alpha = .8)
    plt.plot(X2[:, 0], X2[:, 1], 'rs', markersize = 4, alpha = .8)

    plt.axis('equal')
    plt.plot()
    plt.show()
    
kmeans_display(X, original_label)

Các bạn cho mình hỏi ý nghĩa của dòng này là gì?

X0 = X[label == 0, :]#Ý nghĩa của dòng này là gì?
X1 = X[label == 1, :]#Ý nghĩa của dòng này là gì?
X2 = X[label == 2, :]#Ý nghĩa của dòng này là gì?

plt.plot(X0[:, 0], X0[:, 1], 'b^', markersize = 4, alpha = .8)#Ý nghĩa của dòng này là gì?
plt.plot(X1[:, 0], X1[:, 1], 'go', markersize = 4, alpha = .8)#Ý nghĩa của dòng này là gì?
plt.plot(X2[:, 0], X2[:, 1], 'rs', markersize = 4, alpha = .8)#Ý nghĩa của dòng này là gì?

Link về bài viết ở đây: K-means

Hung viết 14:37 ngày 01/10/2018

Gộp 3 ma trân X0, X1, X2 thành X theo chiều ngang

X = np.concatenate((X0, X1, X2), axis = 0)

|-----------X0---------|
|-----------X1---------|
|-----------X2---------|

Khởi tạo vector label có length = 3N, N phần tử đầu là 0, N phần tử ở giữa là 1, N phần tử cuối là 2

original_label = np.asarray([0]*N + [1]*N + [2]*N).T

N = 2
label = [001122]

N = 3
label = [000111222]

Tách ma trân X theo chiều ngang thành 3 ma trận X0, X1, X2 như ban đầu.

X0 = X[label == 0, :]
X1 = X[label == 1, :]
X2 = X[label == 2, :]

Chi tiết, giả sử N = 2, không thực hiện Tranpose

label == 0
[True, True, False, False, False, False]
label == 1
[False, False, True, True, False, False]
label == 2
[False, False, False, False, True, True]

X[ label == 0 , : ]
= X[ [ [True], [True], [False], [False], [False], [False] ], : ]
= X0


Bạn nên đọc Numpy Quick Start để nắm cơ bản các hàm của Numpy
https://docs.scipy.org/doc/numpy/user/quickstart.html

Nguyễn Quang Trí viết 14:38 ngày 01/10/2018

Mình đang bí ở đây:

# check convergence
def has_converged(theta_new, grad):
    return np.linalg.norm(grad(theta_new))/
                            len(theta_new) < 1e-3
#Nếu biết trước điểm đặt bi ban đầu theta, đạo hàm của hàm mất mát tại một điểm bất kỳ grad(theta), lượng thông tin lưu trữ từ vần tốc trước đó gamma và learning rate eta, chúng ta có thể viết hàm số GD_momentum trong Python như sau:
def GD_momentum(theta_init, grad, eta, gamma):
    # Suppose we want to store history of theta
    theta = [theta_init]
    v_old = np.zeros_like(theta_init)
    for it in range(100):
        v_new = gamma*v_old + eta*grad(theta[-1])
        theta_new = theta[-1] - v_new
        if has_converged(theta_new, grad):
            break 
        theta.append(theta_new)
        v_old = v_new
    return theta 
    # this variable includes all points in the path
    # if you just want the final answer, 
    # use `return theta[-1]`

Mình đã thử test_left = GD_momentum(-5, grad(-5), 0.1, 0.9) nhưng bị báo lỗi. Vậy phải khởi tạo grad như thế nào mới đúng?

Link về bài viết ở đây(Phần Gradient Descent với Momentum): Gradient Descent (phần 2/2)

Hung viết 14:45 ngày 01/10/2018

grad là 1 hàm, không phải giá trị.

Trong has_converged():

grad(theta_new)

Trong GD_momentum():

grad(theta[-1])

Test code:

test_left = GD_momentum(-5, grad, 0.1, 0.9)

Đoán vậy.


Ps: Bạn tạo topic mỗi khi có chủ đề mới, như của bạn là: Gradient Descent with Momentum

Nguyễn Quang Trí viết 14:43 ngày 01/10/2018

test_left = GD_momentum(-5, grad, 0.1, 0.9)

Nếu làm như bạn nói thì bị lỗi

test_left = GD_momentum(-5, grad, 0.1, 0.9)
Traceback (most recent call last):

  File "<ipython-input-4-865283ef59bf>", line 1, in <module>
    test_left = GD_momentum(-5, grad, 0.1, 0.9)

  File "<ipython-input-1-f4847616ddf6>", line 41, in GD_momentum
    if has_converged(theta_new, grad):

  File "<ipython-input-1-f4847616ddf6>", line 31, in has_converged
    return np.linalg.norm(grad(theta_new))/len(theta_new) < 1e-3

TypeError: object of type 'numpy.float64' has no len()

Ps: Bạn tạo topic mỗi khi có chủ đề mới, như của bạn là: Gradient Descent with Momentum
Lần sau mình sẽ chú ý:D

Hung viết 14:40 ngày 01/10/2018

Chép dòng này vào Google:

TypeError: object of type 'numpy.float64' has no len()

Sau đó mò bug, được các tài liệu sau: ( từ official docs, không StackOverflow )
np.linalg.norm:
https://docs.scipy.org/doc/numpy-1.9.3/reference/generated/numpy.linalg.norm.html
numpy.float64:
https://docs.scipy.org/doc/numpy-1.13.0/user/basics.types.html

Phần này thuộc kĩ năng fix bug, TypeError là lỗi cơ bản. Nên bạn tìm hiểu thêm nhé, có kèm hướng dẫn ở trên.

Linh viết 14:46 ngày 01/10/2018

tại sao phải sử dụng biến K ?

Bài liên quan
0