Trong Bài
5, chúng là đã thảo luận thuật toán Simple Linear Regression. Thuật toán Linear
Regression đó chỉ phụ thuộc vào một biến độc lập để dự đoán cho một biến phụ
thuộc khác. Trong Bài 6, chúng ta sẽ tìm hiểu và cài đặt thuật toán Multiple Linear
Regression. Thuật toán này phụ thuộc vào hai hay nhiều biến độc lập để dự đoán
cho một biến phụ thuộc khác.
Sau bài học này, người học có khả năng:
·
Tìm hiểu
bài toán và dữ liệu
·
Cài đặt
thuật toán Gradient descent
·
Sử dụng
thư viện scikit-learn
6.1 Bài toán và dữ liệu
Trong bài này chúng ta sẽ tìm hiểu dữ liệu được thu thập có 2
biến độc lập là: diện tích của ngôi nhà (Size - tính bằng feet2),
cùng số phòng ngủ (Bedrooms); và một biến phụ thuộc đó là giá của ngôi nhà
(Price – tính bằng USD) tương ứng được bán (dữ liệu lấy từ [1], có thể download từ [2]). Người ta muốn đoán giá của ngôi nhà
thông qua thông tin thu thập được: diện tích và số phòng ngủ.
Chương trình 6.1
không khác ở Bài 5, ngoại trừ dòng 04 và 05:
01. import pandas as pd 02. import numpy as np 03. import os 04. from matplotlib import pyplot 05. duongDan = os.getcwd() + '\data\ex1data2.txt' 06. tenCot = ['Size', 'Bedrooms', 'Price'] 07. duLieu = pd.read_csv(duongDan, names= tenCot) 08. print (duLieu.shape) 09. print (duLieu.head()) |
Chương
trình 6.1
Thông tin dữ liệu chúng ta có được như sau:
(47, 3)
Size Bedrooms
Price
0 2104 3 399900
1 1600 3 329900
2 2400 3 369000
3 1416 2 232000
4 3000 4 539900
Vậy chúng ta biết dữ liệu gồm có 47 hàng và 3 cột (Size,
Bedrooms, và Price). Chúng ta cũng biết
thêm rằng giá trị trên cột Bedrooms rất khác so với các giá trị trên cột Size,
và cả hai cột đầu có giá trị rất khác so với cột Price.
duLieu.plot(kind='box', subplots=True, layout=(2,2), sharex=False, sharey=False) pyplot.show() |
Chúng ta có biểu đồ (giống như Hình 6.1)
Hình 6.1 Đồ thị dữ liệu cho diện tích, số phòng
ngủ và giá của một ngôi nhà.
Chúng ta thấy khoảng giá trị của từng cột là rất khác nhau, với
dữ liệu cột Bedrooms ở trong đoạn [1,5], với cột Size khoảng từ 800 tới 3200, với
cột Price trong khoảng từ 170.000 tới 580.000.
Chính vì sự khác biệt
lớn này, nên nếu chúng ta không xử lý dữ liệu, thuật toán sẽ gặp vấn đề lớn.
6.2 Thuật toán Gradient
descent
Chương trình không khác gì ở Bài 5, ngoại trừ
chúng ta cho số lần lặp là soLanLap = 10:
01. maTran = duLieu.values 02. m,n = maTran.shape 03. X_cacCot = maTran[:,0:n-1] 04. X = np.insert(X_cacCot, 0, values = 1, axis = 1) 05. y = maTran[:,n-1:n] 06. print X[:5] 07. print y[:5] 08. theta = np.zeros((1, X.shape[1])) 09. print theta 10. print X.shape, y.shape, theta.shape 11. def h_X(X, theta): 12. return np.dot(X, theta.T) 13. def computeCost(X, y, theta): 14. saiSo = np.power((h_X(X, theta) - y),2) 15. J = (1.0/(2 * m)) * np.sum(saiSo) 16. return J 17. print computeCost(X, y, theta) 18. def gradientDescent(X, y, theta, alpha, soLanLap): 01. theta_tam = np.zeros(theta.shape) 19. heso_Theta = theta.shape[1] 20. J_tam = np.zeros(soLanLap) 21. for i in range(soLanLap): 22. saiSo = h_X(X,theta) - y 23. for j in range(heso_Theta): 24. X_ij = np.reshape(X[:, j],(len(X),1)) 25. term = np.multiply(saiSo, X_ij) 26. theta_tam[0, j] = theta[0, j] - ((alpha / len(X)) * np.sum(term)) 27. theta = theta_tam 28. J_tam[i] = computeCost(X, y, theta) 29. return theta, J_tam 30. alpha = 0.01 31. soLanLap = 10 32. theta_sauCung, J_chiphi = gradientDescent(X, y, theta, alpha, soLanLap)
33. print theta_sauCung 34. print J_chiphi[-1] |
Chương trình 6.2
Khi chạy chương trình 6.2 sẽ cho kết quả:
[[ 1 2104 3]
[ 1 1600
3]
[ 1 2400
3]
[ 1 1416
2]
[ 1 3000
4]]
[[399900]
[329900]
[369000]
[232000]
[539900]]
[[ 0. 0. 0.]]
(47, 3) (47, 1) (1, 3)
65591548106.5
[[ -3.17739580e+45 -7.33861634e+48 -1.05993953e+46]]
1.24428862154e+104
Kết quả lần lượt in ra 5 dòng đầu của X, y, theta (khởi tạo) cùng kích thước của
chúng. Thật đáng ngạc nhiên khi dòng 17 cho kết quả một con số rất lớn. Với giá
trị khởi tạo, hàm chi phí của chúng ta lên tới xấp xỉ 65 tỉ. Và sau 10 vòng lặp,
trị giá của theta một con số không tưởng, và hàm chi phí khoảng 1.24.10104.
Chúng ta có thể cho rằng do hệ số theta chưa hội
tụ sau số lần lặp ít như vậy. Tuy nhiên khi càng tăng số lần lặp lên, con số dự
đoán lại càng lớn hơn. Khi thử với soLanLap từ 50 trở đi, giá trị dự đoán vượt
cả giới hạn số mà Python sử dụng.
Nguyên nhân vì sao? Như chúng ta đã quan sát dữ
liệu ở phần 6.1: có sự chênh lệch rất lớn giữa giá trị và tỉ lệ giữa các cột.
Chính điều này làm thuật toán của chúng ta không hội tụ (càng lặp nhiều, càng
phân tán).
Vậy thì
ta cần điều chuẩn hóa dữ liệu. Trong bài này ta dùng kĩ thuật chuẩn hóa dữ liệu
Standardization. Bằng cách thêm vào dòng lệnh:
duLieu = (duLieu - duLieu.mean())/duLieu.std() |
vào trước dòng lệnh 01
trong Chương trình 6.2 trên. Sau đó chạy chương trình thì kết quả in ra sẽ là
(với soLanLap = 1000):
[[ 1.
0.13000987 -0.22367519]
[ 1. -0.50418984 -0.22367519]
[ 1. 0.50247636 -0.22367519]
[ 1. -0.73572306 -1.53776691]
[ 1. 1.25747602 1.09041654]]
[[ 0.47574687]
[-0.08407444]
[ 0.22862575]
[-0.86702453]
[ 1.59538948]]
[[ 0. 0. 0.]]
(47, 3) (47, 1) (1, 3)
0.489361702128
[[ -1.10963248e-16 8.78503652e-01 -4.69166570e-02]]
0.130703369608
Như chúng ta thấy, giá trị của theta ở ngưỡng
phù hợp (θ = [θ0 θ1 θ2] = [0 0.8785
-0.0469]), và chi phí sau 1000 lần lặp là 0.131.
Chúng ta sử dụng lại Chương trình 5.5, ta sẽ có
đồ thị của hàm chi phí ứng với số lần lăp:
Hình 6.2 Hàm chi phí biến đổi sau các bước lặp
của thuật toán.
Nhìn vào đồ thị chúng ta thấy rằng không có sự
thay đổi nhiều từ bước lặp 500 trở đi. Nói một cách khác, sau 500 vòng lặp,
theta của chúng ta đã hội tụ.
Và khi chúng ta thay soLanLap = 500 thì kết quả
cho theta và hàm chi phí là:
[[ -1.24238681e-16
8.30383883e-01 8.23982853e-04]]
0.131951337758
Kết quả rất gần với kết quả sau 1000 lặp ở phía
trên.
6.3 Kết luận
Cần bổ sung vào đây.
Bài
tập:
Bạn thử áp dụng các kĩ thuật điều chỉnh dữ liệu khác trong
Bài 4 để áp dụng vào Bài 6 này xem kết quả khác nhau như thế nào?
Tài liệu tham khảo:
2. https://github.com/alexband/ml-class/blob/master/mlclass-ex1/ex1data2.txt
0 nhận xét:
Đăng nhận xét