Gradient descent tính tay từng bước

By Better Wise

Bài trước bạn đã có trong tay gradient: vector chỉ hướng hàm tăng nhanh nhất tại một điểm, và độ lớn của nó cho biết hàm dốc đến đâu. Câu hỏi thực chiến của một kỹ sư ML là: biết hướng tăng rồi thì làm gì? Trả lời: đi ngược lại, mỗi lần một bước nhỏ, lặp đi lặp lại. Đó chính là gradient descent, vòng lặp mà cả hồi quy tuyến tính lẫn mạng nơ-ron đều dùng. Hôm nay ta chạy nó bằng tay để thấy loss giảm sau từng vòng, chứ không tin vào con số do thư viện in ra.

Sau bài này bạn sẽ:

  • Viết đúng quy tắc cập nhật của gradient descent và giải thích vai trò của dấu trừ.
  • Chạy ba vòng lặp bằng tay trên một hàm hai biến, ghi lại giá trị hàm sau mỗi bước.
  • Đọc được xu hướng của loss và lý do nó giảm chậm dần.
  • Nhận ra hai tham số có thể tiến về đích với tốc độ rất khác nhau dù dùng chung một learning rate.

Từ "hướng dốc nhất" đến một bước cập nhật

Gradient $\nabla L(\theta)$ chỉ chiều làm loss tăng. Vậy muốn loss giảm, ta đi ngược chiều đó, với độ dài bước do learning rate $\alpha$ quyết định:

$$ \theta_{t+1} = \theta_t - \alpha \nabla L(\theta_t) $$

Ba thành phần cần nhớ: $\theta$ là tham số model (trong project sắp tới là weight và bias), $\nabla L(\theta)$ là gradient của loss, và $\alpha$ là learning rate. Dấu trừ là phần "thông minh" duy nhất của thuật toán: nếu bỏ dấu trừ, bạn đang leo lên chứ không phải đi xuống. Một vòng lặp gồm bốn việc lặp lại: tính gradient tại điểm hiện tại, cập nhật, tính loss tại điểm mới, ghi lại.

flowchart TD
    A["🎯<br/>Điểm khởi đầu"] --> B["📐<br/>Tính gradient"]
    B --> C["👣<br/>Cập nhật theta"]
    C --> D["📉<br/>Ghi loss mới"]
    D --> E{"Đủ vòng<br/>hoặc gradient ~ 0"}
    E -->|Chưa| B
    E -->|Rồi| F["✅<br/>Dừng"]

Note: Gradient descent không giải phương trình để tìm nghiệm, nó lặp để giảm dần loss. Vì vậy điều quan trọng khi tính tay không phải ra đáp án đẹp, mà là bảng giá trị sau mỗi vòng có giảm ổn định hay không.

Bài tập nhanh 1. Cho $f(x, y) = x^2 + 3y^2$. Tính gradient tại điểm $(1, -2)$. Nếu chạy một bước với $\alpha = 0{,}1$, điểm mới là gì?

Xem đáp án

$\nabla f = (2x,\ 6y)$, tại $(1, -2)$ là $(2, -12)$. Cập nhật: $x = 1 - 0{,}1 \cdot 2 = 0{,}8$ và $y = -2 - 0{,}1 \cdot (-12) = -0{,}8$. Lưu ý $y$ nhảy khá xa vì đạo hàm riêng theo $y$ có độ lớn gấp sáu lần.

Ba vòng lặp bằng tay trên $f(x, y) = x^2 + 3y^2$

Chọn hàm này vì nó giống một loss bậc hai: có cực tiểu tại $(0, 0)$ và độ cong hai trục khác nhau, đúng kiểu bài toán thật. Gradient là $\nabla f = (2x,\ 6y)$. Xuất phát tại $(2, 1)$, learning rate $\alpha = 0{,}1$, loss ban đầu $f(2, 1) = 4 + 3 = 7$.

  1. Vòng 1: gradient $(2 \cdot 2,\ 6 \cdot 1) = (4, 6)$. Cập nhật $x = 2 - 0{,}1 \cdot 4 = 1{,}6$, $y = 1 - 0{,}1 \cdot 6 = 0{,}4$. Loss mới: $f(1{,}6; 0{,}4) = 2{,}56 + 3 \cdot 0{,}16 = 3{,}04$.
  2. Vòng 2: gradient $(3{,}2,\ 2{,}4)$. Cập nhật $x = 1{,}6 - 0{,}32 = 1{,}28$, $y = 0{,}4 - 0{,}24 = 0{,}16$. Loss mới: $1{,}6384 + 0{,}0768 = 1{,}7152$.
  3. Vòng 3: gradient $(2{,}56,\ 0{,}96)$. Cập nhật $x = 1{,}28 - 0{,}256 = 1{,}024$, $y = 0{,}16 - 0{,}096 = 0{,}064$. Loss mới: $1{,}048576 + 0{,}012288 \approx 1{,}0609$.

Ghi lại thành bảng, đây là thứ bạn nên làm mỗi lần tính tay:

Vòng $x$ $y$ $\partial f/\partial x = 2x$ $\partial f/\partial y = 6y$ $f(x,y)$
0 2 1 4 6 7
1 1,6 0,4 3,2 2,4 3,04
2 1,28 0,16 2,56 0,96 1,7152
3 1,024 0,064 2,048 0,384 1,0609

Bài tập nhanh 2. Chạy tiếp vòng 4 từ $(1{,}024;\ 0{,}064)$ với cùng $\alpha = 0{,}1$. Loss có tiếp tục giảm không?

Xem đáp án

Gradient $(2{,}048;\ 0{,}384)$. Điểm mới: $x = 0{,}8192$, $y = 0{,}0256$. Loss $= 0{,}6711 + 3 \cdot 0{,}000655 \approx 0{,}6731$. Vẫn giảm, nhưng mức giảm chỉ còn khoảng $0{,}39$ so với $1{,}3$ ở vòng đầu.

Đọc bảng: loss giảm đều nhưng hai trục không đều

Nhìn cột loss: $7 \to 3{,}04 \to 1{,}715 \to 1{,}061$. Giảm mạnh rồi chậm lại, đúng như kỳ vọng, vì càng gần cực tiểu thì gradient càng nhỏ nên bước đi càng ngắn. Đây là lý do người ta hay vẽ loss theo số vòng lặp để biết quá trình có hội tụ hay không.

Nhìn cột $y$: nó lao về 0 nhanh hơn hẳn $x$, dù cả hai dùng chung $\alpha$. Nguyên nhân nằm ở độ cong: $\partial f/\partial y = 6y$ lớn gấp ba lần $2x$ tại cùng độ lớn, nên bước nhảy theo trục $y$ cũng lớn gấp ba. Trong project hồi quy tuyến tính, hiện tượng này là lý do feature có scale lớn thường nhận bước cập nhật lớn và dễ gây bất ổn, đó là nội dung bài sau sẽ khai thác.

Quy tắc cập nhật của gradient descent là theta mới bằng theta cũ trừ đi _____. Với f(x, y) = x^2 + 3y^2, đạo hàm riêng theo y là _____. Từ điểm (2, 1) với alpha = 0,1, sau vòng đầu tiên x bằng _____ và y bằng _____. Loss sau vòng đầu là _____, giảm từ 7.

Bài tập nhanh 3 (nối với project). Trong hồi quy tuyến tính một tham số, loss có dạng $L(w) = (w - 3)^2$, tức model đúng khi $w = 3$. Bắt đầu từ $w = 1$, $\alpha = 0{,}1$. Tính hai vòng cập nhật và cho biết loss đổi thế nào.

Xem đáp án

$\frac{dL}{dw} = 2(w - 3)$. Vòng 1: gradient $= -4$, $w = 1 + 0{,}4 = 1{,}4$, $L = 2{,}56$ (từ $4$). Vòng 2: gradient $= 2(1{,}4 - 3) = -3{,}2$, $w = 1{,}72$, $L = 1{,}6384$. Loss giảm và $w$ tiến về 3, đúng chiều mà ta muốn model học.

Bốn lỗi hay làm hỏng bảng tính tay

  • Trộn hai thời điểm. Phải tính toàn bộ gradient tại điểm cũ rồi mới cập nhật tất cả các biến cùng lúc. Cập nhật $x$ xong rồi lấy $x$ mới tính đạo hàm cho $y$ là sai thuật toán.
  • Quên dấu trừ. Nếu loss tăng sau mỗi vòng, kiểm tra dấu trước khi ngờ learning rate.
  • Làm tròn quá sớm. Giữ ít nhất bốn chữ số ở các vòng giữa, sai số nhỏ sẽ cộng dồn và làm bạn kết luận sai về hội tụ.
  • Chỉ ghi loss mà không ghi gradient. Gradient thu nhỏ dần là dấu hiệu hội tụ; thiếu nó bạn không phân biệt được "gần đích" với "bước quá nhỏ".

Một mẹo kiểm tra nhanh: loss mới phải nhỏ hơn loss cũ với $\alpha$ đủ nhỏ. Nếu không, dừng lại và soát bảng trước khi soát công thức.

Mang gì sang bài tiếp theo

  • Gradient descent là vòng lặp: tính gradient, đi ngược chiều nó một đoạn $\alpha$, ghi loss, lặp lại.
  • Trên $f(x, y) = x^2 + 3y^2$ từ $(2, 1)$ với $\alpha = 0{,}1$, loss đi $7 \to 3{,}04 \to 1{,}715 \to 1{,}061$ trong ba vòng.
  • Loss giảm chậm dần vì gradient nhỏ dần khi về gần cực tiểu.
  • Hai tham số có thể hội tụ với tốc độ khác nhau nếu độ cong của hàm khác nhau theo từng trục.

Bài sau, "Learning rate, dao động và phân kỳ", sẽ trả lời câu hỏi còn treo: nếu $\alpha$ không phải $0{,}1$ mà là $0{,}01$ hoặc $0{,}6$ thì bảng giá trị trên thay đổi ra sao, và khi nào loss bắt đầu nhảy lên thay vì giảm.

Front: Quy tắc cập nhật của gradient descent? Back: theta mới = theta cũ - alpha nhân gradient của loss tại theta cũ.

Front: Gradient chỉ theo hướng nào? Back: Hướng làm hàm tăng nhanh nhất tại điểm đang xét.

Front: Vì sao công thức cập nhật có dấu trừ? Back: Vì gradient chỉ chiều tăng, trừ đi để đi theo chiều giảm loss.

Front: Gradient của f(x, y) = x^2 + 3y^2? Back: (2x, 6y).

Front: Điểm khởi đầu và learning rate dùng trong ví dụ của bài? Back: (x, y) = (2, 1) và alpha = 0,1.

Front: Loss sau vòng 1 của ví dụ? Back: f(1,6; 0,4) = 3,04, giảm từ 7.

Front: Loss sau vòng 2 của ví dụ? Back: f(1,28; 0,16) = 1,7152.

Front: Loss sau vòng 3 của ví dụ? Back: f(1,024; 0,064) xấp xỉ 1,0609.

Front: Mỗi vòng lặp cần ghi lại những gì khi tính tay? Back: Giá trị các tham số, các đạo hàm riêng tại điểm đó, và loss tại điểm mới.

Front: Vì sao y tiến về 0 nhanh hơn x trong ví dụ? Back: Vì đạo hàm riêng theo y là 6y, lớn gấp ba lần 2x, nên bước theo trục y dài hơn.

Front: Vì sao loss giảm chậm dần qua các vòng? Back: Càng gần cực tiểu gradient càng nhỏ nên bước cập nhật càng ngắn.

Front: Dấu hiệu cho thấy quá trình đã hội tụ khi tính tay? Back: Gradient gần 0 và loss gần như không đổi giữa hai vòng liên tiếp.

Front: Trong ML, theta và L(theta) tương ứng với gì? Back: Theta là tham số của model (weight, bias), L là loss cần giảm.

Front: Lỗi thường gặp khi cập nhật nhiều biến? Back: Cập nhật lần lượt từng biến và dùng giá trị mới để tính gradient cho biến sau.