Recurrent Neural Network (RNN)
Mạng neural hồi quy (RNN) đọc từng bước trong một chuỗi và duy trì trạng thái ẩn qua các bước. Bài viết đề cập đến cơ chế hồi quy, huấn luyện, biến thể và mã nguồn.
Mạng nơ-ron hồi quy (RNN) là một mạng nơ-ron xử lý tuần tự từng phần tử, đồng thời truyền trạng thái ẩn từ bước này sang bước kế tiếp; do đó, đầu ra ở mỗi bước có thể phụ thuộc vào mọi dữ liệu đã đọc trước đó. Cùng một bộ trọng số được áp dụng ở mọi bước, cho phép một mạng xử lý chuỗi có độ dài bất kỳ, từ một câu đến hàng giờ dữ liệu cảm biến. RNN là kiến trúc chủ đạo cho xử lý ngôn ngữ tự nhiên (NLP), nhận dạng tiếng nói và phân tích chuỗi thời gian cho đến khi transformer thay thế chúng trong hầu hết tác vụ ngôn ngữ vào cuối thập niên 2010. Các biến thể có cổng vẫn phổ biến trong xử lý streaming và model chạy trên thiết bị; cơ chế hồi quy cũng trở lại trong model không gian trạng thái (SSMs) như Mamba.
RNN hoạt động như thế nào#
RNN đơn giản, còn gọi là mạng Elman theo bài báo năm 1990 của Jeffrey Elman, cập nhật trạng thái ẩn theo công thức hₜ = tanh(Wxₜ + Uhₜ₋₁ + b) và có thể xuất đầu ra yₜ = Vhₜ + c tại mỗi bước. Trạng thái ẩn là vector có kích thước cố định, tóm tắt chuỗi đã đọc đến thời điểm hiện tại; tanh giữ các giá trị trong khoảng −1 đến 1 khi trạng thái được đưa trở lại làm đầu vào. Khi vẽ một bản sao mạng cho mỗi bước, vòng lặp được trải thành một mạng truyền thẳng sâu, trong đó các lớp dùng chung trọng số:
Đoạn code bên dưới chạy nn.RNN của PyTorch trên một chuỗi và lặp lại cùng phép hồi quy bằng vòng lặp thông thường:
import torch
from torch import nn
torch.manual_seed(0)
rnn = nn.RNN(input_size=3, hidden_size=4, batch_first=True)
x = torch.randn(1, 6, 3) # one sequence: 6 time steps, 3 features each
# PyTorch runs the whole sequence; output holds the hidden state after every step
output, h_n = rnn(x)
# The same recurrence by hand, reusing one set of weights at every step
h = torch.zeros(1, 4)
for t in range(x.shape[1]):
h = torch.tanh(x[:, t] @ rnn.weight_ih_l0.T + rnn.bias_ih_l0 + h @ rnn.weight_hh_l0.T + rnn.bias_hh_l0)
print(f"Output shape: {tuple(output.shape)}, final state shape: {tuple(h_n.shape)}")
print(f"Hand-written loop matches nn.RNN: {torch.allclose(h, h_n[0], atol=1e-6)}")Đoạn code in ra Output shape: (1, 6, 4), final state shape: (1, 1, 4) và Hand-written loop matches nn.RNN: True. Đầu ra chứa một trạng thái ẩn 4 chiều cho mỗi bước thời gian; vòng lặp tái tạo trạng thái cuối cùng chỉ với một ma trận trọng số cho đầu vào và một ma trận cho trạng thái trước đó.
Các tác vụ chuỗi#
Cùng một phép hồi quy phù hợp với các tác vụ có độ dài đầu vào và đầu ra khác nhau:
- Nhiều đầu vào thành một đầu ra: Đọc toàn bộ chuỗi rồi phân loại dựa trên trạng thái cuối cùng, như trong phân tích cảm xúc hoặc gán nhãn một cửa sổ dữ liệu cảm biến.
- Nhiều đầu vào thành nhiều đầu ra: Xuất đầu ra ở mọi bước, chẳng hạn gán nhãn từng từ trong câu hoặc từng khung hình âm thanh.
- Chuỗi thành chuỗi: RNN encoder đọc đầu vào, còn RNN decoder tạo đầu ra có độ dài khác; đây là thiết kế của các hệ thống dịch máy thần kinh đời đầu và những model chuỗi-sang-chuỗi khác.
- Một đầu vào thành nhiều đầu ra: Tạo chuỗi từ một đầu vào duy nhất, chẳng hạn tạo chú thích từ vector đặc trưng của ảnh trong các model tạo chú thích ảnh đời đầu.
RNN hai chiều bổ sung một RNN thứ hai đọc chuỗi theo chiều ngược lại rồi kết hợp hai trạng thái tại mỗi bước, nhờ đó mọi đầu ra đều tiếp nhận ngữ cảnh quá khứ lẫn tương lai. RNN xếp chồng đưa các trạng thái ẩn của lớp này vào lớp kế tiếp làm chuỗi đầu vào.
Huấn luyện bằng backpropagation through time#
RNN được huấn luyện bằng backpropagation through time (BPTT): mạng được trải theo chuỗi, loss được tính tổng qua các bước và backpropagation chạy qua đồ thị đã trải. Gradient truyền đến bước t từ bước T đi qua T − t bản sao của lớp hồi quy và được nhân với U cùng đạo hàm của tanh ở mỗi lần. Khi các hệ số này phần lớn nhỏ hơn 1, gradient suy giảm theo cấp số nhân—đây là vấn đề vanishing gradient mà Yoshua Bengio, Patrice Simard và Paolo Frasconi phân tích năm 1994. Khi các hệ số lớn hơn 1, gradient tăng theo cấp số nhân, tạo thành vấn đề exploding gradient. Đoạn code bên dưới đo mức độ ảnh hưởng của từng đầu vào trong chuỗi 50 bước đến trạng thái ẩn cuối cùng:
import torch
from torch import nn
torch.manual_seed(0)
rnn = nn.RNN(input_size=8, hidden_size=32, batch_first=True)
x = torch.randn(1, 50, 8, requires_grad=True) # one 50-step sequence
# Backpropagate from the final hidden state to the input at every step
output, h_n = rnn(x)
h_n.sum().backward()
grad_norms = x.grad[0].norm(dim=1)
for distance in [0, 10, 20, 30, 40]:
print(f"Input {distance:>2} steps before the end: gradient {grad_norms[-1 - distance]:.1e}")Đoạn mã in gradient của 1.6e+00, 3.4e-03, 6.2e-06, 1.2e-08 và 1.1e-11 tại các đầu vào cách thời điểm kết thúc lần lượt 0, 10, 20, 30 và 40 bước. Cứ mỗi mười bước, gradient giảm khoảng ba bậc độ lớn, vì vậy quá trình huấn luyện hầu như không thể điều chỉnh trọng số để sử dụng đầu vào cách đó vài chục bước. Gradient clipping, được Razvan Pascanu và các cộng sự phân tích cho RNN vào năm 2013, giới hạn gradient bùng nổ; còn BPTT cắt cụt giới hạn lan truyền ngược trong một cửa sổ cố định để khống chế bộ nhớ. Gradient biến mất đòi hỏi thay đổi kiến trúc; đó chính là điều các cổng của LSTM và GRU mang lại.
RNN và các kiến trúc liên quan#
- LSTM và GRU: RNN có cổng, với cập nhật trạng thái dạng cộng, cho phép thông tin và gradient truyền qua nhiều bước. Trên thực tế, “RNN” thường dùng để chỉ các kiến trúc này cũng như RNN đơn giản.
- Transformer: Trực tiếp tập trung vào mọi vị trí trước đó thay vì nén lịch sử vào một trạng thái, đồng thời huấn luyện tất cả vị trí song song. Chi phí attention tăng theo độ dài chuỗi, còn RNN sử dụng cùng lượng tính toán và bộ nhớ cho mỗi bước mới.
- Mạng nơ-ron tích chập (CNN): Kết hợp các vị trí lân cận bằng bộ lọc có kích thước cố định, trên không gian của ảnh hoặc trên thời gian bằng phép tích chập 1D; trường tiếp nhận được xác định bởi độ sâu của mạng.
- Mô hình không gian trạng thái: Các phép truy hồi tuyến tính như Mamba được huấn luyện song song bằng phép quét và chạy từng bước như RNN khi suy luận. Mạng nơ-ron lỏng là RNN thời gian liên tục, trong đó neuron tuân theo các phương trình vi phân.
Ứng dụng#
- Dự đoán từ trên bàn phím: Model dự đoán từ tiếp theo của Gboard là LSTM có cổng đầu vào và quên ghép nối, một biến thể LSTM gọn nhẹ hơn, được huấn luyện bằng học liên kết trên điện thoại của người dùng, như các nhà nghiên cứu Google mô tả năm 2018.
- Dự báo nhu cầu: DeepAR của Amazon huấn luyện một RNN tự hồi quy trên nhiều chuỗi thời gian có liên quan và đưa ra phân phối xác suất cho từng giá trị tương lai.
- Âm thanh phát trực tuyến: Bộ phát hiện từ đánh thức và bộ khử nhiễu xử lý âm thanh từng khung bằng các lớp hồi quy nhỏ, giúp bộ nhớ và độ trễ luôn ổn định trên điện thoại và tai nghe.
- Theo dõi đối tượng: Bộ theo dõi duy trì trạng thái cho từng đối tượng qua các khung hình, tương tự vai trò của trạng thái ẩn trong RNN. Mọi bộ theo dõi tích hợp trong YOLO26 chế độ track, từ ByteTrack và BoT-SORT đến TrackTrack mặc định, đều cập nhật trạng thái đó bằng bộ lọc Kalman, một phép truy hồi tuyến tính dùng các phương trình vận tốc không đổi được thiết lập thủ công thay cho trọng số học được.










