AI Cho Mọi Người

AI Cho Mọi Người

Stochastic, mini-batch, và batch gradient descent

 

 

 

Trong bài này, các bạn sẽ học qua ba biến thể của thuật toán gradient descent trong việc huấn luyện mô hình linear regression.

 

1. Stochastic gradient descent (SGD)

Huấn luyện mô hình linear regression theo SGD dùng từng mẫu dữ liệu để cập nhật bộ tham số. Công thức cho các bước trong linear regression theo SGD như sau.

Tính feed forward

$${h_\theta }\left( x \right) = {\theta _0}{x_0} + {\theta _1}{x_1} + … + {\theta _n}{x_n}$$

 

Tính loss

$$J\left( {x,y;\theta } \right) = {\left( {{h_\theta }\left( x \right) – y} \right)^2}$$

 

Tính đạo hàm cho từng tham số

$$\frac{{\partial J\left( {x,y;\theta } \right)}}{{\partial {\theta _j}}} = 2\left( {{h_\theta }\left( x \right) – y} \right){x_j}$$

 

Cập nhật tham số

$${\theta _j} = {\theta _j} – \eta \frac{{\partial J\left( {x,y;\theta } \right)}}{{\partial {\theta _j}}}$$

 

Áp dụng cho bài toán dự đoán giá nhà

Đọc và xử lý data

import numpy as np
from numpy import genfromtxt
import matplotlib.pyplot as plt

data = genfromtxt('my_house_price_prediction.csv', delimiter=',')
m = data.shape[0]
X = data[:,0]
y = data[:,1:]
X_b = np.c_[np.ones((m, 1)), X]

plt.scatter(X, y)
plt.xlabel('Diện tích nhà (x 100$m^2$)')
plt.ylabel('Giá nhà (chục lượng vàng)')
plt.show()

Hiển thị dữ liệu

 

Source code chương trình

def stochastic_gradient_descent():
    n_epochs = 50
    learning_rate = 0.01
    
    # khởi tạo giá trị tham số
    thetas = np.random.randn(2, 1)
    
    thetas_path = [thetas]
    losses = []
    
    for epoch in range(n_epochs):
        for i in range(m):
            # lấy ngẫu nhiên 1 sample
            random_index = np.random.randint(m)
            xi = X_b[random_index:random_index+1]
            yi = y[random_index:random_index+1]
            
            # tính output (o = x1*w1 + x2*w2)
            oi = xi.dot(thetas)
            
            # tính loss li [l = (output - y)^2]
            li = (oi - yi)*(oi - yi)
            
            # tính gradient cho loss
            g_li = 2*(oi - yi)
            
            # tính gradient (g_x1 = x1*g_li) và (g_x2 = x2*g_li)
            gradients = xi.T.dot(g_li)
                        
            # update giá trị theta
            thetas = thetas - learning_rate*gradients
            
            # logging
            thetas_path.append(thetas)            
            losses.append(li[0][0])

    return thetas_path, losses

bgd_thetas, losses = stochastic_gradient_descent()

plt.scatter(X, y)
data_y = X*bgd_thetas[-1][1]+ bgd_thetas[-1][0]
plt.plot(X,data_y, color="r")
plt.show()

 

Kết quả sau 50 epoch

 

Giá trị loss cho 200 mẫu đầu tiên (200 lần cập nhật tham số đầu tiên)

 

2. Batch gradient descent (BGD)

Tính feed forward cho tất cả các mẫu trong bộ dữ liệu. Cách tính feed forward cho mẫu thứ i như sau

$${h_\theta }\left( {{x^{(i)}}} \right) = {\theta _0}x_0^{(i)} + {\theta _1}x_1^{(i)} + … + {\theta _n}x_n^{(i)}$$

 

Tính loss

$$J\left( \theta \right) = \frac{1}{m}\sum\limits_{i = 1}^m {{{\left( {{h_\theta }\left( {{x^{(i)}}} \right) – {y^{(i)}}} \right)}^2}}$$

 

Tính đạo hàm cho từng tham số

$$\frac{{\partial J\left( \theta \right)}}{{\partial {\theta _j}}} = \frac{2}{m}\sum\limits_{i = 1}^m {\left( {{h_\theta }\left( {{x^{(i)}}} \right) – {y^{(i)}}} \right)} x_j^{(i)}$$

 

Cập nhật cho từng tham số

$${\theta _j} = {\theta _j} – \eta \frac{{\partial J\left( \theta \right)}}{{\partial {\theta _j}}}$$

 

Áp dụng cho bài toán dự đoán giá nhà

Phần đọc và xử lý dữ liệu giống như trong mục SGD. Phần dưới hiển thị source cho bài toán dự đoán giá nhà dung BGD

def batch_gradient_descent():
    n_iterations = 50
    learning_rate = 0.01
    
    # khởi tạo giá trị tham số
    thetas = np.random.randn(2, 1)
    thetas_path = [thetas]
    losses = []
    
    for i in range(n_iterations):
        # tính output
        output = X_b.dot(thetas)
        
        # tính loss
        loss = (output - y)**2        
                
        # tính đạo hàm cho loss
        loss_grd = 2*(output - y)/m
        
        # tính đạo hàm cho các tham số
        gradients = X_b.T.dot(loss_grd)
        
        # cập nhật tham số
        thetas = thetas - learning_rate*gradients
        thetas_path.append(thetas)
        
        mean_loss = np.sum(loss)/m
        losses.append(mean_loss)

    return thetas_path, losses

bgd_thetas, losses = batch_gradient_descent()

plt.scatter(X, y)
data_y = X*bgd_thetas[-1][1]+ bgd_thetas[-1][0]
plt.plot(X,data_y, color="r")
plt.show()

 

Kết quả sau khi huấn luyện 50 epoch

 

Giá trị loss cho từng epoch

 

3. Mini-batch gradient descent (MBGD)

MBGD dùng một số mẫu để huấn luyện mô hình. Gọi bs là số lượng mẫu được dùng cho một lần cập nhật tham số, các bước tính cho việc huấn luyện mô hình theo MBGD  như sau

Tính feed forward cho bs mẫu dữ liệu. Cách tính cho một mẫu thứ i như sau

$${h_\theta }\left( {{x^{(i)}}} \right) = {\theta _0}x_0^{(i)} + {\theta _1}x_1^{(i)} + … + {\theta _n}x_n^{(i)}$$

 

Tính loss

$$J\left( \theta \right) = \frac{1}{{bs}}\sum\limits_{i = 1}^{bs} {{{\left( {{h_\theta }\left( {{x^{(i)}}} \right) – {y^{(i)}}} \right)}^2}}$$

 

Tính đạo hàm cho từng tham số

$$\frac{{\partial J\left( \theta \right)}}{{\partial {\theta _j}}} = \frac{2}{{bs}}\sum\limits_{i = 1}^{bs} {\left( {{h_\theta }\left( {{x^{(i)}}} \right) – {y^{(i)}}} \right)} x_j^{(i)}$$

 

Cập nhật cho từng tham số

$${\theta _j} = {\theta _j} – \eta \frac{{\partial J\left( \theta \right)}}{{\partial {\theta _j}}}$$

 

Áp dụng cho bài toán dự đoán giá nhà

Source code chương trình

def mini_batch_gradient_descent():
    n_iterations = 30
    minibatch_size = 5
    
    thetas = np.random.randn(2, 1)
    thetas_path = [thetas]    
    losses = []
    
    for epoch in range(n_iterations):
        shuffled_indices = np.random.permutation(m)
        X_b_shuffled = X_b[shuffled_indices]
        y_shuffled = y[shuffled_indices]
                
        for i in range(0, m, minibatch_size):
            xi = X_b_shuffled[i:i+minibatch_size]
            yi = y_shuffled[i:i+minibatch_size]
            
            # tính output 
            output = xi.dot(thetas)
            
            # tính loss
            loss = (output - yi)**2
            
            # tính đạo hàm cho loss
            loss_grd = 2*(output - yi)/minibatch_size
            
            # tính đạo hàm cho các tham số
            gradients = xi.T.dot(loss_grd)
            
            # cập nhật tham số
            learning_rate = 0.01
            thetas = thetas - learning_rate*gradients
            thetas_path.append(thetas)
            
            loss_mean = np.sum(loss)/minibatch_size
            losses.append(loss_mean)

    return thetas_path, losses

mbgd_thetas, losses = mini_batch_gradient_descent()

plt.scatter(X, y)
data_y = X*mbgd_thetas[-1][1]+ mbgd_thetas[-1][0]
plt.plot(X,data_y, color="r")
plt.show()

 

Kết quả sau 30 epoch

 

Giá trị loss cho 20 mini-batch đầu tiên