Mô hình chuỗi và RNN với BPTT

Dữ liệu tuần tự, bốn kiểu one-to-many many-to-one many-to-many, cell nhớ hidden state và lan truyền ngược theo thời gian.
KhóThuật toán ~60 phút

Giới thiệu

Bài này học xử lý chuỗi có thứ tự và cell nhớ RNN. Dùng để dịch câu, chấm cảm xúc và gán nhãn từ.

Kiến thức cần nhớ

Bốn kiểu chuỗi

  • One-to-many: 1 ảnh sinh ra 1 câu mô tả.
  • Many-to-one: 1 câu cho ra 1 nhãn cảm xúc.
  • Many-to-many đồng bộ: gán nhãn từng từ một.
  • Many-to-many lệch: dịch máy, vào dài khác ra.
  • Ví dụ đời thường: như nghe cả câu mới hiểu ý.
KiểuInputOutput
One-to-many1 ảnh1 câu
Many-to-one1 câu1 nhãn
Đồng bộN từN nhãn
LệchN từM từ khác

Cell RNN

  • Định nghĩa: trộn đầu vào mới với trí nhớ cũ mỗi bước.
  • Trọng số dùng chung nên dài bao nhiêu cũng đủ.
  • Ví dụ đời thường: như ghi chú lề cập nhật từng trang.
  • Viết đè toàn bộ trí nhớ nên hay quên xa.
  • Dữ liệu xếp thành batch, bước thời gian, đặc trưng.

BPTT

  • Định nghĩa: lan truyền ngược mở ra theo thời gian.
  • Lỗi cuối chuỗi chảy ngược về từng bước trước.
  • Ví dụ đời thường: như truy lại băng ghi hình từng phút.
  • Chuỗi dài thì gradient teo hoặc nổ dần.
  • Cần cắt ngắn và kẹp gradient để chạy ổn.

Ví dụ

  • Input: "phim hay quá" -> Output: nhãn khen.
  • Giải thích: many-to-one đọc cả chuỗi rồi chốt 1 nhãn.
# Cell RNN cập nhật trí nhớ mỗi bước
h = tanh(x @ Wx + h_cu @ Wh + b)  # trộn mới và cũ
print(h)  # trí nhớ mới

💻 Bài tập

Ngôn ngữ: Python 3 với NumPy cho Bài 1-2, PyTorch cho Bài 3. Nộp vào day-100/.

Bài 1: RNN cell tự cài

class RNNCell:
    def __init__(self, input_size, hidden_size, seed=0): ...
    def forward(self, xs: np.ndarray, h0=None) -> tuple[np.ndarray, list]:
        """xs: (T, input_size). h_t = tanh(x_t Wx + h_{t-1} Wh + b). Trả (hs: (T, hidden), cache)."""
    def backward(self, dhs, cache) -> dict: ...   # BPTT, trả dWx, dWh, db
  1. Gradient check với sai phân trung tâm trên chuỗi T = 5.
  2. Xác nhận số tham số không đổi khi T từ 5 lên 100.
input_size=3, hidden=4 -> số tham số = 3*4 + 4*4 + 4 = 32, bất kể T

Bài 2: Gradient teo và nổ

  1. Chuỗi T = 50. Đặt loss chỉ ở bước cuối. In chuẩn ∥∂L/∂ht∥\lVert \partial L / \partial h_t \rVert cho từng t. Vẽ theo t (trục y log).
  2. Nhân Wh với 0.5 và với 2.0. Vẽ lại. Chỉ ra trường hợp teo và trường hợp nổ.
  3. Cài gradient clipping theo chuẩn: nếu ∥g∥>5\lVert g \rVert > 5 thì g←5g/∥g∥g \leftarrow 5 g / \lVert g \rVert.

Bài 3: Các kiểu bài toán chuỗi (nâng cao)

Dùng torch.nn.RNN:

  1. Many-to-one: đếm số chữ a trong chuỗi ngẫu nhiên dài 10-30 ký tự {a, b}. Hồi quy ra số lượng.
  2. Many-to-many đồng bộ: với chuỗi bit, xuất tại mỗi bước tổng các bit tới đó mod 2 (parity chạy).
  3. Chuẩn bị batch chuỗi khác độ dài: pad bằng 0 và dùng pack_padded_sequence. Kiểm tra kết quả không phụ thuộc phần pad.
  4. Trong README.md, viết mỗi kiểu (one-to-many, many-to-one, many-to-many đồng bộ, lệch) 1 ví dụ bài toán thật.

✅ Tiêu chí hoàn thành

  • Gradient check BPTT pass.
  • Có hình chuẩn gradient theo bước thời gian cho 3 mức Wh.
  • 2 bài many-to-one và many-to-many đạt accuracy trên 95%.
  • Kết quả không đổi khi thay độ dài pad.

❓ Câu hỏi ôn tập

  • Thứ tự từ vì sao quan trọng?
  • 4 kiểu chuỗi khác nhau sao?
  • Cell RNN nhớ bằng gì?
  • BPTT khác backprop thường ở đâu?

🌕 Bạn đã hoàn thành ngày 100. Làm hết bài tập phía trên rồi sang ngày tiếp theo.

Bớt paste mù, hiểu sâu từng dòng mình viết.

180 Days Challenge. 180 ngày cai nghiện vibe code.