Regularized linear regression

Machine Learning cơ bản với NumPy

0.0 (0 đánh giá)
Tạo bởi Huy Trịnh Cập nhật lần cuối 15:29 02-09-2020 3.630 lượt xem 0 bình luận
Học nhanh

Danh sách bài học

Regularized linear regression

Dẫn nhập

Trong bài trước, chúng ta đã tìm hiểu về TẠO POLYNOMIAL FEATURE.

Ở bài này Kteam sẽ giới thiệu về Regularized linear regression để giúp thuật toán chúng ta tránh rơi vào tình trạng overfit.


Nội dung

Để theo dõi bài này tốt nhất bạn cần có kiến thức về:

Trong bài này chúng ta sẽ tìm hiểu về:

  • Regularization là gì?
  • Regularized cost function cho linear regression
  • Regularized cost gradient và sử dụng thư viện scipy để train thuật toán
  • Regularized normal equation cho linear regression

Regularization là gì?

Khi chúng ta gặp phải vấn đề về overfit, regularization là một trong những giải pháp hiệu quả để giải quyết trường hợp này, giúp chúng ta tránh overfit nhưng vẫn giữ nguyên tính bao quát của thuật toán (không cần phải loại bỏ bất kì feature nào của training set). Cách hoạt động của regularization là giảm độ lớn của các theta đi, làm giảm sức ảnh hưởng của một số feature khiến hàm h_\theta(x) đơn giản hơn, tránh được overfit (vì hàm dự đoán càng phức tạp thì càng dễ rơi vào overfit).

Lưu ý:

  • Nếu chúng ta tăng parameter lambda của regularization lên quá cao (đồng nghĩa với việc sử dụng regularization quá mức), thuật toán của chúng ta sẽ rơi vào trường hợp underfit.
  • Chúng ta sẽ không thực hiện regularization trên feature x0

Regularized cost function

Đầu tiên chúng ta sẽ thực hiện regularized cho hàm cost. Để làm việc này chúng ta chỉ cần thêm một hạng tử regularization vào hàm J(θ) là được:

J(\theta)=\frac{1}{2m} * \sum_{i=0}^m(h_\theta(x^{(i)}) - y^{(i)})^2 +\frac{\lambda}{2m}* \sum_{j=1}^n\theta_{(j)}^2

Trong đó:

  • \frac{1}{2m} * \sum_{i=0}^m(h_\theta(x^{(i)}) - y^{(i)})^2 là công thức hàm cost bình thường (chưa thêm hạng tử regularization vào)
  • \lambda (lambda) là parameter regularization, quyết định “cường độ” của việc regularization
  • \sum_{j=1}^n\theta_{(j)}^2 dùng để tính tổng các bình phương theta, chỉ lấy từ θ1 đến θn , không lấy θ0 vì chúng ta không cần phải regularized feature bias x0

Để thuận tiện cho việc lập trình hàm này trong python, chúng ta có thể vectorize nó thành như thế này:

J(\theta)=\frac{1}{2m}*(h_\theta(x)-y)^T(h_\theta(x)-y)+\frac{\lambda}{2m}*\theta^T\theta

Chúng ta có thể rút gọn thành như vậy vì khi lấy VT * V (với V là 1 vector) thì sẽ đồng nghĩa với việc tính tổng các bình phương của các phần tử trong vector đó.

Bây giờ, chúng ta sẽ lập trình hàm cost regularized này với python. Đầu tiên chúng ta define một hàm mới trong file functions.py với các parameter như sau:

#Hàm cost regularized nhận các parameter X, y, theta
#và parameter regularization lambda mặc định là 0
def J_reg(X, y, theta, l = 0):
	pass

Tiếp theo, ta sẽ khởi tạo một số giá trị để tiện sử dụng:

def J_reg(X, y, theta, l = 0):
	#m là số example, bằng độ dài của y
	m = y.size
	#vì chúng ta chỉ cần regularized các theta từ 1 -> n, ta sẽ tạo
	#một biến tạm là các theta này
	t = theta[1:]

Sau đó ta sẽ tính error và hạng tử regularization:

def J_reg(X, y, theta, l = 0):
	m = y.size
	t = theta[1:]
	#error bằng h(x) – y
	err = predict(X, theta) – y
	#hạng tử regularization bằng lambda * tổng bình phương
	#các theta chia 2m
	regular = (l*(t.T@t))/(2*m)

Cuối cùng ta chỉ việc tính J(θ) dựa theo công thức:

	#J bằng bình phương error / 2m + hạng tử regularization
	J = (err.T@err)/(2*m) + regular
	#trả về kết quả
	return J

Vậy là chúng ta đã lập trình được hàm J(θ) regularized. Tiếp theo, để train thuật toán, ta cần phải có đạo hàm của hàm này (để biết được “độ dốc” của J(θ) tại một vị trí θ nhất định)


Regularized cost gradient và sử dụng thư viện scipy để train thuật toán

Regularized cost gradient

Kteam đã tính sẵn cho bạn đạo hàm của hàm cost này. Đối với θ0, chúng ta sẽ không thực hiện regularization nên công thức sẽ là:

\frac{\partial J(\theta)}{\partial \theta_0} = \frac{1}{m} * \sum_{i=0}^m(h_\theta(x^{(i)})-y^{(i)})x_j^{(i)}

Đối với \theta_1 đến \theta_n , ta sẽ thêm hạng tử regularization nên công thức sẽ như sau:

\frac{\partial J(\theta)}{\partial \theta_j} = \frac{1}{m} * \sum_{i=0}^m(h_\theta(x^{(i)})-y^{(i)})x_j^{(i)}+\frac{\lambda}{m}*\theta_{(j)}

Trong đó:

  • \frac{1}{m} * \sum_{i=0}^m(h_\theta(x^{(i)})-y^{(i)})x_j^{(i)} chính là đạo hàm của hàm J(θ) khi chưa regularized, Kteam đã đề cập trong các bài trước.
  • \frac{\lambda}{m}*\theta_{(j)}  chính là đạo hàm của hạng tử regularization, được thêm vào đối với các theta từ 1 tới n.

Để tránh phải sử dụng hàm tổng, ta có thể vectorized công thức thành:

\frac{\partial J(\theta)}{\partial \theta_0}=\frac{1}{m}*x_0^T(h_\theta(x)-y)

Đối với \theta_0 và:

\frac{\partial J(\theta)}{\partial \theta_{1..n}}= \frac{1}{m}*x^T_{1..n}(h_\theta(x)-y)+\frac{\lambda}{m}*\theta_{1..n}

Đối với θ1 đến θn . Ta có thể vectorized được như trên vì  sẽ tương đương với việc tính tổng các tích đơn thuần bằng hàm tổng.

Chúng ta tiếp tục define thêm 1 hàm grad_reg trong file functions:

#hàm grad_reg nhận các parameter X, y, theta và lambda mặc định là 0
def grad_reg(X, y, theta, l = 0):
	pass

Đầu tiên ta sẽ khởi tạo một số biến cần sử dụng:

def grad_reg(X, y, theta, l = 0):
	#m là số training example
	m = y.size
	#n là số feature (số cột của X)
	n = X.shape[1]
	#grad là vector thể hiện “độ dốc” cần trả về
	grad = np.zeros(n)

Tiếp theo là tính error, cost gradient cho θ0 và cost gradient cho các theta còn lại:

	#tính error = h(x) – y
	err = predict(X, theta) – y
	#tính cost gradient cho theta 0, không có regularization term
	grad[0] = (1/m)*(X[:,0].T@err)
	#tính cost gradient cho các theta còn lại với regularization term
	grad[1:] = (1/m)*(X[:,1:].T@err) + (l/m)*theta[1:]
	#trả về ma trận grad là vector các cost gradient cho từng theta
	return grad

Sử dụng thư viện scipy để train thuật toán

Để train thuật toán, bạn có thể tự lập trình Gradient Descent với công thức:

For i in range(iter)

\theta = \theta - \alpha * cost\_ grad

Ở bài này Kteam sẽ hướng dẫn các bạn 1 cách khác, đó là sử dụng thư viện scipy để train thuật toán.

Cài đặt scipy

Các bước thực hiện để cài đặt thư viện scipy:

Bước 1: Mở cmd với quyền admin:

Regularized linear regression, Python, Kteam, Howkteam

Tips: Bạn có thể mở nhanh cmd bằng tổ hợp phím Win + R; cmd; Enter.

Bước 2: Gõ lệnh:

python -m pip install [--user] scipy

Kteam khuyến khích bạn sử dụng --user để tránh bị lỗi nếu không có quyền truy cập toàn máy tính (local machine). --user chỉ cài đặt Scipy cho user hiện tại.

Sử dụng scipy để train thuật toán

Bài 11 - Resource

Đầu tiên là phần import các thư viện cần thiết:

#file main.py
import numpy as np
#import thư viện scipy.optimize để train thuật toán
import scipy.optimize as opt
import matplotlib.pyplot as plt
from functions import *

Ta load data và tạo các polynomial feature tương tự bài trước:

data = np.loadtxt('data.txt',delimiter=',')
#Lấy các cột đầu của data và thêm cột 1 vào để làm X
X = np.c_[np.ones(data.shape[0]), data[:,:-1]]
#lấy cột cuối làm y
y = data[:,-1]
#Vòng lặp từ mũ 2 đến mũ 8
for i in range(2,9):
	#thêm một cột feature vào bên phải X với giá trị bằng x1 mũ i
	X = np.c_[X, X[:,1]**i]
#Lấy kích thước y làm m
m = y.size
#Lấy số cột của X làm n
n = X.shape[1]
#tính min và max của x1
min_x = np.min(X[:,1])
max_x = np.max(X[:,1])
#tạo ma trận xp có giá trị từ min_x – 30 đến max_x + 30, step là 0.5 (mỗi giá trị lệch nhau 0.5)
xp = np.arange(min_x - 30, max_x + 30, 0.5)
#thêm x0 bằng 1 cho xp
xp = np.c_[np.ones(xp.size), xp]
#thực hiện thêm polynomial feature như đã làm với X
for i in range(2,9):
	xp = np.c_[xp, xp[:,1]**i]
#Normalize X
[X, mu, sig] = Normalize(X)
#thực hiện normalize xp bằng mu và sigma tính từ X
xp -= mu
xp /= sig
xp[:,0] = 1

Tiếp theo là phần train thuật toán bằng hàm scipy.optimize.fmin_cg()

fmin_cg(f, initial_theta, fprime)

Trong đó:

  • f là hàm cost
  • initial_theta là bộ theta ban đầu
  • fprime là đạo hàm của hàm f, cũng chính là hàm grad_reg của chúng ta

Lưu ý: Hàm fmin_cg chỉ truyền vào hàm f fprime 1 parameter là theta vì thế chúng ta phải define lại phiên bản rút gọn của 2 hàm này.

#khởi tạo theta ban đầu bằng 0
itheta = np.zeros(n)
#biến l chính là lambda, bạn có thể thay đổi
# biến này để thấy sự khác biệt khi không dùng regularization (l = 0)
# và có dùng l != 0
l = 0
# hàm J_reg rút gọn, chỉ nhận 1 parameter t
j = lambda t: J_reg(X, y, t, l)
# hàm grad_reg rút gọn, chỉ nhận 1 parameter t
g = lambda t: grad_reg(X, y, t, l)

Cuối cùng là gọi hàm fmin_cg để train:

theta = opt.fmin_cg(j, itheta, g)

Bạn có thể plot kết quả ra để xem:Nếu bạn không thích hàm này in ra kết quả, bạn có thể truyền thêm keyword argument disp = False

#thêm tiêu đề biểu đồ
plt.title(f'Polynomial regression with lambda = {l}')

#plot bộ training set, cần đảo ngược quá trình normalize bằng cách * sigma + mu
plt.plot(X[:,1]*sig[1] +mu[1], y, 'rx')
#plot đường dự đoán 
plt.plot(xp[:,1]*sig[1] +mu[1], xp@theta)

#Thêm chú thích 
plt.legend(['Training example', 'Prediction line'])
plt.xlabel('Change in water level')
plt.ylabel('Water flowing out of the dam')

plt.show()

Bạn hãy tự thay đổi lambda và xem kết quả nhé.

Regularized linear regression, Python, Kteam, Howkteam

Regularized linear regression, Python, Kteam, Howkteam

Regularized linear regression, Python, Kteam, Howkteam

Regularized linear regression, Python, Kteam, Howkteam


Regularized normal equation

Chúng ta còn có 1 phương pháp khác để có được bộ theta, đó là normal equation. Kteam sẽ hướng dẫn các bạn cách regularized hàm normal equation.

Công thức normal equation regularized:

\theta = (X^TX+\lambda*L)^{-1}X^Ty

Đây là công thức normal equation bình thường nhưng được thêm regularization term \lambda*L với L là 1 identity matrix kích thước n*n với phần tử 0,0 bằng 0:

L = [0 1 0 0 1 1]

Chúng ta lại tiếp tục define một hàm mới trong file functions:

def norm_eqn_reg(X, y, l = 0):
	#n là số feature
	n = X.shape[1]
	#tạo identity matrix n*n
	L = np.eye(n)
	#gán phần tử 0,0 bằng 0
	L[0,0] = 0

Sau đó ta chỉ việc áp dụng công thức:Vậy là chúng ta đã lập trình xong regularized normal equation, để sử dụng bạn chỉ cần gọi tới hàm và truyền đầy đủ các parameter vào.

	#nhân tử đầu tiên
	a = np.linalg.pinv(X.T @ X + l*L)
	#nhân tử thứ 2
	b = X.T @ y
	
	#tính theta
	theta = a @ b
	return theta

Kết luận

Qua bài này chúng ta đã tìm hiểu về regularized linear regression để tránh được tình trạng overfit.

Cảm ơn bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.


Tải xuống

Project

Nếu việc thực hành theo hướng dẫn không diễn ra suôn sẻ như mong muốn. Bạn cũng có thể tải xuống PROJECT THAM KHẢO ở link bên dưới!


Thảo luận

Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần BÌNH LUẬN bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.

Nội dung bài viết

Tác giả/Dịch giả

Chào các bạn!! Mình là Huy - một cậu bé đam mê lập trình :D Trong một mùa hè rảnh rỗi trước năm cuối cấp đầy cam go, sau khi đã cày hết 7749 bộ anime thì mình muốn làm một việc gì đó "có ích cho đời" hơn. Từ đó mình đã thành 1 Kter :)))

Liên hệ: huytrinhm@gmail.com

Khóa học

Machine Learning cơ bản với NumPy

Với mục đích giới thiệu đến mọi người về Machine Learning cũng như tạo điểm khởi đầu cho các bạn mới, muốn tham gia và tìm hiểu ban đầu về lĩnh vực khá hot này. Cùng Kteam tìm hiểu về Machine Learning cơ bản với ngôn ngữ Python.

Thông qua khóa học MACHINE LEARNING VỚI NUMPY, Kteam sẽ hướng dẫn các kiến thức cơ bản của thuật toán Machine Learning để các bạn có thể tạo ra những sản phẩm Machine Learning của riêng mình.

Đánh giá

Bình luận

Để bình luận, bạn cần đăng nhập bằng tài khoản Howkteam.

Đăng nhập
Không có video.