[Machine Learning] Linear Regression và ứng dụng cho bài toán dự đoán điểm Nhập môn Lập trình

Chào mừng các bạn đọc đã quay trở lại với chuỗi bài viết về Machine Learning của CLB AI. Ở bài viết trước, chúng ta đã được tìm hiểu và tiếp cận một cách tổng quát về Machine Learning với ba nhóm bài toán chính là Regression, ClassificationClustering. Để giúp bạn đọc hiểu rõ hơn Machine Learning ở góc độ toán học, ở bài viết này chúng ta sẽ cùng tìm hiểu về một thuật toán đơn giản trong bài toán RegressionLinear Regression (Hồi quy tuyến tính). Thông qua bài viết này, bạn sẽ có thể áp dụng kiến thức để xây dựng một mô hình máy học để dự đoán điểm cuối kỳ Nhập môn Lập trình, và sẽ được “nghịch” với nó để xem phong cách “học” của máy là như thế nào.

1.Linear Regression là gì?

Linear Regression (Hồi quy tuyến tính) là một trong những thuật toán cơ bản và phổ biến nhất của Supervised Learning (Học có giám sát), trong đó đầu ra dự đoán là liên tục. Thuật toán này thích hợp để dự đoán các giá trị đầu ra là các đại lượng liên tục như doanh số hay giá cả thay vì cố gắng phân loại chúng thành các đại lượng rời rạc như màu sắc và chất liệu của quần áo, hay xác định đối tượng trong một bức ảnh là mèo hay chó, …

Thử lấy ví dụ sau: bạn đang có điểm thành phần về các môn như Nhập môn lập trình, OOP, Giải tích,… và điều bạn đang cần là tính ra điểm trung bình cuối kỳ của mình. Rất đơn giản, bạn sẽ tính được chứ? Tất nhiên rồi! Bạn chỉ cần áp công thức tính điểm trung bình vào là ra. Tiếp tục, bạn lại muốn khảo sát, thống kê lại xem điểm thi giữa kỳ Nhập môn lập trình ảnh hưởng như thế nào đến điểm cuối kỳ của các bạn trong lớp, bạn muốn xác định xem quan hệ giữa điểm thành phần và điểm cuối kỳ thì phải làm sao? Đây có lẽ là một bài toán khó đối với những bạn chưa từng làm việc với Máy học hoặc Thống kê, tuy nhiên cũng đừng vội lo lắng, hãy cùng nhau khám phá và giải quyết các thắc mắc trong bài viết này nhé!

Trong Linear Regression chúng ta sẽ gặp hai loại bài toán đó là Hồi quy đơn biếnHồi quy đa biến. Để đơn giản thuật toán, chúng ra sẽ tìm hiểu và phân tích kỹ toán học của bài hồi quy đơn biến. Vậy hồi quy tuyến tính đơn biến là gì? Univariate Linear Regression (hồi quy tuyến tính đơn biến) chính là mối quan hệ giữa hai biến số liên tục trên trục hoành \(x\) và trên trục tung \(y\). Phương trình hồi quy tuyến tính đơn biến có dạng như phương trình đường thẳng \( y = ax + b \) với \(x\) là biến độc lập và \(y\) là biến phụ thuộc vào \(x\). Đối với Hồi quy tuyến tính đa biến, bạn có thể hiểu một cách đơn giản là sẽ có nhiều biến độc lập \(x_1, x_2, \dots, x_n\) và nhiều hệ số \(a_1, a_2, \dots, a_n\) thay vì chỉ một biến \(x\) duy nhất.

2. Một vài ký hiệu cần lưu ý và cách xác định input và output của bài toán.

Tổng quát hơn, trong supervised learning (học có giám sát), chúng ta có một bộ dữ liệu và bộ dữ liệu này gọi là training set (tập huấn luyện)

Giả sử chúng ta có bộ dữ liệu thống kê điểm giữa kỳ và điểm cuối kỳ trong Nhập môn lập trình. Khi đó, với bài toán hồi quy đơn biến này, cần tìm ra một mô hình nhận vào input là điểm giữa kỳ và output ra dự đoán điểm cuối kỳ hợp lí nhất dựa trên mối quan hệ giữa hai cột điểm mà mô hình đó tìm được.

Điểm giữa kỳĐiểm cuối kỳ
4.003.98
6.005.5
8.757.8
6.705.9
7.708.6

Bảng 1: Thống kê điểm NMLT của sinh viên trong một lớp.

Để dễ dàng, ta sẽ thống nhất sử dụng một vài ký hiệu sau xuyên suốt bài viết này: 

  • \(m\): Đại diện số lượng các training example (mẫu huấn luyện). Giả  sử, chúng ta có 40 dòng điểm cuối kỳ khác nhau được thu thập dựa trên điểm giữa kỳ tương ứng. Như vậy, ta có 40 mẫu huấn luyện và m bằng 40. 
  • \(x\): Để ký hiệu các input variable (biến đầu vào) cũng thường được gọi là các feature (đặc trưng). Trong hồi quy đa biến, \(x\) là một vector nhưng trong ví dụ này, \(x\) là số điểm đánh giá trong nửa học kỳ đầu – là một con số trong hồi quy đơn biến.
  • \(y\): Để ký hiệu các biến đầu ra hay các biến mục tiêu , ở đây là điểm cuối kỳ tương ứng.
  • \((x,y)\): đại diện một mẫu huấn luyện – training example. 
  • \(x^{(i)}, y^{(i)}\): dùng để chỉ một mẫu huấn luyện cụ thể. Giả sử, với \(i = 3\) tương ứng ta có điểm dữ liệu \(x^{(3)}, y^{(3)}\) : Số điểm cuối kỳ của bạn có thể là bao nhiêu khi điểm giữa kỳ là 8.75? Dựa vào bảng số liệu trên, tại \(y^{(3)}\), kết quả dự đoán đạt giá trị là 7.8. 

Chúng ta đã học phương trình đường thẳng \(y = ax + b\) ở bậc trung học phổ thông và hàm h – hypothesis (giả thuyết) cũng được biểu diễn tương tự cho mô hình hồi quy tuyến tính đơn biến. Nó cũng sẽ lấy giá trị đầu vào là x và cho ra kết quả đầu ra là y nhưng chỉ thay đổi các thông số a và b thành \(\theta_0 = b\) và \(\theta_1 = a\).

Khi đó về mặt toán học, \(h\) là một ánh xạ từ \(x\) sang \(y\):

y = h(x) = h_{\theta} (x) = b + ax = \theta_0 + \theta_1 x

3. Bài toán dự đoán điểm trung bình Nhập môn lập trình 

Nguồn ảnh: NakedCode

Bây giờ, chúng ta hãy đi sâu hơn về việc giải quyết các vấn đề hồi quy đơn biến. Nhìn vào các training example (mẫu huấn luyện) được đưa ra trong hình dưới đây.

Hình 1

Vậy điều gì sẽ xảy ra khi bạn cần ước lượng số điểm chính xác nhất khi đạt 7.00 điểm giữa kỳ từ thông tin trên? Hướng tiếp cận đơn giản nhất là tìm một đường thẳng (*) phù hợp với  tập dữ liệu và vẽ một đường thẳng từ vị trí 7 điểm trên trục x cho đến khi nó chạm vào đường thẳng(*) vừa tìm?

Hình 2

Hãy quan sát hình trên , từ hai mẫu (4.00, 3.98) và (6.00, 5.5), ta vẽ được đường thẳng màu đỏ và từ đó tìm được hai giá trị \(\theta_0\) và \(\theta_1\) lần lượt là 0.76 0.94 . Bây giờ, chúng ta có thể sử dụng hàm giả thuyết để dự đoán điểm cuối kỳ dựa trên điểm giữa kỳ tương ứng với giá trị 7.00 như sau: \(h(x) =  0.76x + 0.94 = 0.76*7 +0.94 = 6.26\) điểm – giá trị ước tính tương ứng với đường thẳng này. 

Tuy nhiên, trong thực tế các bộ dữ liệu đưa vào huấn luyện mô hình nhiều hơn gấp trăm, gấp ngàn lần và số lượng các đặc trưng cũng chênh lệch đáng kể, việc xác định hàm tuyến tính trở nên khó khăn hơn. Sự xuất hiện của các vấn đề trên là tiền đề để máy học ra đời, tạo ra nhiều thuật toán phục vụ cho mọi người như áp dụng thuật toán hồi quy tuyến tính và SVM (Support Vector Machine) trong phân tích chứng khoán hay nhận dạng giọng nói bằng mô hình Markov, …

Hàm giả thuyết ở trên được xây dựng tốt hay chưa? Làm sao để hàm đó trở nên phù hợp nhất có thể? Làm thế nào bạn nhận định được điều đó? Nhờ đó hàm mất mát được tạo ra, hàm sẽ giúp bạn tính khoảng cách giữa kết quả mà hàm giả thuyết h dự đoán được so với giá trị thực sự mà ta quan sát thấy.

Hình 3: Xây dựng hàm mất mát  

Khi bạn có giá trị dự đoán là 6.26 và giá trị thực là 6.00 chúng có ý nghĩa gì? Hàm mất mát sẽ cho bạn biết sự chênh lệch giữa thực tế và giả thuyết và khi giá trị hàm này càng nhỏ, dự đoán của bạn lại càng chính xác và càng phù hợp! Bạn có mong muốn hàm mất mát đưa ra giá trị nhỏ nhất không? Đối với hồi quy tuyến tính, bạn có thể tính bình phương độ sai lệch để đánh giá sự chênh lệch giữa giá trị đưa ra bởi hàm giả thuyết và giá trị thực tế  đo đạc được:

\mathcal{L}(\theta_0 , \theta_1) = \frac{1}{2m} * \sum_{i=1}^{m} [y^{(i)} – h_\theta(x^{(i)})]^2 \\ = \frac{1}{2m} * \sum_{i=1}^{m} [y^{(i)} – (\theta_0 + \theta_1x^{(i)})]^2

Dưới đây là demo code của hàm mất mát của bài toán tính điểm cuối kỳ:

def loss_univariate(X, y, theta_0, theta_1):
     h = theta_0 + theta_1 * X
     m = len(X)
     loss = 1/(2*m) * np.sum((y - h) ** 2)
     return loss

Từ mô hình dữ liệu hình 1, ta thu được hàm giả thuyết từ điểm giữa kỳ sang điểm cuối kỳ :

h(x) = cuoiky = \theta_0 + giuaky *\theta_1 = \theta_0 + \theta_1 x

Với bài toán một biến, cách giải sẽ đơn giản hơn nhiều, khi ấy hàm mất mát có giá trị:

\mathcal{L} = \frac{1}{2m} * [(y^{(1)} – x^{(1)} \theta_1 – \theta_0)^2 + … + (y^{(m)} – x^{(m)} \theta_1 – \theta_0)^2]

Mục tiêu của chúng ta là tối ưu hay còn gọi là đi tìm điểm cực tiểu của hàm \(\mathcal{L}\) bên trên. Vì đây là một hàm số hai biến nên trước khi muốn tìm cực tiểu thì chúng ta cùng ôn tập lại kiến thức của môn giải tích hồi năm nhất nhé ;). Để tìm cực trị của một hàm số 2 biến \(f(x, y)\), ta giải hệ phương trình đạo hàm một phía sau:

\begin{cases} f’_x(x, y) = 0 \\ f’_y(x, y) = 0 \end{cases}
Hình 3: Đồ thị hàm mất mát

Mặc dù lúc trước, khi học môn giải tích, để xác định xem nghiệm của hệ phương trình này là điểm cực tiểu, cực đại hay điểm yên ngựa (điểm không phải cực tiểu cũng không phải cực đại) của hàm \(f(x, y)\), chúng ta còn phải tính \( f’_{xx}(x, y), f’_{yy}(x, y), \) và \(f’_{xy}(x, y)\) và biện luận từng nghiệm, tuy nhiên vì hàm \(\mathcal{L}\) ở đây là hàm số bậc 2, tức là nó có hình dạng như một parabol với một điểm cực tiểu duy nhất (Hình 3) nên nghiệm của hệ phương trình đạo hàm cũng chính là điểm cực tiểu của hàm số \(\mathcal{L}\). Tiếp thu kiến thức kỳ quái này, ta áp dụng vào việc tìm cực tiểu của hàm mất mát như sau:

\mathcal{L}’_{\theta_0} = \frac{1}{m}*[(y^{(1)} – x^{(1)} \theta_1 – \theta_0)(-1) + … + (y^{(m)} – x^{(m)} \theta_1 – \theta_0)*(-1)] = 0
\Leftrightarrow \theta_0 + \theta_1 * \frac{(x^{(1)} + … + x^{(m)})}{m} = \frac{(y^{(1)} + … + y^{(m)})}{m}

\mathcal{L}_{\theta_1} = \frac{1}{m}[(y^{(1)} – x^{(1)} \theta_1 – \theta_0)(-x^{(1)}) + … + (y^{(m)} – x^{(m)} \theta_1 – \theta_0)(-x^{(m)})] = 0
\Leftrightarrow \theta_0 * \frac{(x^{(1)} + … + x^{(m)})}{m} + \theta_1 * \frac{((x^{(1)})^2 + … + (x^{(m)})^2)}{m} = \frac{(y^{(1)}x^{(1)} + … + y^{(m)}x^{(m)})}{m}

Từ hai kết quả đạo hàm trên, ta giải hệ phương trình và tìm thu được kết quả hai tham số θ0θ1 :

\Leftrightarrow \begin{cases} \theta_0 = \frac{(y^{(1)} + … + y^{(m)}) – \theta_1(x^{(1)} + … + x^{(m)})}{m}\\ \theta_1 = \frac{m(y^{(1)}x^{(1)} + … + y^{(m)}x^{(m)}) – (y^{(1)} + … + y^{(m)})(x^{(1)} + … + x^{(m)})}{m((x^{(1)})^2 + … + (x^{(m)})^2) – (x^{(1)} + … + x^{(m)})^2} \end{cases}

Chúng ta sẽ tính toán các giá trị trong phương trình thông qua thư viện thông dụng trong Machine Learning là Numpy, bước quan trọng nhất trong mô hình Linear Regression là đi tìm nghiệm cho bài toán. Chúng ta giải hệ phương trình của bài toán đơn biến như sau:

m = len(X)
x_sum = np.sum(X)
y_sum = np.sum(y)
xy_sum = np.sum(X*y)
x2_sum = np.sum(X**2)

theta_1 = (m*xy_sum - x_sum*y_sum) / (m*x2_sum - x_sum**2)

theta_0 = (y_sum - theta_1*x_sum)/m

print('theta_0 =', theta_0)
print('theta_1 =', theta_1)
theta_0 = 0.9221372438499396
theta_1 = 0.7202378471295553 

Khi đã có giá trị hai tham số, chúng ta không chỉ có thể tính điểm cuối kỳ mà còn biểu diễn các giá trị dưới dạng đồ thị

# Tính điểm cuối kỳ theo theta
y_pred = theta_0 + theta_1*x1

# Biểu diễn trên đồ thị
plt.scatter(x1,x2)
plt.plot(x1,y_pred.T, 'r')
Hình 2
loss_univariate(X, y, theta_0, theta_1)
0.27319262900804736 

Từ đồ thị trên, ta thấy các điểm dữ liệu màu xanh khá gần với đường thẳng màu đỏ vậy mô hình hồi quy tuyến tính này hoạt động tốt với tập dữ liệu đã cho. Bây giờ, chúng ta kiểm tra lại kết quả hai giá trị θ0θ1 khi được tính bằng thư viện Scikit-Learn của Python: 

# Sử dụng hàm trong thư viện sklearn để tìm nghiệm cho bài toán Linear Regression
regr = LinearRegression().fit(X, y)
theta_0 = regr.intercept_[0]
theta_1 = regr.coef_[0][0]

print('theta_0 =', theta_0)
print('theta_1 =', theta_1)
theta_0 = 0.9221372438499378
theta_1 = 0.7202378471295556 

Kết quả thu được như nhau!

Nhược điểm của phương pháp này là gì? Khi mẫu số của phương trình \(\theta_1\) ở trên bằng không thì sao? Lúc ấy, hệ phương trình trong hồi quy tuyến tính có kết quả vô nghiệm nên ta không thể tìm ra bộ trọng số lý tưởng nữa và điều chúng ta cần làm là tìm ra một lời giải đủ tốt, cần một thuật toán để tìm giá trị nhỏ nhất của hàm mất mát \(\mathcal{L}\). Chúng ta sẽ quay lại để đề cập thêm về vấn đề này trong phần tiếp theo nhé!

4. Sử dụng thuật toán hồi quy tuyến tính để giải bài toán tính giá nhà.

Nguồn ảnh: careforproperties

Với mô hình hồi quy tuyến tính đa biến, thay vì đi tìm một đường thẳng \(y=ax+b\) khớp với những điểm đã cho thì chúng ta đi tìm một mặt phẳng/siêu mặt phẳng (plane/hyperplane) trong không gian \(n\) chiều có dạng:

y = \theta_0 + x_1 \theta_1 + … + x_n \theta_n = \mathbf{x}\theta

Trong phương trình đơn biến trên, nếu chúng ta đặt

\theta = \begin{bmatrix} \theta_0 \\[0.3em] \theta_1 \\[0.3em] \vdots \\[0.3em] \theta_n \end{bmatrix}

một vector (cột) hệ số cần phải tối ưu

\mathbf{x} = \begin{bmatrix} 1 & x_0 & \cdots & x_{n} \end{bmatrix}

là một vector hàng chứa các dữ liệu đầu vào mở rộng và số 1 được thêm vào để đơn giản hóa và thuận tiện cho tính toán. Và tương tự, trong mô hình đa biến này, ta cũng có thể dựng nên hàm mất mát cho siêu mặt phẳng trên:

\mathcal{L} = \frac{1}{2m} * \left[\left(y^{(1)} – \begin{bmatrix} 1 & x_0^{(1)} & \cdots & x_{n}^{(1)} \end{bmatrix}\begin{bmatrix} \theta_0 \\[0.3em] \vdots \\[0.3em] \theta_n \end{bmatrix}\right)^2 + … + \left(y^{(m)} – \begin{bmatrix} 1 & x_0^{(m)} & \cdots & x_{n}^{(m)} \end{bmatrix}\begin{bmatrix} \theta_0 \\[0.3em] \vdots \\[0.3em] \theta_n \end{bmatrix} \right)^2\right]

Các bạn dễ chứng minh được rằng, đây là công thức tổng quát cho nghiệm của hệ phương trình trên với số lượng biến θ tùy ý:

\theta = (X^T X)^{-1} X^T y

với

X = \begin{bmatrix} \mathbf{x}^{(1)} \\ \vdots \\ \mathbf{x}^{(m)} \\ \end{bmatrix}
Nguồn ảnh: viblo

Bài toán giá nhà là một trong những ví dụ điển hình của thuật toán hồi quy đa biến này, với một bộ dữ liệu gồm 11 đặc trưng như số lượng phòng tắm, diện tích trong nhà hay cảnh quan xung quanh, … bạn sẽ tính θ như thế nào?  Làm sao vận dụng thuật toán này vào trong bài toán? Với hai bộ dữ liệu gồm data_traindata_test, giờ chúng ta tiến hành train bằng phương pháp nhân ma trận nào: 

# Bước 1: Tính X^T . X
XtX = X.T @ X

# Bước 2: Tính nghịch đảo của X^T . X
XtX_inv = np.linalg.inv(XtX)

# Bước 3: Tính X^T . y
Xty = X.T @ y

# Bước 4: Tính theta
theta = XtX_inv @ Xty
theta = theta[:, 0]
# Tính định thức của X^T . X
print(np.linalg.det(XtX))
 -4.6635911969955336e-71 

Để ý rằng \(-4.66*10^{-71}\), một con số cực kỳ nhỏ và gần với 0! Ở bước hai này, chúng ta không thể tính được nghịch đảo \(X^TX\) một cách chính xác do có sai số.

Liệu chúng ta đã đi đúng hướng chưa? Làm thế nào các bạn xác định được điều đó? Hãy xem sự khác biệt khi sử dụng thư viện Scikit-Learn nào:

# Sử dụng hàm trong thư viện sklearn để tìm nghiệm cho bài toán Linear Regression
regr = LinearRegression(fit_intercept=False).fit(X, y)
theta_sklearn = regr.coef_[0]

print('theta tính bằng công thức (2): ', theta)
print('theta tính bằng thư viện Scikit-Learn: ', theta_sklearn)
theta tính bằng công thức (2):  [ 6.66968205e+00 1.35276164e+05 -2.757094 88e+04 7.13287576e+04 5.67354528e+04 1.60654005e+04 8.42393628e+04 -3.90025757e+03 -4.92800000e+03 -1.28571229e-01 5.12000000e+03 5.20000000e+03] 

theta tính bằng thư viện Scikit-Learn:  [ 6.89600223e+00 -4.45416691e+04  4.79556346e+04  8.49875301e+03   6.92752676e+04  1.81194968e+04  1.16352100e+05 -3.89906079e+03   1.21223086e+02 -2.42831963e-01  7.04792834e+01  5.07438029e+01] 

Khi trả về là giá trị ma trận, bạn so sánh như thế nào? Lúc này, hàm mất mát trong mô hình tuyến tính đa biến được xây dựng để giải đáp các vấn đề trên:

\mathcal{L} = \frac{1}{2m}\displaystyle\sum_{i=1}^{m} [y^{(i)} – \mathbf{x}^{(i)}\theta ]^2
def loss_multivariate(X, y, theta):
    theta = theta.reshape(-1, 1)
    m = len(X)
    # Tính hàm giả thuyết
    h = X @ theta
    loss = 1/(2*m) * np.sum((y - h) ** 2)
    return loss

Và kết quả chúng ta thu được khi so sánh hàm mát mát giữa hai phương pháp là:

loss_multivariate(X, y, theta)
loss_multivariate(X, y, theta_sklearn)
0.040315005553313424 
0.024453221303495358 

Nguồn ảnh: referralcoach

Lời giải của chúng ta tính được vẫn chưa tốt bằng lời giải mà thư viện đã đưa ra, vì sẽ có trường hợp định thức của \(X^TX\) xấp xỉ 0, đồng nghĩa với việc phương trình đạo hàm vô nghiệm. Vậy chúng ta cần có một thuật toán hiệu quả và có thể dễ dàng tính được nghiệm cho bài toán này, đó chính là Gradient Descent.

*Trong Đại số Tuyến tính có một khái niệm gọi là giả nghịch đảo để tìm nghịch đảo của ma trận khi định thức của nó bằng không, tuy nhiên đó là một phần khó và sẽ được đề cập thêm ở một bài khác.

5. Gradient Descent là gì?

Nguồn ảnh: micro.medium

Trong các bài viết trước, chúng ta đã được học cách sử dụng Gradient Descent để tối ưu (tìm điểm cực tiểu) một hàm số bất kỳ, vậy có thể áp dụng ý tưởng của Gradient Descent để tìm ra bộ trọng số lý tưởng nhất cho hàm mất mát ở trên không? 

Với thuật toán Gradient Descent, nếu lỗi quá cao thì thuật toán cần cập nhật các tham số có giá trị mới trong

\theta \gets \theta – \alpha \mathcal{L}’

và khi lỗi vẫn tiếp tục cao trong trường hợp tiếp theo, nó sẽ tiếp tục cập nhật các tham số với giá trị mới lần nữa. Quá trình này được lặp đi lặp lại đến khi hàm mất mát được giảm thiểu. 

def gradient_descent(alpha, n):
    X = [4, 6, 8.75, ... , 5.7]
    y = [3.9, 5.5, 7.8, ... , 4.9]
    m = len(X)
    theta_0 = 0
    theta_1 = 0
    for _ in range (n):
        d_theta_0 = []
        d_theta_1 = []
        for i in range (m):
          d_theta_0.append((theta_0 +theta_1*X[i]) - y[i])
          d_theta_1.append(((theta_0 + theta_1*X[i]) - y[i]) * X[i])

        theta_0 = theta_0 - alpha*(1/m)*sum(d_theta_0)
        theta_1 = theta_1 - alpha *(1/m)*sum(d_theta_1)
      return theta_0, theta_1

Tóm lại, trong Gradient Descent, chúng ta hướng về vùng cực tiểu, Gradient Descent sẽ tự động bước các bước ngày càng nhỏ bởi vì chúng ta đang hướng về khu vực tối ưu hóa với định nghĩa, cực tiểu là nơi đạo hàm bằng 0. Như vậy, khi chúng ta hướng về vùng cực tiểu, đạo hàm của hàm này sẽ tự động nhỏ lại và thuật toán sẽ dần hội tụ.

Dưới đây là code để minh họa cho thuật toán:

def dL(X, y, theta):
    theta = theta.reshape(-1, 1)
    m = len(X)
    return -(1/m) * np.sum(X * (y - X @ theta), axis=0)
def gradient_descent():
    m, n = X.shape
    # Khởi tạo theta ngẫu nhiên
    theta = np.random.randn(n)
    # Chọn các tham số như số lần lặp và hệ số alpha
    iterations = 1000001
    alpha = 0.5
    for i in range(iterations):
        # Cập nhật theta theo công thức của GD
        theta = theta - alpha * dL(X, y, theta)
        # Tính hàm mất mát
        loss = loss_multivariate(X, y, theta)
        if i % 20000 == 0:
            # Xuất giá trị mất mát ra để theo dõi
            print('Iter {}. Loss = {}'.format(i, loss))
    return theta

Kết quả so sánh hàm mất mát giữa hai phương pháp:

loss_multivariate(X, y, theta_gd)
loss_multivariate(X, y, theta_sklearn)
0.04311187540820209 
0.024453221303495358 

Và so sánh trên tập dữ liệu test:

X, y = load_data(data_test)
loss_multivariate(X, y, theta_gd)
loss_multivariate(X, y, theta)
loss_multivariate(X, y, theta_sklearn)
0.04311187540820209 
0.040315005553313424 
0.024453221303495358 

So sánh kết quả cho ra bởi Gradient Descent, ta thấy rằng nó vẫn chưa được tốt so với kết quả của phương pháp giải hệ phương trình cũng như lời giải mà thư viện đưa ra, lí do là vì Gradient Descent vẫn chưa đi đến điểm cực tiểu của hàm mất mát. Những bài viết tiếp theo của CLB sẽ đi sâu vào việc cải thiện mức độ hiệu quả của thuật toán này và tại sao chúng ta nên sử dụng Gradient Descent thay vì đi tìm công thức chính xác của nghiệm. Còn trong phạm vi bài viết này, các bạn có thể tiếp tục tinh chỉnh thử các tham số như số lần lặp hoặc hệ số \(\alpha\) để tìm ra cấu hình thích hợp nhất nhé.

Nguồn ảnh: allthingsd

Tuy nhiên, cũng sẽ có trường hợp mà Gradient Descent lại cho ra kết quả tốt hơn trên tập test, hãy xem ví dụ sau:

# Chọn 1 điểm dữ liệu trong tập dữ liệu test và dự đoán
i = 1
x_1 = X[i]
y_1 = y[i][0]
hypothesis = x_1 @ theta
hypothesis_sklearn = x_1 @ theta_sklearn
hypothesis_gd = x_1 @ theta_gd
print('Dữ liệu của căn nhà cần dự đoán:\n', x_1)
print()
print('Dự đoán của phương pháp đầu tiên: {:.3f} (triệu USD)'.format(hypothesis))
print('Dự đoán của thư viện sklearn: {:.3f} (triệu USD)'.format(hypothesis_sklearn))
print('Dự đoán của gradient descent: {:.3f} (triệu USD)'.format(hypothesis_gd))
print('Giá trị thực tế: {:.3f} (triệu USD)'.format(y_1))
Dữ liệu của căn nhà cần dự đoán:  [1.000e+00 3.000e-06 2.250e-06 2.000e-06 0.000e+00 3.000e-06 7.000e-06  1.951e-03 2.570e-03 7.242e-03 2.170e-03 4.000e-04] 
Dự đoán của phương pháp đầu tiên: 0.709 (triệu USD) 
Dự đoán của thư viện sklearn: 0.632 (triệu USD) 
Dự đoán của gradient descent: 0.602 (triệu USD) 
Giá trị thực tế: 0.538 (triệu USD) 

Vậy là chúng ta đã xong phần lí thuyết cũng như hiện thực ý tưởng của Linear Regression thông qua Python và các thư viện. Để tham khảo thêm code minh họa cho thuật toán này, các bạn có thể tham khảo Colab Notebook mà mình đã chuẩn bị ở đây nhé!

6. Ứng dụng của Linear Regression trong thực tế

Dựa vào thuật toán này, chúng ta có thể sử dụng để giải các bài toán liên quan đến việc dự đoán mức lương trung bình sau khi ra trường dựa vào các đối số đầu vào là giới tính, điểm trung bình khóa học và số lượng các hoạt động ngoại khóa đã tham gia ,…

Ảnh minh họa.

Hay trong các bài toán trả về giá trị nhiệt độ phòng với giá trị đầu vào là ngày, nhiệt độ ngoài trời và ánh sáng trong phòng, …

Ảnh minh họa.

Cụ thể hơn và gần gũi với người dùng nhất, Facebook cũng sử dụng thuật toán này để dự đoán số lượng người share và bình luận dựa trên những tương tác trong bài viết trước đó của bạn hay số lượng bạn bè trên facebook, …

Ảnh minh họa.

7. Tổng kết.

Như vậy, qua bài viết này, chúng ta đã tìm hiểu về thuật toán Linear Regression, các khái niệm cơ bản cũng như cách ứng dụng nó vào trong các bài toán dự đoán điểm Nhập môn Lập trình và dự đoán giá nhà! Mong là các bạn đã nắm rõ được lí thuyết và cách hiện thực ý tưởng của Linear Regression.

Tuy nhiên, đây chỉ mới là thử nghiệm trên dữ liệu ta đã quan sát được, và kết quả chưa thể phản ánh chính xác mức độ hiệu quả của mô hình Linear Regression khi áp dụng vào việc dự đoán điểm nhập môn lập trình hay dự đoán giá nhà ngoài thực tế. Ở các bài viết sau của clb thì các bạn sẽ được giới thiệu thêm những phương pháp để đánh giá một mô hình khi đưa vào đời sống. Hãy đón đọc thêm các bài viết tiếp theo của chúng mình nhé!

7. Tài liệu tham khảo

Uyên Đặng – HTTT2019

kadikoy moto kurye umraniye moto kurye tuzla moto kurye atasehir moto kurye moto kurye moto kurye moto kurye moto kurye

Leave a Reply

Your email address will not be published. Required fields are marked *