Gradient descent — vòng lặp chỉnh trọng số cho bớt sai
Huấn luyện là vòng lặp forward, tính loss, lấy gradient rồi chỉnh trọng số ngược hướng dốc. Learning rate quyết định mỗi bước đi xa bao nhiêu.
TL;DR: Huấn luyện là vòng lặp bốn bước lặp hàng triệu lần: cho dữ liệu qua model để ra dự đoán (forward), tính loss để đo cái sai, tính gradient — hướng cần chỉnh mỗi trọng số để loss giảm, rồi cập nhật w = w - lr * gradient. Batch là nhúm mẫu nhỏ dùng trong một bước; epoch là một lượt đi hết toàn bộ tập train. Learning rate là siêu tham số kiểm soát độ dài mỗi bước chỉnh trọng số — phải chọn trước khi bắt đầu train. Khi train xong, trọng số đóng băng và model chuyển sang inference. Đường cong loss theo epoch là công cụ đọc chính để chẩn đoán vòng lặp có đang chạy đúng không.
Bài 03 trao cho bạn một công cụ đắc lực: loss — một con số duy nhất đo tổng sai lệch của model. Mục tiêu train là làm con số đó nhỏ lại.
Nhưng làm thế nào? Model có thể có hàng triệu trọng số — mỗi trọng số là một "núm vặn". Vặn nhầm núm, loss tăng thay vì giảm. Vặn đúng nhưng quá mạnh, model bỏ qua đáy và đứng ở phía đối diện — cao hơn điểm xuất phát. Câu hỏi thực sự là: chỉnh núm nào, theo hướng nào, và mỗi lần chỉnh bao nhiêu?
Đây là toàn bộ nội dung của "train" — và thuật toán trả lời câu hỏi đó được gọi là gradient descent.
Loss là con số duy nhất tóm tắt tổng sai lệch của model trên toàn bộ một batch dữ liệu. Gradient descent dùng con số này làm la bàn: mỗi bước cập nhật trọng số đều nhằm làm loss nhỏ hơn.
Train là pha model còn đang điều chỉnh trọng số — tốn kém về tính toán. Inference là pha trọng số đã đóng băng; model chỉ chạy forward pass để dự đoán. Gradient descent thuộc hoàn toàn về pha train.
1. Xuống dốc trong sương mù
Hình dung bạn đứng giữa một vùng đồi núi trong đêm tối. Mục tiêu là xuống thung lũng thấp nhất — nhưng bạn không thấy toàn cảnh, chỉ sờ được độ dốc ngay dưới bàn chân. Chiến lược hợp lý: bước ngược chiều dốc, từng bước nhỏ một. Không cần biết thung lũng ở đâu — gradient descent hoạt động y hệt vậy.
| Xuống dốc trong sương mù | Gradient descent |
|---|---|
| Vùng đồi núi | Không gian trọng số của model |
| Độ cao tại mỗi điểm | Giá trị loss |
| Thung lũng thấp nhất | Loss tối thiểu — mục tiêu train |
| Độ dốc ngay dưới bàn chân | Gradient của mỗi trọng số |
| Một bước đi | Một lần cập nhật trọng số |
| Độ dài bước chân | Learning rate |
Gradient = "độ dốc dưới bàn chân" cho từng trọng số. Cập nhật = bước ngược chiều dốc. Learning rate = độ dài mỗi bước.
2. Bốn bước của vòng lặp huấn luyện
Mỗi lần cập nhật trọng số đi qua đúng bốn bước, rồi lặp lại từ đầu trên batch tiếp theo:

Bước 1 — Forward pass: Cho một nhúm dữ liệu (batch) đi qua mạng từ input tới output. Kết quả là dự đoán của model — đây là pha duy nhất cũng xảy ra trong inference.
Bước 2 — Tính loss: So sánh dự đoán với nhãn đúng bằng hàm loss đã chọn. Kết quả là một con số duy nhất — tín hiệu học của toàn bộ bước.
Bước 3 — Tính gradient: Với mỗi trọng số, tính xem "nếu tăng trọng số này một chút, loss tăng hay giảm?". Con số đó là gradient của trọng số.
Backpropagation là kỹ thuật tính gradient cho mọi trọng số cùng lúc một cách hiệu quả — chi tiết ngoài phạm vi khoá.
Bước 4 — Cập nhật trọng số: Áp công thức sau cho mỗi trọng số:
w <- w - lr * gradient(w)
Trọng số mới bằng trọng số cũ trừ đi learning rate nhân gradient. Vì cập nhật theo hướng ngược gradient (trừ, không cộng), loss có xu hướng giảm sau mỗi bước — miễn là learning rate được chọn hợp lý (mục 4). Đó chính là ý nghĩa của "xuống dốc". Bốn bước này lặp lại liên tục trên từng batch cho đến khi loss không còn giảm đáng kể.
3. Batch và epoch — tại sao không dùng cả tập mỗi bước?
Tại sao mỗi bước cập nhật chỉ dùng một batch nhỏ thay vì toàn bộ tập huấn luyện?
Khi tập dữ liệu có hàng triệu mẫu, tính gradient trên toàn bộ tập mỗi bước cập nhật đòi hỏi đọc và xử lý hàng triệu mẫu trước khi chỉnh được một lần — chi phí tính toán khổng lồ và không cần thiết. Gradient tính trên một nhúm nhỏ ngẫu nhiên (batch) vẫn đủ chỉ đúng hướng xuống dốc, dù có nhiễu hơn, và cho phép cập nhật trọng số nhiều lần trong một epoch thay vì chỉ một lần.
Hai khái niệm cần nắm rõ trước khi đọc pseudocode:
- Batch: tập con mẫu dùng trong một bước cập nhật. Gradient được tính trên batch này; số bước cập nhật mỗi epoch bằng kích thước tập train chia kích thước batch.
- Epoch: một lượt đi hết toàn bộ tập huấn luyện. Model đã thấy mỗi mẫu đúng một lần sau khi kết thúc một epoch. Train thường chạy hàng chục đến hàng trăm epoch.
for epoch in 1..N_EPOCHS:
shuffle(train_data)
for batch in split(train_data, batch_size):
preds = forward(model, batch.inputs) // step 1: run model
loss = compute_loss(preds, batch.labels) // step 2: measure error
grads = backprop(model, loss) // step 3: gradient per weight
update_weights(model, grads, lr) // step 4: w = w - lr * g
val_loss = evaluate(model, validation_data)
log("epoch", epoch, "val_loss", val_loss) // track learning curve
4. Learning rate quyết định mỗi bước dài ngắn thế nào?
Learning rate (lr) là hằng số nhỏ bạn chọn trước khi bắt đầu train. Nó điều chỉnh mỗi bước cập nhật trọng số đi xa bao nhiêu theo hướng gradient chỉ ra. Giá trị thường dùng nằm trong khoảng từ 0.0001 đến 0.1 tuỳ bài toán.
Model đang train ổn — loss giảm đều qua từng epoch. Bạn quyết định tăng learning rate lên gấp 100 lần. Đường cong loss sẽ có hình dạng như thế nào trong các epoch tiếp theo? Viết dự đoán ra trước khi đọc phần dưới.
Learning rate quá lớn: Mỗi bước chỉnh trọng số quá mạnh, nhảy vọt qua đáy thung lũng và đứng ở phía đối diện — cao hơn điểm xuất phát. Loss dao động mạnh lên xuống giữa các epoch, hoặc thậm chí phóng lớn dần theo từng bước. Vòng lặp chạy bình thường về mặt kỹ thuật — không báo lỗi — nhưng model không hội tụ về đâu cả.
Learning rate quá nhỏ: Mỗi bước chỉnh trọng số cực nhỏ. Loss vẫn giảm nhưng chậm đến mức trông như đứng yên — sau hàng trăm epoch vẫn còn cao. Chi phí tính toán bỏ ra lớn nhưng kết quả thu về gần như không có.
Learning rate hợp lý: Loss giảm tương đối nhanh ở những epoch đầu, sau đó phẳng dần khi model tiến gần vùng tối ưu. Đây là hình dạng lành mạnh mà bạn muốn thấy.
5. Đường cong loss đọc như thế nào?
Đường cong loss (hay learning curve) là biểu đồ đơn giản: trục ngang là epoch, trục dọc là giá trị loss. Đây là công cụ đọc chính khi train — không phải để ngắm, mà để chẩn đoán sức khoẻ của vòng lặp.
Thường người ta vẽ hai đường trên cùng một biểu đồ:
- Training loss: loss tính trên dữ liệu model đang học.
- Validation loss: loss tính trên tập dữ liệu chưa dùng trong train, chạy cuối mỗi epoch.
Hình dạng lành mạnh: cả hai đường giảm tương đối nhanh rồi phẳng dần, validation loss bám sát training loss.
Triệu chứng của learning rate sai — phần bài này sở hữu:
- Quá lớn: loss dao động mạnh lên xuống qua các epoch, hoặc phóng to dần. Hai đường cong không hội tụ về đâu cả.
- Quá nhỏ: loss giảm không đáng kể, đường cong gần như nằm ngang từ rất sớm dù cả hai đường vẫn đang giảm từ từ.
Hai kiểu hỏng khác — model thiếu sức chứa (underfit) và model ghi nhớ tập train quá mức (overfit) — có triệu chứng khác nhau trên đường cong. Bạn sẽ tự chẩn đoán cả ba ca đó ở bài mini-challenge.
6. Ba hiểu lầm phổ biến
❌ Nhầm 1: "Train là nạp dữ liệu vào và model tự nhớ."
✅ Model không lưu dữ liệu huấn luyện. Nó điều chỉnh trọng số qua hàng triệu bước gradient descent. Sau train, những gì còn lại là bộ trọng số — không phải dữ liệu gốc.
❌ Nhầm 2: "Loss không giảm → chắc tại dữ liệu xấu."
✅ Thủ phạm đầu tiên cần kiểm tra là learning rate. Quá lớn thì loss dao động hoặc phóng to; quá nhỏ thì loss giảm không thấy được. Sau khi đã điều chỉnh learning rate và loại trừ vấn đề kiến trúc model, mới xét đến chất lượng dữ liệu.
❌ Nhầm 3: "Mỗi bước cập nhật nhìn hết toàn bộ dữ liệu."
✅ Mỗi bước cập nhật chỉ dùng một batch nhỏ — thường vài chục đến vài trăm mẫu. Toàn bộ dữ liệu được quét hết sau đúng một epoch. Train thường chạy hàng chục đến hàng trăm epoch, tức hàng triệu bước cập nhật trọng số.
7. Đào sâu
Gradient descent có lịch sử lâu hơn deep learning nhiều thập kỷ:
- A Stochastic Approximation Method — Robbins & Monro, 1951 — bài báo gốc đề xuất thuật toán tìm nghiệm của phương trình khi chỉ quan sát được tín hiệu nhiễu (không phải giá trị chính xác), và chứng minh chuỗi cập nhật vẫn hội tụ đến nghiệm đúng. "Stochastic" ám chỉ quan sát bị nhiễu, không phải mini-batch. Liên hệ với SGD: gradient tính trên một batch ngẫu nhiên chính là ước lượng nhiễu của gradient thật trên toàn bộ dữ liệu — một trường hợp riêng của framework này.
Deep learning kết hợp gradient descent với backpropagation (Rumelhart, Hinton & Williams, 1986, Nature) để tính gradient hiệu quả trên mạng nhiều tầng — đây là nền tảng của mọi framework train hiện đại như PyTorch và JAX.
8. Liên hệ các bài khác
- Bài 03 — Loss: đo cái sai thành một con số — gradient descent dùng loss làm la bàn. Không có loss, không có tín hiệu để chỉnh trọng số.
- Bài 02 — Xếp lớp và phi tuyến — sức chứa của mạng quyết định loss có thể xuống thấp đến đâu; thiếu sức chứa là một trong ba ca hỏng bài 07 yêu cầu chẩn đoán.
- Bài 05 — Tham số và siêu tham số — learning rate là siêu tham số do người chọn; bài đó đào sâu sự phân biệt này và ý nghĩa thực tế của "7 tỷ tham số".
- Bài 07 — Mini-challenge: đọc đường cong loss — bạn sẽ dùng kiến thức từ bài này để tự chẩn đoán ba ca huấn luyện hỏng từ đường cong thật.
9. Tóm tắt
- Công thức cập nhật: trọng số mới = trọng số cũ − learning_rate × gradient.
- Learning rate quá lớn: loss dao động không hội tụ; quá nhỏ: loss giảm cực chậm.
- Đường cong loss theo epoch là công cụ chẩn đoán chính — hình lành mạnh là giảm nhanh rồi phẳng dần.
- Khi train xong, trọng số đóng băng; model chuyển sang inference, không điều chỉnh gì thêm.
10. Tự kiểm tra
Q1Tại sao mỗi bước cập nhật trọng số chỉ dùng một batch nhỏ thay vì toàn bộ tập huấn luyện?▸
Tính gradient trên toàn bộ tập với hàng triệu mẫu sẽ đòi hỏi đọc và xử lý toàn bộ dữ liệu trước khi chỉnh được một lần — chi phí không thực tế với tập lớn. Gradient tính trên batch nhỏ ngẫu nhiên vẫn đủ chỉ đúng hướng xuống dốc, dù có nhiễu hơn, và cho phép cập nhật trọng số nhiều lần trong một epoch thay vì chỉ một lần.
Q2Gradient trong gradient descent là gì? Tại sao cập nhật trọng số theo hướng ngược gradient (trừ đi) thay vì cộng vào?▸
Gradient là tập con số — mỗi trọng số có một con số riêng — cho biết: nếu tăng trọng số này một chút, loss tăng hay giảm và bao nhiêu. Cập nhật theo hướng ngược gradient (trừ đi) vì mục tiêu là giảm loss. Nếu gradient dương (tăng trọng số → loss tăng), ta trừ đi để giảm trọng số → loss giảm. Đây là ý nghĩa của "xuống dốc".
Q3Model đang train bỗng nhiên có loss phóng to dần qua từng epoch thay vì giảm. Thủ phạm đầu tiên cần kiểm tra là gì, và tại sao?▸
Thủ phạm đầu tiên là learning rate quá lớn. Khi learning rate quá lớn, mỗi bước cập nhật nhảy quá xa qua đáy thung lũng, đứng ở phía đối diện — cao hơn điểm xuất phát. Loss tăng thay vì giảm sau mỗi bước, dẫn đến đường cong phóng to. Kiểm tra bằng cách giảm learning rate xuống 10 đến 100 lần và quan sát vài epoch tiếp theo.
Q4Epoch khác batch ở điểm nào? Nếu tập train có 50.000 mẫu và batch_size bằng 500, một epoch có bao nhiêu bước cập nhật?▸
Batch là tập con mẫu dùng trong một bước cập nhật. Epoch là một lượt đi hết toàn bộ tập train — model đã thấy mỗi mẫu đúng một lần. Với 50.000 mẫu và batch_size bằng 500, một epoch có 100 bước cập nhật (50.000 chia 500). Train chạy nhiều epoch, nên tổng số bước cập nhật bằng 100 nhân số epoch.
Q5Sau khi train xong, model có tiếp tục điều chỉnh trọng số khi xử lý yêu cầu người dùng không? Điều gì xảy ra ở bước forward pass trong inference?▸
Không. Sau train, trọng số đóng băng hoàn toàn. Trong pha inference, model chỉ chạy forward pass — cho input qua các tầng để tính ra output. Không có bước tính gradient, không có bước cập nhật trọng số. Trọng số giữ nguyên từ lúc train kết thúc cho đến khi ai đó khởi động lại quá trình train.
Bài tiếp theo: Tham số và siêu tham số — 7 tỷ tham số nghĩa là gì
Bài này đáng gửi cho bạn học cùng?
Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.
Bài này có giúp bạn hiểu bản chất không?
Hỏi đáp về bài này
Chưa có câu hỏi
Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).
Đặt câu hỏi đầu tiên