All lessons in FoundationsTất cả bài trong chương Foundations20
Đạo hàm, gradient và chain rule
Đạo hàm qua ví dụ đời thường, gradient chỉ hướng nào, vì sao đi ngược gradient giúp mô hình bớt sai, và chain rule là gì.
On this pageMục lục bài viết15
Mục tiêu bài học: Sau bài này, bạn sẽ hiểu đạo hàm là gì qua ví dụ đời thường và ví dụ số, biết gradient chỉ hướng nào và vì sao "đi ngược gradient" giúp mô hình bớt sai, đồng thời nắm được vì sao chain rule là trái tim của việc huấn luyện mạng nơ-ron.
1. Hàng tỷ núm vặn - xoay núm nào, về bên nào?
Ở Bài 01, mô hình ML là cỗ máy nhiều núm vặn: mỗi núm là một tham số, và "học" là tìm vị trí núm sao cho mô hình đoán ít sai nhất. Vòng lặp huấn luyện có một bước nghe rất nhẹ nhàng: "chỉnh núm để đoán đỡ sai hơn".
Nhưng chỉnh thế nào? Cách mò mẫm: vặn thử một núm sang phải, chạy lại mô hình, đo độ sai; vặn sang trái, chạy lại, đo lại. Một mạng nơ-ron có hàng triệu đến hàng tỷ núm - mỗi vòng chỉnh sẽ tốn hàng tỷ lần chạy mô hình, chỉ để biết nên xoay mỗi núm về bên nào.
Toán học cho ta một "giác quan" tốt hơn hẳn: với mỗi núm, không cần vặn thử vẫn biết trước nếu vặn nhẹ sang phải thì độ sai tăng hay giảm, và nhạy đến mức nào. Giác quan đó là đạo hàm (derivative). Và điều đáng ngạc nhiên hơn, xin để dành đến mục 7: nhờ chain rule, hàng tỷ câu hỏi "núm này nên xoay bên nào" được trả lời trong cùng một lượt, với chi phí chỉ gấp vài lần so với một lần chạy mô hình.
Đây là mảnh ghép toán cuối cùng bạn cần trước khi bước vào hàm mất mát (Bài 10) và gradient descent (Bài 11).
2. Đạo hàm: tốc độ thay đổi tức thời
2.1. Đồng hồ tốc độ trên xe
Bạn chạy xe từ nhà đến quán cà phê. Quãng đường đã đi là một hàm theo thời gian. Con số trên đồng hồ tốc độ - 40 km/h - không nói bạn đã đi bao xa; nó nói ngay khoảnh khắc này quãng đường đang tăng nhanh cỡ nào: "cứ đà này, mỗi giờ thêm 40 km".
Tốc độ chính là đạo hàm của quãng đường theo thời gian. Tổng quát: đạo hàm của hàm tại một điểm cho biết khi đầu vào nhích lên một chút xíu, đầu ra thay đổi nhanh chậm ra sao. Trên đồ thị, đó là độ dốc (slope) của đường cong tại điểm ấy.
2.2. Tự tay "đo" đạo hàm của f(x) = x²
Chưa cần công thức nào, bạn vẫn đo được đạo hàm bằng số. Lấy tại , ở đó . Nhích thêm một lượng nhỏ rồi xem thay đổi bao nhiêu so với mức nhích:
| Mức nhích | Thay đổi | Tỷ số thay đổi / nhích | |
|---|---|---|---|
| 0,1 | 1,21 | 0,21 | 2,1 |
| 0,01 | 1,0201 | 0,0201 | 2,01 |
| 0,001 | 1,002001 | 0,002001 | 2,001 |
Mức nhích càng nhỏ, tỷ số càng sát về 2. Ta nói đạo hàm của tại bằng 2, ký hiệu . Ý nghĩa thực dụng: quanh , đầu vào nhích 1 phần thì đầu ra nhích khoảng 2 phần.
Tỷ số ở cột cuối có tên riêng: thương số sai phân (difference quotient) - độ dốc của đoạn thẳng nối hai điểm trên đồ thị; sách Mathematics for Machine Learning xây dựng khái niệm đạo hàm từ đúng đại lượng này. Cho nhỏ dần, hai điểm sáp lại nhau, đoạn thẳng trở thành tiếp tuyến và độ dốc của nó là đạo hàm. Sách Dive into Deep Learning cũng mở đầu chương giải tích bằng đúng kiểu thí nghiệm số này - với hàm , cũng tại , và tỷ số cũng tiến về 2.
f(x) = x² .
▲ .
| .
| . ← tại x = 1: dốc lên,
| _. độ dốc = 2
| _ .
| _ .
| ~ .
+---·-------------► x
0 1
🔧 Thử ngay: Tính tay tỷ số tại với : và , nên 4,01. Rất gần 4 - đúng bằng . Quy luật: đạo hàm của tại điểm bất kỳ là .
Các hàm quen thuộc có công thức tính nhanh như vậy (đạo hàm của là , của là ). Trong loạt bài này bạn không cần thuộc bảng công thức - mục 8 sẽ giải thích vì sao; chỉ cần nhớ cho các ví dụ phía dưới.
⚠️ Lưu ý nhỏ: Thí nghiệm "cho nhỏ dần" là một ước lượng thuyết phục chứ chưa phải chứng minh chặt chẽ. Định nghĩa chính thức của đạo hàm dùng khái niệm giới hạn (limit): giá trị mà tỷ số tiến về khi tiến về 0. Trực giác "nhích một chút, xem đổi bao nhiêu" là tất cả những gì bạn cần cho các bài sau.
3. Dấu của đạo hàm cho biết đường nào đi xuống
Sương mù dày đặc, bạn đứng trên sườn núi - hình ảnh người xuống núi ở Bài 01. Bạn không thấy chân núi, cũng không cần biết dốc chính xác bao nhiêu độ; bạn chỉ cần biết phía nào là xuống. Với mục tiêu "giảm độ sai" cũng vậy: thứ quý giá nhất ở đạo hàm không phải con số chính xác, mà là cái dấu của nó.
| Đạo hàm tại điểm đang đứng | Hàm đang... | Muốn giảm giá trị hàm thì... |
|---|---|---|
| Dương (> 0) | đi lên khi tăng | giảm (lùi lại) |
| Âm (< 0) | đi xuống khi tăng | tăng (tiến tới) |
| Bằng 0 | phẳng tại chỗ | đứng yên - có thể đang ở đáy |
Kiểm chứng với (đồ thị hình chữ U, đáy tại ), dùng công thức :
- Tại : → muốn xuống đáy phải giảm . Đúng: đáy nằm bên trái.
- Tại : → muốn xuống đáy phải tăng . Đúng: đáy nằm bên phải.
- Tại : → đang ở đáy.
Quy tắc rút gọn đáng giá cả bài: đi ngược dấu đạo hàm, với một bước đủ nhỏ, thì hàm giảm. "Cảm nhận độ dốc dưới chân" của người xuống núi chính là tính đạo hàm; "bước về phía dốc xuống" là đi ngược dấu của nó.
⚠️ Lưu ý nhỏ: Đạo hàm bằng 0 chỉ nói "chỗ này phẳng", chưa chắc đã là đáy. Với (chữ U úp ngược), đạo hàm tại cũng bằng 0 - nhưng đó là đỉnh. Bài 10 và Bài 11 sẽ gặp thêm những chỗ phẳng "giả" như điểm yên ngựa trên địa hình loss.
4. Đạo hàm riêng: mỗi lần chỉ hỏi một núm
Lợi nhuận của một quán cà phê phụ thuộc vào cả giá bán lẫn chi phí quảng cáo. Chủ quán hỏi: "Tăng giá 1 nghìn thì lợi nhuận đổi bao nhiêu - giả sử quảng cáo giữ nguyên?" Giữ một thứ cố định để hỏi riêng thứ kia: đó chính là cách toán học xử lý hàm nhiều biến.
Độ sai của mô hình phụ thuộc hàng triệu núm cùng lúc, nhưng cách làm không đổi: mỗi lần chỉ hỏi một núm. Muốn biết núm thứ ảnh hưởng ra sao, ta giữ nguyên mọi núm còn lại và chỉ nhích riêng núm đó, rồi đo tốc độ thay đổi y như mục 2. Kết quả gọi là đạo hàm riêng (partial derivative), ký hiệu . Chữ (đọc là "partial") cố tình viết "cong" khác chữ , để nhắc rằng còn nhiều biến khác đang bị giữ cố định.
Ví dụ nhỏ: .
- Hỏi núm (coi như hằng số): phần đứng im, chỉ chuyển động → .
- Hỏi núm (coi như hằng số): phần đứng im → .
Tại điểm : nhích một chút thì tăng với tốc độ ; nhích một chút thì tăng với tốc độ . Núm đang "nhạy" hơn núm - và đó chính là thông tin để quyết định nên chỉnh núm nào mạnh tay hơn.
5. Gradient: la bàn chỉ hướng dốc nhất
Hỏi xong từng núm, bạn có một danh sách các tốc độ. Nhưng người xuống núi chỉ bước được một bước - kết hợp tất cả câu trả lời thế nào để biết bước về hướng nào?
Gom mọi đạo hàm riêng vào một vector (đúng kiểu "danh sách con số" của Bài 06):
Vector này là gradient (ký hiệu , đọc là "nabla"). Nó không chỉ là danh sách cho tiện, mà có một tính chất hình học rất đáng giá: tại điểm đang đứng, gradient chỉ đúng hướng làm hàm tăng nhanh nhất, và độ dài của nó cho biết dốc gắt đến đâu. Đó là chiếc la bàn của mô hình.
Chỉ có điều, la bàn này lại chỉ về hướng lên dốc nhất. Muốn giảm hàm nhanh nhất, hãy bước theo hướng ngược gradient - toàn bộ linh hồn của thuật toán gradient descent (hạ dốc theo gradient) mà Bài 11 sẽ khai thác triệt để.
Ví dụ với "lòng chảo" (đáy tại gốc tọa độ), đứng tại điểm :
- ; → gradient .
- Hướng ngược gradient : giảm cả lẫn , và giảm "mạnh tay" gấp đôi - hợp lý, vì ta đang đứng xa đáy theo trục hơn.
Nhìn lòng chảo f = x² + y² từ trên xuống
(mỗi vòng là một đường đồng mức, như bản đồ địa hình):
┌───────────────────┐
│ ╭─────────╮ │ ↗ gradient [2, 4]: hướng LÊN dốc
│ ╭│ ╭───╮ ●│╮ │ (luôn cắt vuông góc các vòng)
│ ││ │ ⊙ │ ││ │ ⊙ = đáy (0, 0)
│ ╰│ ╰───╯ │╯ │ ● = (1, 2): đang đứng đây
│ ╰─────────╯ │ ↙ đi ngược gradient [−2, −4]
└───────────────────┘ để XUỐNG đáy
Một chi tiết đẹp mà bản đồ địa hình nào cũng thể hiện: mũi tên gradient luôn cắt vuông góc các đường đồng mức. Đi dọc theo một vòng đồng mức thì độ cao không đổi; muốn lên (hay xuống) nhanh nhất, phải cắt ngang các vòng.
🔧 Thử ngay: Với cùng lòng chảo , tính gradient tại : [6, 2]. Hướng xuống dốc nhanh nhất là : lần này núm cần chỉnh mạnh gấp 3 lần núm , vì ta đang xa đáy theo trục hơn.
⚠️ Lưu ý nhỏ: Gradient là thông tin cục bộ - nó chỉ mô tả địa hình ngay quanh chỗ đang đứng. Bước một bước nhỏ theo hướng ngược gradient thì hàm giảm; bước quá dài có thể trượt qua đáy sang sườn bên kia. "Bước dài bao nhiêu" chính là learning rate, chủ đề của Bài 11.
6. Chain rule: đạo hàm của hàm lồng trong hàm
6.1. Xăng tăng giá, rau ngoài chợ tăng bao nhiêu?
Giá rau không phụ thuộc trực tiếp vào giá xăng, mà qua một mắt xích trung gian là chi phí vận chuyển:
flowchart LR
X["giá xăng<br/>tăng 1.000 đ/lít"] -- "mỗi chuyến hàng đắt thêm 200.000 đ" --> C["chi phí vận chuyển<br/>tăng 200.000 đ/chuyến"]
C -- "cứ đắt thêm 100.000 đ/chuyến, rau tăng 500 đ/kg" --> R["giá rau<br/>tăng 1.000 đ/kg"]
Giả sử tiểu thương cho bạn biết hai "tốc độ" cục bộ:
- Xăng tăng 1.000 đồng/lít → chi phí mỗi chuyến chở hàng tăng 200.000 đồng.
- Chi phí mỗi chuyến tăng 100.000 đồng → giá rau tăng 500 đồng/kg.
Vậy xăng tăng 1.000 đồng/lít thì giá rau tăng bao nhiêu? Chuyến hàng đắt thêm 200.000 = 2 lần mức "100.000", nên rau tăng đồng/kg. Bạn vừa nhân hai tốc độ dọc theo dây chuyền:
Đó chính là chain rule (quy tắc dây chuyền / quy tắc mắt xích): đạo hàm của một chuỗi hàm lồng nhau bằng tích các đạo hàm của từng mắt xích. Ghi bằng ký hiệu: nếu phụ thuộc , và phụ thuộc , thì
⚠️ Lưu ý nhỏ: Công thức trên nhìn như hai "phân số" rút gọn cho nhau - một cách nhớ tiện, nhưng không phải phép rút gọn thật: là ký hiệu của một đạo hàm, không phải phép chia hai con số.
6.2. Kiểm chứng bằng số
Lấy với - tức là hàm lồng: bên trong nhân 3, bên ngoài bình phương.
- Mắt xích ngoài: .
- Mắt xích trong: .
- Chain rule: . Tại : 18.
Đối chiếu bằng đường vòng: thay thẳng vào được , đạo hàm là - tại cũng ra 18. Khớp! Cái hay của chain rule là khi chuỗi dài cả trăm mắt xích, ta không cần (và không thể) "thay thẳng" như vậy nữa - cứ nhân dồn từng mắt xích là xong.
7. Chain rule là trái tim của backpropagation
Quay lại câu hỏi mở đầu bài: núm nằm ở tầng đầu tiên, còn loss nằm ở tận cuối. Vặn thì loss đổi bao nhiêu? Một mạng nơ-ron sâu (Bài 01) chính là chuỗi hàm lồng nhau rất dài: dữ liệu đi qua tầng 1, kết quả đó vào tầng 2, rồi tầng 3... và cuối cùng đổ vào hàm mất mát (loss) đo độ sai. Trong sơ đồ dưới, mũi tên liền là lượt xuôi (tính dự đoán), mũi tên đứt là lượt ngược (nhân dồn tốc độ từng mắt xích):
flowchart LR
W1(("núm w₁")) --> T1
X["đầu vào"] --> T1["tầng 1"]
T1 --> T2["tầng 2<br/>núm w₂"]
T2 --> T3["tầng 3<br/>núm w₃"]
T3 --> P["dự đoán"]
P --> L["loss<br/>(độ sai)"]
L -. "(1) ∂loss/∂tầng 3" .-> T3
T3 -. "(2) × ∂tầng 3/∂tầng 2" .-> T2
T2 -. "(3) × ∂tầng 2/∂tầng 1" .-> T1
T1 -. "(4) × ∂tầng 1/∂w₁ = gradient của w₁" .-> W1
Đúng bài toán "giá xăng → giá rau", chỉ là dây chuyền dài hơn: nhân dồn tốc độ của từng mắt xích, lần ngược từ loss về tầng 1:
Thuật toán tổ chức việc "nhân dồn ngược chiều" này một cách hiệu quả, cho mọi tham số cùng lúc, được gọi là backpropagation (lan truyền ngược): dữ liệu chạy xuôi qua chuỗi khi dự đoán, còn đạo hàm được tính bằng cách đi ngược chuỗi đó, và phần lớn tính toán quy về các phép nhân ma trận quen thuộc từ Bài 06. Vòng lặp huấn luyện của các mạng nơ-ron trong loạt bài này lặp đi lặp lại hai nhịp: xuôi để đoán, ngược để tính gradient, rồi chỉnh núm ngược hướng gradient.
Điều bất ngờ nằm ở chi phí. Cách mò mẫm ở mục 1 phải chạy mô hình một lần cho mỗi núm - hàng tỷ lần. Lan truyền ngược tính toàn bộ gradient trong một lượt, và một kết quả kinh điển của Baur và Strassen (1983) - thường gọi là nguyên lý "gradient rẻ" (cheap gradient principle) - cho biết chi phí ấy không vượt quá một hằng số nhỏ (khoảng 5 lần) chi phí tính hàm một lần, bất kể mô hình có bao nhiêu núm. Không có chain rule thì không có cách thực tế nào để biết hàng tỷ núm nên xoay hướng nào; theo nghĩa đó, nó là trái tim của deep learning.
Vì sao huấn luyện tốn bộ nhớ hơn dự đoán nhiều đến vậy?
Để nhân dồn ngược, lượt ngược phải dùng lại các giá trị trung gian mà lượt xuôi đã tính (đầu ra của từng tầng), nên chúng phải được giữ trong bộ nhớ cho đến khi lan truyền ngược xong. Lượng giá trị này tăng theo số tầng và theo kích thước batch (Bài 11). Vì thế mạng sâu hơn hay batch lớn hơn dễ gây lỗi hết bộ nhớ (out-of-memory) khi train, trong khi cùng mô hình ấy chạy dự đoán vẫn nhẹ nhàng.
8. Autograd: để thư viện tính đạo hàm thay bạn
Tin vui cuối bài: bạn hầu như không bao giờ phải tự tay làm những phép nhân dồn ở mục 7. Các thư viện deep learning như PyTorch, TensorFlow, JAX có sẵn automatic differentiation (tự động vi phân, gọi tắt autograd): khi bạn viết các phép tính, thư viện âm thầm ghi lại một đồ thị tính toán (computational graph) - sơ đồ "giá trị nào được tính từ giá trị nào" - rồi khi bạn yêu cầu, nó tự chạy ngược đồ thị đó và áp dụng chain rule giúp bạn.
Minh họa bằng PyTorch, tính lại đúng ví dụ tại của mục 2:
import torch
x = torch.tensor(1.0, requires_grad=True) # "hãy theo dõi x giúp tôi"
y = x ** 2 # tính xuôi: y = 1.0
y.backward() # chạy ngược, áp dụng chain rule
print(x.grad) # tensor(2.) - đúng bằng f'(1) = 2
Ba dòng lệnh thay cho cả bảng "nhích nhỏ dần". Với mạng hàng tỷ tham số, cũng vẫn chỉ là một lời gọi backward().
🔧 Thử ngay: Đổi
1.0thành3.0rồi chạy lại:x.gradphải in ratensor(6.)- đúng . Thử tiếpy = x ** 3tại : kết quảtensor(12.), khớp công thức .
Ý tưởng này không hề mới: sách Dive into Deep Learning dẫn tài liệu sớm nhất về tự động vi phân từ năm 1964 (Wengert), còn các ý tưởng cốt lõi của backpropagation hiện đại đến từ một luận án tiến sĩ năm 1980 và được phát triển tiếp vào cuối thập niên 1980 - rất lâu trước khi các thư viện autograd trở thành chuyện thường ngày.
Vậy học đạo hàm để làm gì, nếu máy tính hộ hết? Để hiểu chuyện gì đang diễn ra: khi Bài 11 nói về "learning rate quá lớn làm loss nhảy loạn", hay Bài 10 giải thích vì sao hàm mất mát phải cho ra tín hiệu độ dốc dùng được, bạn sẽ thấy tất cả quy về những trực giác của bài hôm nay. Bạn cần hiểu la bàn chỉ gì; còn việc chế tạo la bàn, cứ để thư viện lo.
Tóm tắt bài học
- Huấn luyện = chỉnh núm vặn để giảm độ sai; đạo hàm cho biết trước "nhích núm này thì độ sai tăng hay giảm, nhạy cỡ nào" mà không cần vặn thử.
- Đạo hàm = tốc độ thay đổi tức thời = độ dốc; đo được bằng số bằng cách nhích đầu vào một lượng nhỏ dần (với tại , tỷ số tiến về 2).
- Dấu đạo hàm là kim chỉ nam: dương → hàm đang tăng → muốn giảm thì lùi; âm → tiến; bằng 0 → có thể đang ở đáy. Quy tắc vàng: đi ngược dấu đạo hàm, với một bước đủ nhỏ, thì hàm giảm.
- Hàm nhiều biến: đạo hàm riêng hỏi từng núm một (giữ các núm khác cố định); gradient gom tất cả thành một vector chỉ hướng tăng nhanh nhất (và cắt vuông góc các đường đồng mức) → đi ngược gradient để giảm nhanh nhất (nền tảng của Bài 11).
- Chain rule: đạo hàm của chuỗi hàm lồng nhau = tích đạo hàm từng mắt xích (xăng → vận chuyển → giá rau).
- Mạng nơ-ron là chuỗi hàm lồng rất dài; backpropagation = áp dụng chain rule ngược chuỗi để tính gradient cho mọi tham số trong một lượt, với chi phí chỉ gấp một hằng số nhỏ so với một lượt chạy xuôi - trái tim của deep learning.
- Autograd trong PyTorch/TensorFlow/JAX tự ghi đồ thị tính toán và tính đạo hàm thay bạn; nhiệm vụ của bạn là hiểu ý nghĩa, không phải tính tay.
Câu hỏi tự kiểm tra
- Giải thích cho một người bạn không học toán: "tốc độ xe là đạo hàm của quãng đường" nghĩa là gì?
- Tính tay: với tại , lấy và tính tỷ số . Kết quả gần con số nào? Đối chiếu với công thức .
- Đang đứng tại điểm có đạo hàm bằng . Hàm đang tăng hay giảm khi tăng? Muốn giảm giá trị hàm, bạn nên tăng hay giảm ?
- Tính tay: với lòng chảo , tính gradient tại điểm . Từ điểm đó, hướng bước để hàm giảm nhanh nhất là hướng nào? Núm nào cần chỉnh mạnh tay hơn, vì sao?
- Dùng chain rule tính đạo hàm của với tại , rồi kiểm chứng bằng cách khai triển và lấy đạo hàm trực tiếp.
- Vì sao nói "không có chain rule thì không huấn luyện được mạng nơ-ron nhiều tầng"? Vẽ lại sơ đồ chuỗi tầng và chỉ ra chain rule được áp dụng ở đâu.
Đọc thêm
Nguồn nền tảng của bài:
| Nguồn | Đọc phần nào |
|---|---|
| Sách Dive into Deep Learning (d2l.ai) | Chương 2.4 - Calculus: đạo hàm bằng thí nghiệm số, đạo hàm riêng, gradient, chain rule; Chương 2.5 - Automatic Differentiation: autograd, đồ thị tính toán và đôi nét lịch sử; Chương 5.3 - Forward Propagation, Backward Propagation, and Computational Graphs: vì sao train tốn bộ nhớ hơn dự đoán |
| Sách Mathematics for Machine Learning | Chương 5 (phần đầu) - Vector Calculus: difference quotient, quy tắc đạo hàm, ví dụ chain rule , đạo hàm riêng và gradient |
Nguồn online bổ sung (miễn phí):
- Essence of Calculus - 3Blue1Brown (playlist YouTube) - loạt video hoạt hình giúp "nhìn thấy" giải tích; đặc biệt xem Chapter 4 về chain rule.
- Tài liệu autograd của PyTorch - hướng dẫn chính thức, chạy thử đoạn code ở mục 8 và mở rộng thêm.
- Machine Learning cơ bản - blog tiếng Việt của Vũ Hữu Tiệp, có phần ôn giải tích cho ML.
- Who Invented the Reverse Mode of Differentiation? - Andreas Griewank (PDF) - dành cho ai tò mò lịch sử: lan truyền ngược được "phát minh lại" nhiều lần ra sao, và nguyên lý "gradient rẻ" đến từ đâu.
Bài tiếp theo: Hàm mất mát và bài toán tối ưu - đã có la bàn (gradient), giờ cần đích đến - hàm mất mát cho từng loại bài toán, và bức tranh tối ưu hóa mà nó tạo ra.