🏷️sec_linear_regression
Hồi quy ám chỉ các phương pháp để xây dựng mối quan hệ giữa điểm dữ liệu
Bài toán hồi quy xuất hiện mỗi khi chúng ta muốn dự đoán một giá trị số. Các ví dụ phổ biến bao gồm dự đoán giá cả (nhà, cổ phiếu, ...), thời gian bệnh nhân nằm viện, nhu cầu trong ngành bán lẻ và vô vàn thứ khác. Không phải mọi bài toán dự đoán đều là bài toán hồi quy cổ điển. Trong các phần tiếp theo, chúng tôi sẽ giới thiệu bài toán phân loại, khi mục tiêu là dự đoán lớp đúng trong một tập các lớp cho trước.
Hồi quy tuyến tính có lẽ là công cụ tiêu chuẩn đơn giản và phổ biến nhất được sử dụng cho bài toán hồi quy.
Xuất hiện từ đầu thế kỉ 19, hồi quy tuyến tính được phát triển từ một vài giả thuyết đơn giản.
Đầu tiên, ta giả sử quan hệ giữa các đặc trưng
Để khớp một mô hình dự đoán giá nhà, chúng ta cần một tập dữ liệu các giao dịch mà trong đó ta biết giá bán, diện tích, tuổi đời cho từng căn nhà. Trong thuật ngữ của học máy, tập dữ liệu này được gọi là dữ liệu huấn luyện hoặc tập huấn luyện, và mỗi hàng (tương ứng với dữ liệu của một giao dịch) được gọi là một ví dụ hoặc mẫu. Thứ mà chúng ta muốn dự đoán (giá nhà) được gọi là mục tiêu hoặc nhãn. Các biến (tuổi đời và diện tích) mà những dự đoán dựa vào được gọi là các đặc trưng hoặc hiệp biến.
Thông thường, chúng ta sẽ dùng
Giả định tuyến tính trên cho thấy rằng mục tiêu (giá nhà) có thể được biểu diễn bởi tổng có trọng số của các đặc trưng (diện tích và tuổi đời):
Ở đây,
Cho một tập dữ liệu, mục đích của chúng ta là chọn được các trọng số
Trong các bài toán mà tập dữ liệu thường chỉ có một vài đặc trưng, biễu diễn tường minh mô hình ở dạng biểu thức dài như trên khá là phổ biến.
Trong học máy, chúng ta thường làm việc với các tập dữ liệu nhiều chiều, vì vậy sẽ tốt hơn nếu ta tận dụng các ký hiệu trong đại số tuyến tính.
Khi đầu vào của mô hình có
Thu thập toàn bộ các đặc trưng vào một vector
Ở đây, vector
Với một tập hợp điểm dữ liệu
Cho một tập dữ liệu huấn luyện
Kể cả khi biết rằng mô hình tuyến tính là lựa chọn tốt nhất để dự đoán
Trước khi tiến hành tìm các giá trị tốt nhất cho
Trước khi suy nghĩ về việc làm thế nào để khớp mô hình với dữ liệu, ta cần phải xác định một phương pháp để đo mức độ khớp.
Hàm mất mát định lượng khoảng cách giữa giá trị thực và giá trị dự đoán của mục tiêu.
Độ mất mát thường là một số không âm và có giá trị càng nhỏ càng tốt.
Khi các dự đoán hoàn hảo, chúng sẽ có độ mất mát sẽ bằng
Hằng số fig_fit_linreg
.
Lưu ý rằng khi hiệu giữa giá trị ước lượng
Khi huấn luyện mô hình, ta muốn tìm các tham số ($\mathbf{w}^, b^$) sao cho tổng độ mất mát trên toàn bộ các mẫu huấn luyện được cực tiểu hóa:
$$\mathbf{w}^, b^ = \operatorname*{argmin}_{\mathbf{w}, b}\ L(\mathbf{w}, b).$$
Hóa ra hồi quy tuyến tính chỉ là một bài toán tối ưu hóa đơn giản.
Khác với hầu hết các mô hình được giới thiệu trong cuốn sách này, hồi quy tuyến tính có thể được giải bằng cách áp dụng một công thức đơn giản, cho một nghiệm tối ưu toàn cục.
Để bắt đầu, chúng ta có thể gộp hệ số điều chỉnh
Bởi vậy chỉ có một điểm cực trị trên mặt mất mát và nó tương ứng với giá trị mất mát nhỏ nhất.
Lấy đạo hàm của hàm mất mát theo
Tuy những bài toán đơn giản như hồi quy tuyến tính có thể có nghiệm theo công thức, bạn không nên làm quen với sự may mắn này. Mặc dù các nghiệm theo công thức giúp ta phân tích toán học một cách thuận tiện, các điều kiện để có được nghiệm này chặt chẽ đến nỗi không có phương pháp học sâu nào thoả mãn được.
Trong nhiều trường hợp ở đó ta không thể giải quyết các mô hình theo phép phân tích, và thậm chí khi mặt mất mát là các mặt bậc cao và không lồi, trên thực tế ta vẫn có thể huấn luyện các mô hình này một cách hiệu quả. Hơn nữa, trong nhiều tác vụ, những mô hình khó để tối ưu hóa này hoá ra lại tốt hơn các phương pháp khác nhiều, vậy nên việc bỏ công sức để tìm cách tối ưu chúng là hoàn toàn xứng đáng.
Kỹ thuật chính để tối ưu hóa gần như bất kỳ mô hình học sâu nào, sẽ được sử dụng xuyên suốt cuốn sách này, bao gồm việc giảm thiểu lỗi qua các vòng lặp bằng cách cập nhật tham số theo hướng làm giảm dần hàm mất mát. Thuật toán này được gọi là hạ gradient. Trên các mặt mất mát lồi, giá trị mất mát cuối cùng sẽ hội tụ về giá trị nhỏ nhất. Tuy điều tương tự không thể áp dụng cho các mặt không lồi, ít nhất thuật toán sẽ dẫn tới một cực tiểu (hy vọng là tốt).
Ứng dụng đơn giản nhất của hạ gradient bao gồm việc tính đạo hàm của hàm mất mát, tức trung bình của các giá trị mất mát được tính trên mỗi mẫu của tập dữ liệu. Trong thực tế, việc này có thể cực kì chậm. Chúng ta phải duyệt qua toàn bộ tập dữ liệu trước khi thực hiện một lần cập nhật. Vì thế, thường ta chỉ muốn lấy một minibatch ngẫu nhiên các mẫu mỗi khi ta cần tính bước cập nhật. Phương pháp biến thể này được gọi là hạ gradient ngẫu nhiên.
Trong mỗi vòng lặp, đầu tiên chúng ta lấy ngẫu nhiên một minibatch
Chúng ta có thể biểu diễn việc cập nhật bằng công thức toán như sau (
Tổng kết lại, các bước của thuật toán như sau: (i) khởi tạo các giá trị tham số của mô hình, thường thì sẽ được chọn ngẫu nhiên. (ii) tại mỗi vòng lặp, ta lấy ngẫu nhiên từng batch từ tập dữ liệu (nhiều lần), rồi tiến hành cập nhật các tham số của mô hình theo hướng ngược với gradient.
Khi sử dụng hàm mất mát bậc hai và mô hình tuyến tính, chúng ta có thể biểu diễn bước này một cách tường minh như sau:
Lưu ý rằng
Trong phương trình trên,
Sau khi huấn luyện đủ số vòng lặp được xác định trước (hoặc đạt được một tiêu chí dừng khác), ta sẽ ghi lại các tham số mô hình đã được ước lượng, ký hiệu là
Hồi quy tuyến tính thực ra là một bài toán tối ưu lồi, do đó chỉ có một cực tiểu (toàn cục). Tuy nhiên, đối với các mô hình phức tạp hơn, như mạng sâu, mặt của hàm mất mát sẽ có nhiều cực tiểu. May mắn thay, vì một lý do nào đó mà những người làm về học sâu hiếm khi phải vật lộn để tìm ra các tham số cực tiểu hóa hàm mất mát trên dữ liệu huấn luyện. Nhiệm vụ khó khăn hơn là tìm ra các tham số dẫn đến giá trị mất mát thấp trên dữ liệu mà mô hình chưa từng thấy trước đây, một thử thách được gọi là sự khái quát hóa. Chúng ta sẽ gặp lại chủ đề này xuyên suốt cuốn sách.
Với mô hình hồi quy tuyến tính đã được huấn luyện
Ở đây ta sẽ dùng từ dự đoán thay vì suy luận, dù suy luận là một thuật ngữ khá phổ biến trong học sâu, áp dụng thuật ngữ này ở đây lại không phù hợp. Trong thống kê, suy luận thường được dùng cho việc ước lượng thông số dựa trên tập dữ liệu. Việc dùng sai thuật ngữ này là nguyên nhân gây ra sự hiểu nhầm giữa những người làm học sâu và các nhà thống kê.
Khi huấn luyện mô hình, chúng ta thường muốn xử lý đồng thời các mẫu dữ liệu trong minibatch.
Để làm được điều này một cách hiệu quả, chúng ta phải vector hóa việc tính toán bằng cách sử dụng các thư viện đại số tuyến tính thay vì sử dụng các vòng lặp for
trong Python.
Chúng ta sẽ sử dụng hai phương pháp cộng vector dưới đây để hiểu được tại sao vector hóa là cần thiết trong học máy.
Đầu tiên, ta khởi tạo hai vector for
trong Python ở phương pháp thứ nhất và một hàm trong thư viện np
ở phương pháp thứ hai.
%matplotlib inline
from d2l import mxnet as d2l
import math
from mxnet import np
import time
n = 10000
a = np.ones(n)
b = np.ones(n)
Vì ta sẽ cần đánh giá xếp hạng thời gian xử lý một cách thường xuyên trong cuốn sách này, ta sẽ định nghĩa một bộ tính giờ (sau đó có thể truy cập được thông qua gói d2l
để theo dõi thời gian chạy).
# Saved in the d2l package for later use
class Timer(object):
"""Record multiple running times."""
def __init__(self):
self.times = []
self.start()
def start(self):
# Start the timer
self.start_time = time.time()
def stop(self):
# Stop the timer and record the time in a list
self.times.append(time.time() - self.start_time)
return self.times[-1]
def avg(self):
# Return the average time
return sum(self.times)/len(self.times)
def sum(self):
# Return the sum of time
return sum(self.times)
def cumsum(self):
# Return the accumuated times
return np.array(self.times).cumsum().tolist()
Bây giờ, ta có thể đánh giá xếp hạng hai phương pháp cộng vector.
Đầu tiên, ta sử dụng vòng lặp for
để cộng các tọa độ tương ứng.
timer = Timer()
c = np.zeros(n)
for i in range(n):
c[i] = a[i] + b[i]
'%.5f sec' % timer.stop()
Trong phương pháp hai, ta dựa vào thư viện np
để tính tổng hai vector theo từng phần tử.
timer.start()
d = a + b
'%.5f sec' % timer.stop()
Bạn có thể nhận thấy rằng, phương pháp thứ hai nhanh hơn rất nhiều lần so với phương pháp thứ nhất. Việc vector hóa thường tăng tốc độ tính toán lên nhiều bậc. Ngoài ra, giao phó công việc tính toán cho thư viện để tránh phải tự viết lại sẽ giảm thiểu khả năng phát sinh lỗi.
Mặc dù bạn đã có thể thực hành với kiến thức được trình bày phía trên, trong phần tiếp theo chúng ta sẽ làm rõ hơn nguồn gốc của hàm mất mát bình phương thông qua các giả định về phân phối của nhiễu.
Nhắc lại ở trên rằng hàm mất mát bình phương
Như được đề cập trước đó, hồi quy tuyến tính được phát minh bởi Gauss vào năm 1795.
Ông cũng là người khám phá ra phân phối chuẩn (còn được gọi là phân phối Gauss).
Hóa ra là mối liên hệ giữa phân phối chuẩn và hồi quy tuyến tính không chỉ dừng lại ở việc chúng có chung cha đẻ.
Để gợi nhớ lại cho bạn, mật độ xác suất của phân phối chuẩn với trung bình
Dưới đây ta định nghĩa một hàm Python để tính toán phân phối chuẩn.
x = np.arange(-7, 7, 0.01)
def normal(z, mu, sigma):
p = 1 / math.sqrt(2 * math.pi * sigma**2)
return p * np.exp(- 0.5 / sigma**2 * (z - mu)**2)
Giờ ta có thể trực quan hóa các phân phối chuẩn.
# Mean and variance pairs
parameters = [(0, 1), (0, 2), (3, 1)]
d2l.plot(x, [normal(x, mu, sigma) for mu, sigma in parameters], xlabel='z',
ylabel='p(z)', figsize=(4.5, 2.5),
legend=['mean %d, var %d' % (mu, sigma) for mu, sigma in parameters])
Có thể thấy rằng, thay đổi giá trị trung bình tương ứng với việc dịch chuyển phân phối dọc theo trục x, tăng giá trị phương sai sẽ trải rộng phân phối và hạ thấp đỉnh của nó.
Để thấy rõ hơn mối quan hệ giữa hồi quy tuyến tính và hàm mất mát trung bình bình phương sai số (MSE), ta có thể giả định rằng các quan sát bắt nguồn từ những quan sát nhiễu, và giá trị nhiễu này tuân theo phân phối chuẩn như sau:
Do đó, chúng ta có thể viết khả năng thu được một giá trị cụ thể của
Dựa vào nguyên lý hợp lý cực đại, giá trị tốt nhất của
Bộ ước lượng được chọn theo nguyên lý hợp lý cực đại được gọi là bộ ước lượng hợp lý cực đại (Maximum Likelihood Estimators -- MLE).
Dù việc cực đại hóa tích của nhiều hàm mũ trông có vẻ khó khăn, chúng ta có thể khiến mọi thứ đơn giản hơn nhiều mà không làm thay đổi mục tiêu ban đầu bằng cách cực đại hóa log của hàm hợp lý.
Vì lý do lịch sử, các bài toán tối ưu thường được biểu diễn dưới dạng bài toán cực tiểu hóa thay vì cực đại hóa.
Do đó chúng ta có thể cực tiểu hóa hàm đối log hợp lý (Negative Log-Likelihood - NLL)
Giờ ta chỉ cần thêm một giả định nữa:
Cho đến nay, chúng ta mới chỉ đề cập về các hàm tuyến tính. Trong khi mạng nơ-ron có thể xấp xỉ rất nhiều họ mô hình, ta có thể bắt đầu coi mô hình tuyến tính như một mạng nơ-ron và biểu diễn nó theo ngôn ngữ của mạng nơ-ron. Để bắt đầu, hãy cùng viết lại mọi thứ theo ký hiệu 'tầng' (layer).
Những người làm học sâu thích vẽ giản đồ để trực quan hóa những gì đang xảy ra trong mô hình của họ.
Trong :numref:fig_single_neuron
, mô hình tuyến tính được minh họa như một mạng nơ-ron.
Những giản đồ này chỉ ra cách kết nối (ở đây, mỗi đầu vào được kết nối tới đầu ra) nhưng không có giá trị của các trọng số và các hệ số điều chỉnh.
Vì chỉ có một nơ-ron tính toán (một nút) trong đồ thị (các giá trị đầu vào không cần tính mà được cho trước), chúng ta có thể coi mô hình tuyến tính như mạng nơ-ron với chỉ một nơ-ron nhân tạo duy nhất. Với mô hình này, mọi đầu vào đều được kết nối tới mọi đầu ra (trong trường hợp này chỉ có một đầu ra!), ta có thể coi phép biến đổi này là một tầng kết nối đầy đủ, hay còn gọi là tầng kết nối dày đặc. Chúng ta sẽ nói nhiều hơn về các mạng nơ-ron cấu tạo từ những tầng như vậy trong chương kế tiếp về mạng perceptron đa tầng.
Vì hồi quy tuyến tính (được phát minh vào năm 1795) được phát triển trước ngành khoa học thần kinh tính toán, nên việc mô tả hồi quy tuyến tính như một mạng nơ-ron có vẻ hơi ngược thời.
Để hiểu tại sao nhà nghiên cứu sinh vật học/thần kinh học Warren McCulloch và Walter Pitts tìm đến các mô hình tuyến tính để làm điểm khởi đầu nghiên cứu và phát triển các mô hình nơ-ron nhân tạo, hãy xem ảnh của một nơ-ron sinh học tại :numref:fig_Neuron
.
Mô hình này bao gồm sợi nhánh (cổng đầu vào), nhân tế bào (bộ xử lý trung tâm), sợi trục (dây đầu ra), và đầu cuối sợi trục (cổng đầu ra), cho phép kết nối với các tế bào thần kinh khác thông qua synapses.
Thông tin
Dựa trên các nghiên cứu thực tế về các hệ thống thần kinh sinh học, ta chắc chắn một điều rằng nhiều đơn vị như vậy khi được kết hợp với nhau theo đúng cách, cùng với thuật toán học phù hợp, sẽ tạo ra các hành vi thú vị và phức tạp hơn nhiều so với bất kỳ nơ-ron đơn lẻ nào có thể làm được.
Đồng thời, hầu hết các nghiên cứu trong học sâu ngày nay chỉ lấy một phần cảm hứng nhỏ từ ngành thần kinh học.
Như trong cuốn sách kinh điển về AI Trí tuệ Nhân tạo: Một hướng Tiếp cận Hiện đại :cite:Russell.Norvig.2016
của Stuart Russell và Peter Norvig, họ đã chỉ ra rằng: mặc dù máy bay có thể được lấy cảm hứng từ loài chim, ngành điểu học không phải động lực chính làm đổi mới ngành hàng không trong nhiều thế kỷ qua.
Tương tự, cảm hứng trong học sâu hiện nay chủ yếu đến từ ngành toán học, thống kê và khoa học máy tính.
- Nguyên liệu của một mô hình học máy bao gồm dữ liệu huấn luyện, một hàm mất mát, một thuật toán tối ưu, và tất nhiên là cả chính mô hình đó.
- Vector hóa giúp mọi thứ trở nên dễ hiểu hơn (về mặt toán học) và nhanh hơn (về mặt lập trình).
- Cực tiểu hóa hàm mục tiêu và thực hiện phương pháp hợp lý cực đại có ý nghĩa giống nhau.
- Các mô hình tuyến tính cũng là các mạng nơ-ron.
- Giả sử ta có dữ liệu
$x_1, \ldots, x_n \in \mathbb{R}$ . Mục tiêu của ta là đi tìm một hằng số$b$ để cực tiểu hóa$\sum_i (x_i - b)^2$ .- Tìm một công thức nghiệm cho giá trị tối ưu của
$b$ . - Bài toán và nghiệm của nó có liên hệ như thế nào tới phân phối chuẩn?
- Tìm một công thức nghiệm cho giá trị tối ưu của
- Xây dựng công thức nghiệm cho bài toán tối ưu hóa hồi quy tuyến tính với bình phương sai số.
Để đơn giản hơn, bạn có thể bỏ qua hệ số điều chỉnh
$b$ ra khỏi bài toán (chúng ta có thể thực hiện việc này bằng cách thêm vào một cột toàn giá trị một vào$X$ ).- Viết bài toán tối ưu hóa theo ký hiệu ma trận-vector (xem tất cả các điểm dữ liệu như một ma trận và tất cả các giá trị mục tiêu như một vector).
- Tính gradient của hàm mất mát theo
$w$ . - Tìm công thức nghiệm bằng cách giải phương trình gradient bằng không.
- Khi nào phương pháp làm này tốt hơn so với sử dụng hạ gradient ngẫu nhiên? Khi nào phương pháp này không hoạt động?
- Giả sử rằng mô hình nhiễu điều khiển nhiễu cộng
$\epsilon$ là phân phối mũ, nghĩa là$p(\epsilon) = \frac{1}{2} \exp(-|\epsilon|)$ .- Viết hàm đối log hợp lý của dữ liệu theo mô hình
$-\log P(Y \mid X)$ . - Bạn có thể tìm ra nghiệm theo công thức không?
- Gợi ý là thuật toán hạ gradient ngẫu nhiên có thể giải quyết vấn đề này.
- Điều gì có thể sai ở đây (gợi ý - điều gì xảy ra gần điểm dừng khi chúng ta tiếp tục cập nhật các tham số). Bạn có thể sửa nó không?
- Viết hàm đối log hợp lý của dữ liệu theo mô hình
Bản dịch trong trang này được thực hiện bởi:
- Đoàn Võ Duy Thanh
- Lê Khắc Hồng Phúc
- Phạm Minh Đức
- Phạm Ngọc Bảo Anh
- Nguyễn Văn Tâm
- Phạm Hồng Vinh
- Nguyễn Phan Hùng Thuận
- Vũ Hữu Tiệp
- Tạ H. Duy Nguyên
- Bùi Nhật Quân
- Lê Gia Thiên Bửu
- Lý Phi Long
- Nguyễn Minh Thư
- Tạ Đức Huy
- Minh Trí Nguyễn
- Trần Thị Hồng Hạnh
- Nguyễn Quang Hải
- Lê Thành Vinh