# 🎯 Cross-entropy và đạo hàm của loss theo từng tham số

By Better Wise

## Nối từ log-sum-exp sang loss: bài này đứng ở đâu

Bài trước đã cho ta một softmax tính được mà không tràn số: trừ đi $\max_c z_c$ trước khi lấy exp, rồi dùng log-sum-exp để tính $\log\sum_c \exp(z_c)$. Giờ ta gắn loss lên trên softmax đó và đi ngược một bước: **cross-entropy đạo hàm theo logits bằng đúng $p - y$**, rồi từ đó lan tiếp về weight của lớp cuối. Đây là mắt xích mà đồ án mạng 2 lớp sẽ dựa vào để viết `backward()`.

Sau bài này bạn có thể:

- Viết cross-entropy cho nhãn one-hot dưới dạng ổn định số học.
- Suy ra $\partial L/\partial z = p - y$ từng bước, không cần nhớ công thức.
- Lan truyền gradient đó về $W$, $b$ và cả $h$ của lớp ẩn.
- Kiểm tra shape của cả bốn đại lượng trên bằng một phép nhân ma trận duy nhất.

## Cross-entropy nhìn từ xác suất lớp đúng

Với nhãn one-hot $y$ và $p = \mathrm{softmax}(z)$:

$$
L = -\sum_{c} y_c \log p_c = -\log p_t
$$

trong đó $t$ là lớp đúng. Điểm cần khắc: **cross-entropy chỉ nhìn vào một con số**, xác suất mà model gán cho lớp đúng. Nếu $p_t = 0.9$ thì $L \approx 0.105$; nếu $p_t = 0.01$ thì $L \approx 4.6$. Các lớp sai chỉ ảnh hưởng gián tiếp, thông qua việc chúng chiếm bớt phần xác suất trong phép chuẩn hóa.

Vì $p_t$ có thể underflow về 0, ta không bao giờ tính `-log(p[t])` trực tiếp. Thay $p_t = \exp(z_t)/\sum_c \exp(z_c)$ vào và lấy log:

$$
L = \log\sum_{c} \exp(z_c) - z_t
$$

Đây chính là chỗ log-sum-exp của bài trước quay lại làm việc: một hàm `logsumexp` ổn định là đủ để có cross-entropy ổn định.

**Xem đáp án bài tập 1**

Cho $z = [2.0,\ 1.0,\ -1.0]$, $t = 0$. Tính $p$, $L$ bằng cả hai công thức.

$\sum \exp(z) = 7.389 + 2.718 + 0.368 = 10.475$, nên $p = [0.7055,\ 0.2595,\ 0.0351]$ và $L = -\log 0.7055 = 0.3488$. Công thức log-sum-exp cho $\log 10.475 - 2.0 = 2.3488 - 2.0 = 0.3488$. Khớp. Lưu ý $p$ cộng lại bằng 1, đó là ràng buộc bạn sẽ dùng ngay dưới đây.

## Đạo hàm theo logits: vì sao chỉ là $p$ trừ $y$

Lấy $L = \log\sum_c \exp(z_c) - z_t$ đạo hàm theo một logit $z_k$ bất kỳ:

- Đạo hàm của $-\log p_t$ phần $z_t$: $-1$ nếu $k = t$, ngược lại $0$. Viết gọn là $-y_k$.
- Đạo hàm của $\log\sum_c \exp(z_c)$ theo $z_k$: $\dfrac{\exp(z_k)}{\sum_c \exp(z_c)} = p_k$.

Cộng lại:

$$
\frac{\partial L}{\partial z_k} = p_k - y_k
$$

Toàn bộ gradient của loss theo vector logits là $g = p - y$. Không có ma trận Jacobian $C \times C$ nào cần dựng, vì ta chỉ cần gradient của một loss vô hướng. Đây là lý do trong thực tế người ta gộp softmax và cross-entropy thành một khối `softmax_cross_entropy` trả về cả loss lẫn $g$.

Vài tính chất đáng kiểm tra bằng mắt:

| Thành phần | Giá trị | Ý nghĩa |
| --- | --- | --- |
| $g_t = p_t - 1$ | luôn âm | đẩy logit lớp đúng lên |
| $g_k = p_k$ với $k \neq t$ | luôn dương | đẩy logit lớp sai xuống |
| $\sum_k g_k$ | $= 0$ | gradient chỉ tái phân bố, không đổi tổng |

Với ví dụ trên: $g = [0.7055-1,\ 0.2595,\ 0.0351] = [-0.2945,\ 0.2595,\ 0.0351]$, tổng xấp xỉ 0. Gradient bị chặn trong $[-1, 1]$, nên bản thân cross-entropy không gây exploding gradient; nếu sau này bạn thấy gradient nổ, thủ phạm nằm ở chỗ khác.

Một hệ quả thực dụng: nếu model rất tự tin và đúng ($p_t \to 1$) thì $g \to 0$, học gần như dừng. Nếu model rất tự tin và sai ($p_t \to 0$ với $t$ đúng) thì $g_t \to -1$, một cú đẩy mạnh nhưng vẫn hữu hạn. Đó là hành vi ta muốn.

## Lan truyền về weight lớp cuối

Giờ đặt lớp cuối là affine: $z = hW^\top + b$ theo góc nhìn từng mẫu, hay gọn hơn $z_i = W h_i + b$ với $W \in \mathbb{R}^{C \times D}$, $h_i \in \mathbb{R}^{D}$, $b \in \mathbb{R}^{C}$.

Theo quy tắc chuỗi, một gradient $g$ ở logits sẽ cho:

$$
\frac{\partial L}{\partial W} = g\,h^\top, \qquad \frac{\partial L}{\partial b} = g, \qquad \frac{\partial L}{\partial h} = W^\top g
$$

với từng mẫu. Với mini-batch $N$ mẫu và loss là trung bình, gom $G \in \mathbb{R}^{N \times C}$ (mỗi hàng là $p_i - y_i$) và $H \in \mathbb{R}^{N \times D}$:

$$
\frac{\partial L}{\partial W} = \frac{1}{N} G^\top H, \qquad \frac{\partial L}{\partial b} = \frac{1}{N}\sum_{i=1}^{N} G_i
$$

```mermaid
flowchart TD
  H["h (N, D)"] --> Z["z = W h + b (N, C)"]
  W["W (C, D)"] --> Z
  Z --> P["p = softmax(z)"]
  P --> L["L = -log p_t"]
  L --> G["G = p - y (N, C)"]
  G --> DW["dL/dW = Gᵀ H / N (C, D)"]
  G --> DB["dL/db = mean(G) (C,)"]
  G --> DH["dL/dh = G W / N (N, D)"]
```

Bảng shape để dán vào notebook đồ án:

| Đại lượng | Shape | Ghi chú |
| --- | --- | --- |
| $z$ | $(N, C)$ | logits thô |
| $p$ | $(N, C)$ | mỗi hàng tổng bằng 1 |
| $G = \partial L/\partial z$ | $(N, C)$ | $p - y$ |
| $H$ | $(N, D)$ | activation lớp ẩn |
| $\partial L/\partial W$ | $(C, D)$ | khớp shape của $W$ |
| $\partial L/\partial b$ | $(C,)$ | khớp shape của $b$ |
| $\partial L/\partial H$ | $(N, D)$ | đầu vào cho `backward()` của lớp ẩn |

Quy tắc nhẩm: **gradient của một tham số luôn có cùng shape với tham số đó**. Nếu lệch, gần như chắc chắn bạn quên transpose hoặc quên chia $N$.

**Xem đáp án bài tập 2**

Với $g = [-0.2945,\ 0.2595,\ 0.0351]$, $h = [1.0,\ 0.5]$ (một mẫu, $N = 1$):

$\partial L/\partial W = g h^\top = \begin{bmatrix} -0.2945 & -0.1473 \\ 0.2595 & 0.1298 \\ 0.0351 & 0.0176 \end{bmatrix}$, shape $(3, 2)$.

$\partial L/\partial b = g$. Với $W = \begin{bmatrix} 0.1 & 0.2 \\ 0.3 & -0.1 \\ -0.2 & 0.4 \end{bmatrix}$ thì $\partial L/\partial h = W^\top g = [0.0414,\ -0.0708]$. Kiểm tra: cộng các hàng của $\partial L/\partial W$ theo cách phù hợp phải tái tạo lại được hai số này, vì $g h^\top$ và $W^\top g$ chia sẻ cùng $g$.

## Bốn lỗi thường gặp khi cài cross-entropy

1. **Tính `-log(p[t])` trực tiếp.** Underflow, rồi `log(0)` cho `-inf` hoặc NaN. Luôn dùng `logsumexp(z) - z[t]`.
2. **Cộng dồn loss mà không chia $N$**, rồi chia gradient cho $N$. Loss và gradient phải cùng một quy ước chuẩn hóa, nếu không learning rate của bạn vô nghĩa.
3. **Trung bình theo batch nhưng lấy tổng theo lớp.** Với $C$ lớp, chia nhầm cho $C$ làm gradient nhỏ đi $C$ lần. Một mẹo: sau khi viết `backward()`, in `grad_W.shape == W.shape` và so sánh độ lớn gradient với một ước lượng thủ công trên 2 mẫu.
4. **Quên rằng $g$ đã bao gồm softmax.** Nếu bạn vẫn còn một lớp softmax riêng phía sau và lan tiếp $g$ qua nó, gradient bị nhân thêm một lần nữa. Hãy chọn một trong hai: gộp `softmax + cross_entropy`, hoặc tách rời và để autograd lo phần Jacobian.

Một thói quen tốt cho đồ án: viết một hàm `check_gradient(f, x, eps=1e-5)` so sánh gradient giải tích với $(f(x+\epsilon) - f(x-\epsilon))/2\epsilon$ trên vài phần tử ngẫu nhiên của $W$. Bài sau sẽ biến thói quen này thành quy trình chuẩn, kèm chẩn đoán vanishing/exploding gradient.

## Mang gì sang bài gradient checking

Tóm lại: cross-entropy của one-hot label chỉ là $-\log p_t$, viết ổn định thành $\mathrm{logsumexp}(z) - z_t$. Đạo hàm theo logits là $p - y$, một vector có tổng bằng 0, bị chặn trong $[-1, 1]$, và với mini-batch thì $\partial L/\partial W = G^\top H / N$. Ba dòng code đó là toàn bộ phần loss và lớp cuối của mạng 2 lớp. Bài tiếp theo sẽ lấy chính $G$ này làm điểm khởi đầu để kiểm tra gradient bằng sai phân hữu hạn và giải thích vì sao gradient có thể biến mất hoặc nổ khi lan qua nhiều lớp.

Front: Cross-entropy với nhãn one-hot y và softmax p bằng gì?
Back: L = -log p_t, chỉ phụ thuộc xác suất model gán cho lớp đúng t.

Front: Công thức cross-entropy ổn định số học tính từ logits?
Back: L = logsumexp(z) - z_t.

Front: Đạo hàm của cross-entropy theo một logit z_k là gì?
Back: p_k - y_k.

Front: Vì sao gradient theo logits lại đơn giản là p - y?
Back: Vì đạo hàm của -z_t là -y_k và đạo hàm của logsumexp(z) theo z_k là p_k.

Front: Tổng gradient theo logits của một mẫu bằng bao nhiêu?
Back: Bằng 0, vì tổng p bằng 1 và tổng y bằng 1.

Front: Gradient tại lớp đúng có dấu gì?
Back: Âm (p_t - 1), nên nó đẩy logit của lớp đúng lên.

Front: Gradient theo bias của lớp tuyến tính cuối?
Back: dL/db = trung bình của (p - y) trên batch, shape (C,).

Front: Gradient theo weight của lớp tuyến tính cuối?
Back: dL/dW = G^T H / N, với G = p - y và H là activation đầu vào.

Front: Gradient theo activation đầu vào của lớp cuối?
Back: dL/dh = W^T g cho từng mẫu, dạng batch là G W / N.

Front: Vì sao không được viết -log(p[t]) trực tiếp?
Back: p_t có thể underflow về 0 và log(0) cho -inf hoặc NaN.

Front: Cross-entropy đạt giá trị nhỏ nhất khi nào?
Back: Khi p_t = 1, lúc đó L = 0.

Front: Cross-entropy có thể gây exploding gradient không?
Back: Không, gradient theo logits bị chặn trong [-1, 1].

Front: Quy tắc nhẩm để kiểm tra gradient của một tham số?
Back: Gradient phải có cùng shape với tham số đó.

Đạo hàm của cross-entropy theo logits là _____, với p là softmax của logits và y là one-hot.
Cross-entropy ổn định được tính bằng _____.
Với z = W h + b, gradient theo weight của lớp cuối là _____ cho từng mẫu.
Trên mini-batch N mẫu, gradient theo weight là _____, và ta phải _____ ở cả loss lẫn gradient.
Gradient theo logits có tổng bằng _____ nên nó chỉ tái phân bố chứ không đổi tổng.

---

## Contents

Part of [🧠 Khóa 5: Toán cho Machine Learning — tích chập, softmax và lan truyền ngược cho deep learning](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho.md)

- **🖼️ Tích chập, shape và lan truyền ngược**
  - [🔲 Tích chập 1D và 2D: kernel, stride, padding](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho/tich-chap-1d-2d-kernel-stride-padding.md)
  - [📐 Kiểm tra shape và vector hóa tích chập bằng im2col](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho/kiem-tra-shape-va-vector-hoa-tich-chap-im2col.md) (sign-in required)
  - [🔁 Lan truyền ngược qua lớp tuyến tính và lớp tích chập](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho/lan-truyen-nguoc-qua-lop-tuyen-tinh-va-lop-tich-chap.md)
  - [✅ Checkpoint: tích chập và backprop](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho/checkpoint-tich-chap-va-backprop.md)
- **📉 Softmax, cross-entropy và numerical stability**
  - [📊 Softmax và log-sum-exp: ổn định số học](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho/softmax-va-log-sum-exp-on-dinh-so-hoc.md)
  - [🎯 Cross-entropy và đạo hàm của loss theo từng tham số](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho/cross-entropy-va-dao-ham-loss-theo-tham-so.md) — this lesson
  - [🧪 Vanishing/exploding gradient, numerical stability và gradient checking](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho/vanishing-exploding-gradient-numerical-stability-gradient-checking.md)
  - [✅ Checkpoint: loss, gradient và numerical stability](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho/checkpoint-loss-gradient-va-numerical-stability.md)
- **🚀 Capstone: forward/backward cho mạng 2 lớp**
  - [🏗️ Project: forward pass và kiểm tra shape cho mạng 2 lớp](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho/project-forward-pass-va-kiem-tra-shape-mang-2-lop.md)
  - [⚙️ Project: backward pass, gradient checking và training loop](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho/project-backward-pass-gradient-checking-va-training-loop.md) (premium content)
  - [✅ Checkpoint: capstone forward/backward](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho/checkpoint-capstone-forward-backward.md) (premium content)
- [Course cheatsheet](https://everwise.study/courses/khoa-5-toan-cho-machine-learning-tich-chap-softmax-va-lan-truyen-nguoc-cho/cheatsheet.md) (premium content)
