.. raw:: html
.. raw:: html
.. raw:: html
.. _sec_linear_regression:
Hồi quy Tuyến tính
==================
.. raw:: html
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
:math:`\mathbf{x}` và mục tiêu với giá trị số thực :math:`y`. Trong khoa
học tự nhiên và khoa học xã hội, mục tiêu của hồi quy thường là *đặc
trưng hóa* mối quan hệ của đầu vào và đầu ra. Mặt khác, học máy lại
thường quan tâm đến việc *dự đoán*.
.. raw:: html
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.
.. raw:: html
.. raw:: html
.. raw:: html
Các Thành phần Cơ bản của Hồi quy Tuyến tính
--------------------------------------------
.. raw:: html
*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* :math:`\mathbf{x}` và mục tiêu
:math:`y` là tuyến tính, do đó :math:`y` có thể được biểu diễn bằng tổng
trọng số của đầu vào :math:`\textbf{x}`, cộng hoặc trừ thêm nhiễu của
các quan sát. Thứ hai, ta giả sử nhiễu có quy tắc (tuân theo phân phối
Gauss). Để tạo động lực, hãy bắt đầu với một ví dụ. Giả sử ta muốn ước
lượng giá nhà (bằng đô la) dựa vào diện tích (đơn vị feet vuông) và tuổi
đời (theo năm).
.. raw:: html
Để 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*.
.. raw:: html
Thông thường, chúng ta sẽ dùng :math:`n` để kí hiệu số lượng mẫu trong
tập dữ liệu. Chỉ số :math:`i` được dùng để xác định một mẫu cụ thể. Ta
ký hiệu mỗi điểm dữ liệu đầu vào là
:math:`x^{(i)} = [x_1^{(i)}, x_2^{(i)}]` và nhãn tương ứng là
:math:`y^{(i)}`.
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
Mô hình Tuyến tính
~~~~~~~~~~~~~~~~~~
.. raw:: html
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):
.. math:: \mathrm{giá nhà} = w_{\mathrm{\textrm{diện_tích}}} \cdot \mathrm{\textrm{diện_tích}} + w_{\mathrm{\textrm{tuổi_đời}}} \cdot \mathrm{\textrm{tuổi_đời}} + b.
.. raw:: html
Ở đây, :math:`w_{\mathrm{\textrm{diện_tích}}}` và
:math:`w_{\mathrm{\textrm{tuổi_đời}}}` được gọi là các *trọng số*, và
:math:`b` được gọi là *hệ số điều chỉnh* (còn được gọi là *độ dời*). Các
trọng số xác định mức độ đóng góp của mỗi đặc trưng tới đầu ra, còn hệ
số điều chỉnh là dự đoán của giá nhà khi tất cả các đặc trưng đều bằng
:math:`0`. Ngay cả khi không bao giờ có một ngôi nhà có diện tích hoặc
tuổi đời bằng không, ta vẫn cần sử dụng hệ số điều chỉnh; nếu không khả
năng biểu diễn của mô hình tuyến tính sẽ bị suy giảm.
.. raw:: html
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ố
:math:`w` và hệ số điều chỉnh :math:`b` sao cho dự đoán của mô hình khớp
nhất với giá nhà thực tế quan sát được trong dữ liệu.
.. raw:: html
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ó :math:`d` đặc trưng, ta biễu diễn dự đoán
:math:`\hat{y}` bởi
.. math:: \hat{y} = w_1 \cdot x_1 + ... + w_d \cdot x_d + b.
.. raw:: html
Thu thập toàn bộ các đặc trưng vào một vector :math:`\mathbf{x}` và toàn
bộ các trọng số vào một vector :math:`\mathbf{w}`, ta có thể biễu diễn
mô hình một cách gọn gàng bằng tích vô hướng:
.. math:: \hat{y} = \mathbf{w}^T \mathbf{x} + b.
.. raw:: html
.. raw:: html
.. raw:: html
Ở đây, vector :math:`\mathbf{x}` tương ứng với một điểm dữ liệu. Chúng
ta sẽ thấy rằng việc truy cập đến toàn bộ tập dữ liệu sẽ tiện hơn nếu ta
biểu diễn tập dữ liệu bằng *ma trận* :math:`\mathbf{X}`. Mỗi hàng của ma
trận :math:`\mathbf{X}` thể hiện một mẫu và mỗi cột thể hiện một đặc
trưng.
.. raw:: html
Với một tập hợp điểm dữ liệu :math:`\mathbf{X}`, kết quả dự đoán
:math:`\hat{\mathbf{y}}` có thể được biểu diễn bằng phép nhân giữa ma
trận và vector:
.. math:: {\hat{\mathbf{y}}} = \mathbf X \mathbf{w} + b.
.. raw:: html
Cho một tập dữ liệu huấn luyện :math:`\mathbf{X}` và các giá trị mục
tiêu đã biết trước :math:`\mathbf{y}`, mục tiêu của hồi quy tuyến tính
là tìm vector *trọng số* :math:`\mathbf{w}` và hệ số điều chỉnh
:math:`b` sao cho với một điểm dữ liệu mới :math:`\mathbf{x}_i` được lấy
mẫu từ cùng phân phối của tập huấn luyện, giá trị mục tiêu :math:`y_i`
sẽ được dự đoán với sai số nhỏ nhất (theo kỳ vọng).
.. raw:: html
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
:math:`y` từ :math:`\mathbf{x}`, chúng ta cũng không kỳ vọng tìm được dữ
liệu thực tế mà ở đó :math:`y` đúng bằng
:math:`\mathbf{w}^T \mathbf{x}+b` với mọi điểm (:math:`\mathbf{x}, y)`.
Để dễ hình dung, mọi thiết bị đo lường dùng để quan sát đặc trưng
:math:`\mathbf{X}` và nhãn :math:`\mathbf{y}` đều có sai số nhất định.
Chính vì vậy, kể cả khi ta chắc chắn rằng mối quan hệ ẩn sau tập dữ liệu
là tuyến tính, chúng ta sẽ thêm một thành phần nhiễu để giải thích các
sai số đó.
.. raw:: html
Trước khi tiến hành tìm các giá trị tốt nhất cho :math:`\mathbf{w}` và
:math:`b`, chúng ta sẽ cần thêm hai thứ nữa: (i) một phép đo đánh giá
chất lượng mô hình và (ii) quy trình cập nhật mô hình để cải thiện chất
lượng.
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
Hàm mất mát
~~~~~~~~~~~
.. raw:: html
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 :math:`0`.
Hàm mất mát thông dụng nhất trong các bài toán hồi quy là hàm tổng bình
phương các lỗi. Khi giá trị dự đoán của một điểm dữ liệu huấn luyện
:math:`i` là :math:`\hat{y}^{(i)}` và nhãn tương ứng là :math:`y^{(i)}`,
bình phương của lỗi được xác định như sau:
.. math:: l^{(i)}(\mathbf{w}, b) = \frac{1}{2} \left(\hat{y}^{(i)} - y^{(i)}\right)^2.
.. raw:: html
Hằng số :math:`1/2` không tạo ra sự khác biệt thực sự nào nhưng sẽ giúp
ký hiệu thuận tiện hơn: nó sẽ được triệt tiêu khi lấy đạo hàm của hàm
mất mát. Vì các dữ liệu trong tập huấn luyện đã được xác định trước và
không thể thay đổi, sai số thực nghiệm chỉ là một hàm của các tham số mô
hình. Để tìm hiểu cụ thể hơn, hãy xét ví dụ dưới đây về một bài toán hồi
quy cho trường hợp một chiều trong :numref:`fig_fit_linreg`.
.. raw:: html
.. _fig_fit_linreg:
.. figure:: ../img/fit_linreg.svg
Khớp dữ liệu với một mô hình tuyến tính.
.. raw:: html
Lưu ý rằng khi hiệu giữa giá trị ước lượng :math:`\hat{y}^{(i)}` và giá
trị quan sát :math:`y^{(i)}` lớn, giá trị hàm mất mát sẽ tăng một lượng
còn lớn hơn thế do sự phụ thuộc bậc hai. Để đo chất lượng của mô hình
trên toàn bộ tập dữ liệu, ta đơn thuần lấy trung bình (hay tương đương
là lấy tổng) các giá trị mất mát của từng mẫu trong tập huấn luyện.
.. math:: L(\mathbf{w}, b) =\frac{1}{n}\sum_{i=1}^n l^{(i)}(\mathbf{w}, b) =\frac{1}{n} \sum_{i=1}^n \frac{1}{2}\left(\mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)}\right)^2.
.. raw:: html
Khi huấn luyện mô hình, ta muốn tìm các tham số
(:math:`\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:
.. math:: \mathbf{w}^*, b^* = \operatorname*{argmin}_{\mathbf{w}, b}\ L(\mathbf{w}, b).
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
Nghiệm theo Công thức
~~~~~~~~~~~~~~~~~~~~~
.. raw:: html
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 :math:`b` vào tham số :math:`\mathbf{w}` bằng cách thêm một
cột toàn :math:`1` vào ma trận dữ liệu. Khi đó bài toán dự đoán trở
thành bài toán cực tiểu hóa :math:`||\mathbf{y} - X\mathbf{w}||`. Bởi vì
biểu thức này có dạng toàn phương, nó là một hàm số lồi, và miễn là bài
toán này không suy biến (các đặc trưng độc lập tuyến tính), nó là một
hàm số lồi chặt.
.. raw:: html
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
:math:`\mathbf{w}` và giải phương trình đạo hàm này bằng :math:`0`, ta
sẽ được nghiệm theo công thức:
.. math:: \mathbf{w}^* = (\mathbf X^T \mathbf X)^{-1}\mathbf X^T y.
.. raw:: html
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.
.. raw:: html
.. raw:: html
.. raw:: html
Hạ Gradient
~~~~~~~~~~~
.. raw:: html
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.
.. raw:: html
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).
.. raw:: html
Ứ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*.
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
Trong mỗi vòng lặp, đầu tiên chúng ta lấy ngẫu nhiên một minibatch
:math:`\mathcal{B}` dữ liệu huấn luyện với kích thước cố định. Sau đó,
chúng ta tính đạo hàm (gradient) của hàm mất mát trên minibatch đó theo
các tham số của mô hình. Cuối cùng, gradient này được nhân với tốc độ
học :math:`\eta > 0` và kết quả này được trừ đi từ các giá trị tham số
hiện tại.
.. raw:: html
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
(:math:`\partial` là ký hiệu đạo hàm riêng của hàm số) :
.. math:: (\mathbf{w},b) \leftarrow (\mathbf{w},b) - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \partial_{(\mathbf{w},b)} l^{(i)}(\mathbf{w},b).
.. raw:: html
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.
.. raw:: html
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
:math:`\mathbf{w}` và :math:`\mathbf{x}` là các vector. Ở đây, việc ký
hiệu bằng các vector giúp công thức dễ đọc hơn nhiều so với việc biểu
diễn bằng các hệ số như :math:`w_1, w_2, \ldots, w_d`.
.. math::
\begin{aligned}
\mathbf{w} &\leftarrow \mathbf{w} - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \partial_{\mathbf{w}} l^{(i)}(\mathbf{w}, b) && =
\mathbf{w} - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \mathbf{x}^{(i)} \left(\mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)}\right),\\
b &\leftarrow b - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \partial_b l^{(i)}(\mathbf{w}, b) && =
b - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \left(\mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)}\right).
\end{aligned}
.. raw:: html
.. raw:: html
.. raw:: html
Trong phương trình trên, :math:`|\mathcal{B}|` là số ví dụ trong mỗi
minibatch (*kích thước batch*) và :math:`\eta` là *tốc độ học*. Cũng cần
phải nhấn mạnh rằng các giá trị của kích thước batch và tốc độ học được
lựa chọn trước một cách thủ công và thường không được học thông qua quá
trình huấn luyện mô hình. Các tham số này tuy điều chỉnh được nhưng
không được cập nhật trong vòng huấn luyện, và được gọi là *siêu tham
số*. *Điều chỉnh siêu tham số* là quá trình lựa chọn chúng, thường dựa
trên kết quả của vòng lặp huấn luyện được đánh giá trên một tập *kiểm
định* riêng biệt.
.. raw:: html
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à :math:`\hat{\mathbf{w}}, \hat{b}` (ký hiệu “mũ” thường
thể hiện các giá trị ước lượng). Lưu ý rằng ngay cả khi hàm số thực sự
tuyến tính và không có nhiễu, các tham số này sẽ không cực tiểu hóa được
hàm mất mát. Mặc dù thuật toán dần dần hội tụ đến một điểm cực tiểu, nó
vẫn không thể tới chính xác được cực tiểu đó với số bước hữu hạn.
.. raw:: html
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.
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
Dự đoán bằng Mô hình đã được Huấn luyện
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. raw:: html
Với mô hình hồi quy tuyến tính đã được huấn luyện
:math:`\hat{\mathbf{w}}^\top x + \hat{b}`, ta có thể ước lượng giá của
một căn nhà mới (ngoài bộ dữ liệu dùng để huấn luyện) với diện tích
:math:`x_1` và tuổi đời :math:`x_2` của nó. Việc ước lượng mục tiêu khi
biết trước những đặc trưng thường được gọi là *dự đoán* hay *suy luận*
(*inference*).
.. raw:: html
Ở đâ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ê.
.. raw:: html
.. raw:: html
.. raw:: html
Vector hóa để tăng Tốc độ Tính toán
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. raw:: html
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.
.. raw:: html
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 :math:`10000` chiều chứa toàn giá trị một. Chúng ta sẽ sử dụng
vòng lặp ``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.
.. code:: python
%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)
.. raw:: html
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).
.. code:: python
# 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()
.. raw:: html
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.
.. code:: python
timer = Timer()
c = np.zeros(n)
for i in range(n):
c[i] = a[i] + b[i]
'%.5f sec' % timer.stop()
.. parsed-literal::
:class: output
'2.69728 sec'
.. raw:: html
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ử.
.. code:: python
timer.start()
d = a + b
'%.5f sec' % timer.stop()
.. parsed-literal::
:class: output
'0.00025 sec'
.. raw:: html
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.
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
Phân phối Chuẩn và Hàm mất mát Bình phương
------------------------------------------
.. raw:: html
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.
.. raw:: html
Nhắc lại ở trên rằng hàm mất mát bình phương
:math:`l(y, \hat{y}) = \frac{1}{2} (y - \hat{y})^2` có nhiều thuộc tính
tiện lợi. Việc nó có đạo hàm đơn giản
:math:`\partial_{\hat{y}} l(y, \hat{y}) = (\hat{y} - y)` là một trong số
đó.
.. raw:: html
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
:math:`\mu` và phương sai :math:`\sigma^2` được cho bởi:
.. math:: p(z) = \frac{1}{\sqrt{2 \pi \sigma^2}} \exp\left(-\frac{1}{2 \sigma^2} (z - \mu)^2\right).
.. raw:: html
Dưới đây ta định nghĩa một hàm Python để tính toán phân phối chuẩn.
.. code:: python
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)
.. raw:: html
Giờ ta có thể trực quan hóa các phân phối chuẩn.
.. code:: python
# 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])
.. figure:: output_linear-regression_vn_0dfe3a_11_0.svg
.. raw:: html
.. raw:: html
.. raw:: html
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ó.
.. raw:: html
Để 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:
.. math:: y = \mathbf{w}^\top \mathbf{x} + b + \epsilon \text{ tại } \epsilon \sim \mathcal{N}(0, \sigma^2).
.. raw:: html
Do đó, chúng ta có thể viết *khả năng* thu được một giá trị cụ thể của
:math:`y` khi biết trước :math:`\mathbf{x}` là
.. math:: p(y|\mathbf{x}) = \frac{1}{\sqrt{2 \pi \sigma^2}} \exp\left(-\frac{1}{2 \sigma^2} (y - \mathbf{w}^\top \mathbf{x} - b)^2\right).
.. raw:: html
Dựa vào *nguyên lý hợp lý cực đại*, giá trị tốt nhất của :math:`b` và
:math:`\mathbf{w}` là những giá trị giúp cực đại hóa *sự hợp lý* của
toàn bộ tập dữ liệu:
.. math:: P(Y\mid X) = \prod_{i=1}^{n} p(y^{(i)}|\mathbf{x}^{(i)}).
.. raw:: html
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*) :math:`-\log p(\mathbf y|\mathbf X)`
mà không cần thay đổi gì thêm. Kết nối các công thức trên, ta có:
.. math:: -\log p(\mathbf y|\mathbf X) = \sum_{i=1}^n \frac{1}{2} \log(2 \pi \sigma^2) + \frac{1}{2 \sigma^2} \left(y^{(i)} - \mathbf{w}^\top \mathbf{x}^{(i)} - b\right)^2.
.. raw:: html
.. raw:: html
.. raw:: html
Giờ ta chỉ cần thêm một giả định nữa: :math:`\sigma` là một hằng số cố
định. Do đó, ta có thể bỏ qua số hạng đầu tiên bởi nó không phụ thuộc
vào :math:`\mathbf{w}` hoặc :math:`b`. Còn số hạng thứ hai thì giống hệt
hàm bình phương sai số đã được giới thiệu ở trên, nhưng được nhân thêm
với hằng số :math:`\frac{1}{\sigma^2}`. May mắn thay, nghiệm không phụ
thuộc vào :math:`\sigma`. Điều này dẫn tới việc cực tiểu hóa bình phương
sai số tương đương với việc ước lượng hợp lý cực đại cho mô hình tuyến
tính dưới giả định có nhiễu cộng Gauss.
.. raw:: html
.. raw:: html
.. raw:: html
Từ Hồi quy Tuyến tính tới Mạng Học sâu
--------------------------------------
.. raw:: html
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*).
.. raw:: html
.. raw:: html
.. raw:: html
Giản đồ Mạng Nơ-ron
~~~~~~~~~~~~~~~~~~~
.. raw:: html
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.
.. raw:: html
.. _fig_single_neuron:
.. figure:: ../img/singleneuron.svg
Hồi quy tuyến tính là một mạng nơ-ron đơn tầng.
.. raw:: html
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.
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
Sinh vật học
~~~~~~~~~~~~
.. raw:: html
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*.
.. raw:: html
.. _fig_Neuron:
.. figure:: ../img/Neuron.svg
Nơ-ron trong thực tế
.. raw:: html
Thông tin :math:`x_i` đến từ các nơ-ron khác (hoặc các cảm biến môi
trường như võng mạc) được tiếp nhận tại các sợi nhánh. Cụ thể, thông tin
đó được nhân với các *trọng số của synapses* :math:`w_i` để xác định mức
ảnh hưởng của từng đầu vào (ví dụ: kích hoạt hoặc ức chế thông qua tích
:math:`x_i w_i`). Các đầu vào có trọng số đến từ nhiều nguồn được tổng
hợp trong nhân tế bào dưới dạng tổng có trọng số
:math:`y = \ sum_i x_i w_i + b` và thông tin này sau đó được gửi đi để
xử lý thêm trong sợi trục :math:`y`, thường là sau một vài xử lý phi
tuyến tính qua :math:`\sigma(y)`. Từ đó, nó có thể được gửi đến đích (ví
dụ, cơ bắp) hoặc được đưa vào một tế bào thần kinh khác thông qua các
sợi nhánh.
.. raw:: html
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.
.. raw:: html
.. raw:: html
.. raw:: html
Đồ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.
.. raw:: html
.. raw:: html
.. raw:: html
Tóm tắt
-------
.. raw:: html
- 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.
.. raw:: html
.. raw:: html
.. raw:: html
Bài tập
-------
.. raw:: html
1. Giả sử ta có dữ liệu :math:`x_1, \ldots, x_n \in \mathbb{R}`. Mục
tiêu của ta là đi tìm một hằng số :math:`b` để cực tiểu hóa
:math:`\sum_i (x_i - b)^2`.
- Tìm một công thức nghiệm cho giá trị tối ưu của :math:`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?
2. 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 :math:`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 :math:`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 :math:`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?
3. Giả sử rằng mô hình nhiễu điều khiển nhiễu cộng :math:`\epsilon` là
phân phối mũ, nghĩa là
:math:`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
:math:`-\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?
.. raw:: html
.. raw:: html
.. raw:: html
Thảo luận
---------
- `Tiếng Anh `__
- `Tiếng Việt `__
Những người thực hiện
---------------------
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