Project: Hồi quy tuyến tính với gradient descent
Mục tiêu: để đường loss tự chứng minh model đang học
Bài trước bạn đã chốt một điểm quan trọng: với hàm loss lồi thì gradient bằng 0 chỉ ra cực tiểu toàn cục, không có saddle point đáng lo. MSE của hồi quy tuyến tính đúng là hàm lồi như vậy, nên gradient descent chỉ có một đích đến duy nhất. Project này là lúc bạn kiểm chứng điều đó bằng số, không bằng niềm tin.
Đề bài: cho 4 điểm dữ liệu $x = [1, 2, 3, 4]$, $y = [3, 5, 7, 9]$. Đường thật là $y = 2x + 1$. Model khởi tạo từ $w = 0$, $b = 0$ và phải tự tìm ra $w \approx 2$, $b \approx 1$. Không dùng sklearn, không dùng autograd: bạn viết tay hàm loss, gradient và vòng lặp cập nhật. Mọi framework sau này chỉ là tự động hóa đúng vòng lặp bạn sắp viết.
Spec: một model, một loss, hai gradient
Ba công thức là toàn bộ project:
$$ \hat{y}i = w x_i + b, \qquad L = \frac{1}{n}\sum{i=1}^{n}(\hat{y}_i - y_i)^2 $$
$$ \frac{\partial L}{\partial w} = \frac{2}{n}\sum_{i=1}^{n}(\hat{y}i - y_i),x_i, \qquad \frac{\partial L}{\partial b} = \frac{2}{n}\sum{i=1}^{n}(\hat{y}_i - y_i) $$
Quy tắc cập nhật, chạy đồng thời cho cả hai tham số: $w \leftarrow w - \alpha \frac{\partial L}{\partial w}$ và $b \leftarrow b - \alpha \frac{\partial L}{\partial b}$.
Điểm cần nhớ: gradient theo $w$ có thêm $x_i$ vì $w$ được nhân với $x$ (chain rule), còn gradient theo $b$ thì không. Hệ số $2/n$ là hằng số chung của cả hai, và nó chính là chỗ dễ sai nhất khi viết tay.
Trong hồi quy tuyến tính với loss MSE, đạo hàm riêng theo w có thêm thừa số _____ so với đạo hàm theo b. Hệ số nhân chung của cả hai gradient là _____. Quy tắc cập nhật tham số là theta mới bằng theta cũ trừ _____. Nếu loss tăng dần qua các vòng lặp thì nguyên nhân đầu tiên cần kiểm tra là _____. Một vòng lặp được coi là hội tụ khi chuẩn của gradient gần _____ hoặc loss thay đổi dưới ngưỡng cho trước.
Bài tập 1. Với $w = 0$, $b = 0$, tính $\partial L/\partial w$ và $\partial L/\partial b$ bằng tay, rồi thực hiện một bước cập nhật với $\alpha = 0.05$. Loss trước và sau bước đó là bao nhiêu? (Đáp án ở mục gỡ rối bên dưới.)
Lộ trình 5 bước
- Dựng dữ liệu và hàm
predict(x, w, b). In ra dự đoán với w = b = 0 để thấy model đang sai bao xa. - Viết
loss(w, b)theo công thức MSE, rồi kiểm tra tay tại w = 0, b = 0 (kết quả phải là 41). - Viết
gradients(w, b)trả về cặp (gw, gb). Trước khi tin nó, kiểm tra bằng finite difference: (L(w + eps) - L(w - eps)) / (2 * eps) với eps = 1e-6. - Viết vòng lặp cập nhật, log loss, w, b ở 5 vòng đầu và mỗi 50 vòng sau đó.
- Chạy với alpha = 0.05, rồi thử alpha = 0.5 và alpha = 1.5 để thấy hội tụ, dao động và phân kỳ khác nhau thế nào.
Khung vòng lặp tối thiểu, chú ý dòng cập nhật đồng thời:
x, y = [1, 2, 3, 4], [3, 5, 7, 9]
w, b, alpha = 0.0, 0.0, 0.05
for step in range(1, 201):
r = [w * xi + b - yi for xi, yi in zip(x, y)]
loss = sum(ri ** 2 for ri in r) / len(x)
gw = 2 / len(x) * sum(ri * xi for ri, xi in zip(r, x))
gb = 2 / len(x) * sum(r)
w, b = w - alpha * gw, b - alpha * gb # cập nhật cùng lúc
if step <= 5 or step % 50 == 0:
print(step, round(loss, 4), round(w, 4), round(b, 4))
Bài tập 2. Nếu bạn lỡ viết loss là $L = \frac{1}{n}\sum r_i^2$ nhưng gradient lại là $\frac{1}{n}\sum r_i x_i$ (thiếu hệ số 2), bước kiểm tra finite difference sẽ báo gì? Vì sao?
Nghiệm thu: dấu hiệu bạn đã xong
| Tiêu chí | Ngưỡng chấp nhận |
|---|---|
| Loss tại điểm khởi tạo | đúng 41.0 khi $w = b = 0$ |
| Gradient check tại 3 điểm ngẫu nhiên | sai lệch tương đối < $10^{-6}$ |
| Log loss | giảm đơn điệu qua các vòng với $\alpha = 0.05$ |
| Tham số sau 200 vòng | $w$ trong $[1.95, 2.05]$, $b$ trong $[0.9, 1.1]$ |
| Thí nghiệm alpha | nêu được 3 chế độ: hội tụ, dao động, phân kỳ |
Điều kiện cuối cùng mới là phần "chứng minh": bạn phải chỉ ra được loss giảm qua từng vòng lặp bằng chính log của mình, ví dụ 41.0 → 1.129 → 0.043, chứ không chỉ nói "chắc là nó giảm".
Gỡ rối: đáp án bài tập và bẫy thường gặp
Đáp án bài tập 1. Residual đều âm: $r = [-3, -5, -7, -9]$. Vậy $\partial L/\partial w = \frac{2}{4}(-3 - 10 - 21 - 36) = -35$ và $\partial L/\partial b = \frac{2}{4}(-24) = -12$. Cập nhật: $w = 0 + 1.75 = 1.75$, $b = 0 + 0.6 = 0.6$. Loss từ 41 xuống còn khoảng 1.129. Chỉ một bước mà loss giảm gần 40 lần.
Đáp án bài tập 2. Gradient số tính đúng đạo hàm của loss bạn đã viết, tức là có hệ số $2/n$. Gradient giải tích thiếu 2 sẽ lệch đúng một thừa số 2 ở mọi điểm, nên check báo sai lệch tương đối khoảng 100%. Nếu bạn bỏ hệ số 2 ở cả hai chỗ thì model vẫn hội tụ, chỉ là learning rate hiệu dụng bị chia đôi.
Bốn bẫy hay gặp:
- Cập nhật tuần tự thay vì đồng thời. Tính $w$ mới rồi dùng $w$ mới để tính $b$ là trộn hai bộ tham số khác nhau. Dùng tuple assignment như đoạn code trên.
- Quên reset trạng thái khi đổi alpha. Khởi tạo lại $w = b = 0$ cho mỗi thí nghiệm, nếu không bạn đang so sánh các điểm xuất phát khác nhau.
- Chọn alpha theo cảm tính. Với dữ liệu nhỏ như trên, alpha = 1.5 làm loss nhảy vọt ngay vòng đầu. Hãy log loss ở vòng 1 trước khi chạy 200 vòng.
- Không scale feature khi làm bài mở rộng. Nếu $x$ có đơn vị hàng nghìn, gradient theo $w$ rất lớn và alpha phải nhỏ hơn nhiều.
Front: Với loss MSE, gradient theo b là gì? Back: (2/n) nhân tổng của (y_hat trừ y).
Front: Vì sao gradient theo w có thêm x_i? Back: Vì w nhân với x, chain rule kéo x xuống.
Front: Quy tắc cập nhật của gradient descent? Back: theta mới bằng theta cũ trừ alpha nhân gradient.
Front: Dấu của gradient cho biết điều gì? Back: Đó là hướng loss tăng nhanh nhất, nên ta đi ngược dấu.
Front: Gradient check bằng finite difference dùng để làm gì? Back: So gradient giải tích với xấp xỉ số để phát hiện lỗi công thức.
Front: Loss dao động rồi tăng dần, nguyên nhân thường gặp? Back: Learning rate quá lớn.
Front: Nghiệm tối ưu của bài toán x = [1,2,3,4], y = [3,5,7,9]? Back: w = 2, b = 1.
Front: Khởi tạo w = b = 0, alpha = 0.05, sau một bước w bằng bao nhiêu? Back: 1.75, vì gradient theo w là -35.
Front: Vì sao phải cập nhật w và b đồng thời? Back: Gradient phải tính trên cùng một bộ tham số, nếu không hướng đi bị sai.
Front: Loss MSE của hồi quy tuyến tính có phải hàm lồi không? Back: Có, nên chỉ có một cực tiểu toàn cục và không có saddle point đáng lo.
Front: Log loss sau mỗi vòng lặp giúp gì? Back: Chứng minh loss thực sự giảm và phát hiện phân kỳ ngay từ vòng đầu.
Front: Khi nào nên dừng vòng lặp? Back: Khi chuẩn gradient nhỏ hơn ngưỡng hoặc loss thay đổi dưới ngưỡng.
Chốt lại: model tự tìm ra đường thẳng
Bạn vừa dựng trọn một pipeline nhỏ: model tuyến tính, loss MSE, hai gradient viết tay, vòng lặp cập nhật đồng thời, và một bảng log đủ để chứng minh loss giảm từng vòng (41.0 xuống 1.129 rồi 0.043). Đây cũng là lúc bạn thấy rõ vì sao bài trước nhấn mạnh vào điểm dừng: hàm lồi chỉ có một đáy, nên mọi dao động bạn gặp đều đến từ learning rate chứ không phải từ địa hình loss.
Bài tiếp theo là checkpoint của module: các câu hỏi sẽ ghép phần tính tay, chẩn đoán learning rate và project này lại với nhau để kiểm tra bạn đã nắm chắc toàn bộ đường đi từ đạo hàm đến một model hội tụ.