Chuyển đến nội dung chính

Giải thích Mạng Nơ-ron Lan Truyền Thẳng: Hướng dẫn Hoàn Chỉnh

Mạng Nơ-ron Lan Truyền Thẳng (FFNN) là nền tảng của học sâu, được dùng trong nhận dạng ảnh, Transformers và hệ thống gợi ý. Hướng dẫn FFNN đầy đủ này giải thích kiến trúc, khác biệt với MLP, hàm kích hoạt, lan truyền ngược, ví dụ thực tế và triển khai bằng PyTorch.
· 11 phút đọc

Khám phá cùng AI

Khi xem xét Các thuật toán Machine Learning, có rất ít khái niệm nền tảng như Mạng Nơ-ron Lan Truyền Thẳng (FFNN). Nếu bạn từng xây dựng mạng nơ-ron đầu tiên của mình, rất có khả năng đó là mạng lan truyền thẳng. Chúng hiện diện gần như ở mọi nơi — từ bài toán phân loại đơn giản cho đến vận hành các tầng trong kiến trúc sâu. 

Trước hết, hãy xem FFNN nằm ở đâu trong bức tranh tổng thể:

Sơ đồ cho thấy Mạng Nơ-ron Lan Truyền Thẳng nằm dưới chiếc ô AI. Hình do Tác giả tạo

Trong hướng dẫn này, tôi sẽ giải thích FFNN thực sự là gì, cách nó phát triển và vì sao đến nay vẫn còn phù hợp, đồng thời khám phá các ví dụ trong thực tế.

Mạng Nơ-ron Lan Truyền Thẳng là gì?

Nói một cách trực quan, cách mô tả hay nhất cho kiến trúc mạng này là “Dữ liệu chỉ chảy theo chiều tiến, không có vòng lặp.”

Cốt lõi của FFNN là xử lý dữ liệu theo một chiều duy nhất, từ đầu vào đến đầu ra. Không có vòng quay lại, không đệ quy, không chu trình (ngoại trừ lan truyền ngược, chúng ta sẽ bàn ngay sau đây). 

Khi mới học về chủ đề này, hình ảnh giúp tôi dễ hiểu nhất là băng chuyền trong nhà máy. 

Tại sao? 

Vì mỗi bước trong quy trình (hay mỗi tầng trong mạng) thực hiện một thao tác đơn giản lên đầu vào trước khi chuyển tiếp sang bước kế tiếp.

Cách hoạt động như sau:

  1. Đầu vào đi vào tầng đầu tiên (tầng đầu vào).
  2. Chúng được biến đổi bởi trọng số và độ chệch rồi đi qua một hàm kích hoạt.
  3. Quy trình này tiếp tục qua một hoặc nhiều tầng ẩn.
  4. Cuối cùng, tầng đầu ra đưa ra dự đoán.

Trước khi cho bạn thấy kiến trúc mạng trông như thế nào, tôi muốn làm rõ một ngộ nhận phổ biến:

“Mạng Nơ-ron Lan Truyền Thẳng giống hệt MLP.”

Để hóa giải ngộ nhận này, ta cần điểm qua lịch sử sơ khai của Học Sâu. 

Lịch sử sơ khai của học sâu

Perceptron: Ta bắt đầu với Perceptron, được Frank Rosenblatt phát minh vào thập niên 1950. Đây là bộ phân loại nhị phân một tầng; dù không thể giải được mọi thứ (như bài toán XOR), nó đã đặt nền móng cho mạng nơ-ron.

Nói đơn giản, perceptron hoạt động như sau:

  1. Đầu vào: Mỗi đầu vào (như x_1, x_2, v.v.) có một trọng số đi kèm (w_1, w_2, v.v.).
  2. Tổng có trọng số: Các đầu vào được nhân với trọng số và cộng lại, cùng với một hằng số độ chệch: z = w1*x1 + w2*x2+ ... + b.
  3. Kích hoạt: Kết quả đi qua một hàm bậc thang (hàm kích hoạt). Nếu giá trị vượt ngưỡng, perceptron xuất ra 1; ngược lại là 0.

Hình minh họa hoạt động nội tại của một Perceptron đơn. Hình do Tác giả tạo.

Về bản chất, perceptron là bộ phân loại tuyến tính, nghĩa là nó chỉ có thể vẽ ranh giới quyết định dạng đường thẳng (hoặc siêu phẳng). Một mặt, Perceptron có ưu điểm như rất đơn giản, tinh gọn (lấy cảm hứng từ sinh học) và rẻ về tính toán. Mặt khác, nó không giải được các bài toán không thể phân tách tuyến tính, như XOR. 

Perceptron Nhiều Lớp (MLP): Vượt nhanh vài thập kỷ, vào thập niên 1980, các nhà nghiên cứu nhận ra rằng nếu xếp chồng nhiều perceptron và thêm các hàm kích hoạt phi tuyến, ta có thể giải quyết bài toán phức tạp hơn. Cấu trúc này được gọi là Perceptron Nhiều Lớp.

Cách thức hoạt động: 

  1. Tầng đầu vào: Nhận các đặc trưng thô từ dữ liệu.
  2. Các tầng ẩn: Một hoặc nhiều tầng perceptron thực hiện biến đổi. Mỗi nơ-ron thực hiện z = w*x + b rồi đưa qua hàm kích hoạt phi tuyến như sigmoid, tanh, v.v. 
  3. Tầng đầu ra: Tầng cuối tạo ra dự đoán cuối cùng (ví dụ: xác suất lớp, giá trị hồi quy).

Việc bổ sung các hàm kích hoạt phi tuyến là then chốt. Nếu không có chúng, việc xếp chồng các tầng chỉ quy về một phép biến đổi tuyến tính duy nhất. Với chúng, MLP có thể biểu diễn các hàm phi tuyến rất phức tạp.

Điều này dẫn đến một kết quả nổi tiếng trong lý thuyết mạng nơ-ron: Định lý Xấp xỉ Phổ quát. 

Ranh giới Tuyến tính vs Phi tuyến. Hình do Tác giả tạo.

Định lý này nói rằng một mạng nơ-ron chỉ cần một tầng ẩn — miễn là có hàm kích hoạt phi tuyến và đủ số nơ-ron — có thể xấp xỉ bất kỳ hàm liên tục nào trên một miền bị chặn. 

Kỷ nguyên Học Sâu: Bước sang thập niên 2010, chúng ta bước vào kỷ nguyên học sâu. Với GPU và dữ liệu lớn, FFNN phát triển thành các kiến trúc sâu và mạnh hơn, làm nền tảng cho CNN, RNN và Transformers — vốn là nơi chúng ta đang đứng hiện nay.

Quay lại ngộ nhận ban đầu, giờ ta biết rằng:

  • Mạng Nơ-ron Lan Truyền Thẳng (FFNN): Danh mục tổng quát của bất kỳ mạng nơ-ron nào có luồng dữ liệu một chiều (đầu vào → ẩn → đầu ra), không có vòng lặp.
  • Perceptron Nhiều Lớp (MLP): Một loại FFNN cụ thể có ít nhất một tầng ẩn gồm các perceptron (nơ-ron có trọng số, độ chệch và hàm kích hoạt).

Nói cách khác, mọi MLP đều là FFNN, nhưng không phải mọi FFNN đều là MLP. Đây là điểm rất quan trọng cần ghi nhớ. Một ngộ nhận khác thường gặp là về perceptron một tầng (tức chỉ từ đầu vào đến đầu ra).

Perceptron một tầng là một FFNN, nhưng không phải MLP! Chỉ khi thêm các tầng ẩn, nó mới trở thành MLP.

Sự phân biệt này quan trọng vì MLP có khả năng xấp xỉ hàm phổ quát (khi có đủ đơn vị ẩn và hàm kích hoạt phi tuyến), trong khi perceptron một tầng đơn giản bị hạn chế về khả năng biểu diễn.

Kiến trúc của Mạng Nơ-ron Lan Truyền Thẳng

Từ phần trước, ta đã học khá nhiều về FFNN, nhưng nói gọn, có thể xem chúng như một chồng các phép biến đổi đơn giản. Có nhiều thành phần hợp thành một FFNN, nên hãy tìm hiểu chi tiết hơn, đặc biệt là cấu trúc MLP. 

Trong MLP, có ba loại tầng: Đầu vào, Ẩn và Đầu ra, như ta đã nhắc đến trước đó. 

Kiến trúc Mạng Nơ-ron Lan Truyền Thẳng Kết nối đầy đủ (MLP). Hình do Tác giả tạo.

Hãy quan sát sơ đồ trên khi chúng ta đi sâu hơn vào các tầng này. 

Tầng đầu vào

Đây là điểm vào của mạng.  Mỗi nơ-ron ở đây đại diện cho một đặc trưng trong tập dữ liệu. Quan trọng là tầng đầu vào không tự thực hiện phép tính — nó chỉ chuyển các con số thô sang phía trước. Trong ví dụ của chúng ta, vì chỉ có hai nơ-ron ở Tầng Đầu Vào, điều đó có nghĩa là tập dữ liệu có hai đặc trưng (hoặc ta chỉ xét hai đặc trưng từ tập dữ liệu). 

Các tầng ẩn

Đây là nơi phép tính thực sự diễn ra. Chúng ta có hai tầng ẩn, mỗi tầng gồm bốn nơ-ron. Mỗi nơ-ron trong tầng ẩn thực hiện ba việc sau:

  1. Tổng có trọng số: Mỗi đầu vào được nhân với một trọng số rồi cộng lại. 
  2. Độ chệch (bias): Thêm một hằng số để tăng độ linh hoạt dịch chuyển hàm.
  3. Hàm kích hoạt: Áp dụng một hàm nén phi tuyến như ReLU, tanh hoặc sigmoid. Bước này cho phép mạng học được các mẫu phi tuyến phức tạp.

Tầng đầu ra

Tầng đầu ra tạo ra dự đoán cuối cùng, và thiết kế của nó phụ thuộc vào bài toán cần giải:

  • Hồi quy như dự đoán giá nhà. Khi đó, tầng đầu ra sẽ có một nơ-ron không dùng kích hoạt (tuyến tính). Vì sao tuyến tính? Vì ta không muốn nén giá trị — giá nhà có thể là bất kỳ số thực nào.
  • Phân loại nhị phân (quyết định có/không), như dự đoán email có phải spam hay không. Ở đây, tầng đầu ra là một nơ-ron với kích hoạt sigmoid. Vì sao sigmoid? Vì ta muốn mạng xuất ra giá trị trong khoảng 0 đến 1 (vì ta dự đoán xác suất). 
  • Phân loại đa lớp (từ 3 lớp trở lên) — như phân loại ảnh thành các loài động vật khác nhau. Tầng đầu ra sẽ có một nơ-ron cho mỗi lớp, với kích hoạt softmax. Vì sao softmax? Vì nó biến các điểm số thô thành xác suất có tổng bằng 1 (ví dụ: mèo 70%, chó 20%, ngựa 10%).

Tham khảo thêm, đây là sơ đồ thể hiện chín dạng hàm kích hoạt thường dùng trong FFNN và học sâu nói chung. 

Trực quan hóa các hàm kích hoạt phổ biến. Hình do Tác giả tạo.

Trước khi tiếp tục, cũng cần lưu ý rằng mỗi nơ-ron ở một tầng kết nối với mọi nơ-ron ở tầng kế tiếp (vì vậy mới gọi là kết nối đầy đủ). 

Quay lại ví dụ của chúng ta, ta có:

Params = (2⋅4+4)+(4⋅4+4)+(4⋅1+1)=12+20+5=37

Mỗi ngoặc cho thấy số tham số giữa hai tầng liên tiếp, trong đó số nơ-ron của tầng trước nhân với tầng hiện tại rồi cộng thêm số độ chệch (tức số nơ-ron của tầng hiện tại). Hãy thử tự tính với các ví dụ mạng nơ-ron khác để luyện tập!

Huấn luyện một Mạng Lan Truyền Thẳng

Trong Học Sâu, huấn luyện gồm hai bước: lan truyền tiến (forward pass/propagation) và lan truyền ngược (backpropagation). Nói đơn giản, Lan truyền tiến cho ta dự đoán, còn Lan truyền ngược là cách ta học từ sai sót. 

Lan truyền tiến 

Mọi thứ ta đã đề cập đến giờ thuộc về lan truyền tiến. Tóm lại, khi dữ liệu đi qua MLP, mỗi tầng thực hiện hai bước giống nhau, có thể viết bằng các phương trình sau:

Ở đây z là đầu ra sau khi nhân đầu ra của tầng trước với trọng số của tầng hiện tại và cộng độ chệch, còn gọi là Bước Tuyến tính. 

Tự nhiên, nếu tầng trước là tầng đầu vào, thì sẽ là x thay vì al-1. Bước tiếp theo là Bước Kích hoạt. Để chặt chẽ hơn về mặt toán, ta có thể viết Trọng số và Độ chệch như sau:

Lan truyền ngược

Khi đã có đầu ra, làm sao chúng ta cho mạng biết nó đúng hay sai? Hoặc tốt hơn, làm sao khiến mạng giỏi hơn ở tác vụ đã cho? Đây là lúc Lan truyền ngược xuất hiện. Có thể xem đây là hệ thống phản hồi của mạng, cho mô hình biết sai lệch bao nhiêu và cách tự điều chỉnh. Ta có thể chia nhỏ như sau:

  1. So sánh dự đoán: Xem mô hình dự đoán gì (ŷ) và đáp án đúng là gì (y).
  2. Tính lỗi: Dùng hàm mất mát để đo mức độ sai của dự đoán, như MSE.
  3. Lan truyền ngược (qua quy tắc dây chuyền): Tính gradient đối với tất cả độ chệch và trọng số. ∂L/∂w,∂L/∂b .
  4. Cập nhật theo Gradient Descent: Cập nhật các tham số tương ứng để giảm mất mát theo quy tắc dưới đây:

Ở đây, η là tốc độ học, một tham số có thể điều chỉnh để xác định mức thay đổi của tham số ở mỗi lần cập nhật. 

Trực quan hóa Gradient Descent - cho thấy hàm mất mát giảm sau mỗi epoch. Hình do Tác giả tạo.

Qua nhiều vòng lặp của quá trình này, mạng dần dần học và cải thiện hiệu suất tác vụ.

Để rõ ràng hơn, hãy cùng đi qua một ví dụ nhỏ. Giả sử ta có:

  • Đầu vào: x = 2
  • Đầu ra mục tiêu: y=4
  • Dự đoán: ŷ = 3

Giờ hãy đi qua các bước. 

  1. So sánh dự đoán: ŷ =3, y = 4
  2. Lỗi: Với ví dụ này, ta dùng MSE: L=(y−y^​)2=(4−3)2=1
  3. Lan truyền ngược: Mạng xác định mức đóng góp của từng trọng số và độ chệch gây ra lỗi bằng đạo hàm, rồi ta cập nhật từng tham số theo bước cập nhật gradient descent. 

Lập trình một Mạng Lan Truyền Thẳng trong PyTorch

Chúng ta đã điểm qua các yếu tố toán học cần thiết để xây dựng một FFNN (cụ thể là MLP). Để tiến xa hơn, ta sẽ lập trình điều này trong PyTorch. 

Perceptron nhiều lớp

# Imports we will be needing
import torch
import torch.nn as nn
import torch.optim as optim

X,y = dataset # Here will be our dataset 

# We have created a MLP here using nn.Sequential()
model = nn.Sequential(
    nn.Linear(2, 4),  # input layer → hidden layer (2 → 4)
    nn.ReLU(),        # relu activation function
    nn.Linear(4, 4), # hidden layer 1 → hidden layer 2 (4 → 4)
    nn.ReLU(), 
    nn.Linear(4, 1)   # hidden layer 2 → output (4 → 1)
)


criterion = nn.MSELoss()         # regression loss, i.e our loss function
optimizer = optim.SGD(model.parameters(), lr=0.1) # Optimizer using the Stochastic Gradient Descent

# Training Loop
EPOCHS = 200 # Number of epochs we will be training for
for epoch in range(EPOCHS):
    # Forward pass
    outputs = model(X)
    loss = criterion(outputs, y)

    # Backward pass
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

Đến đây, bạn có thể đối chiếu mã PyTorch với các bước toán học ta đã bàn. Tuy nhiên, bạn có thể thắc mắc về Epoch.

Một epoch là một lượt đưa toàn bộ tập dữ liệu huấn luyện qua mạng nơ-ron. Ví dụ, giả sử ta có 1.000 điểm dữ liệu huấn luyện và batch size = 100, thì sau khi mạng đã thấy cả 1.000 ảnh (tức 10 batch), đó là 1 epoch. Việc huấn luyện thường cần nhiều epoch để mô hình liên tục cải thiện trọng số.

Mạng nơ-ron tích chập

Tôi cũng muốn đề cập ngắn gọn đến các FFNN khác, một ví dụ rất nổi tiếng là Mạng Nơ-ron Tích Chập (CNN). 

Sơ đồ minh họa một Mạng Nơ-ron Tích Chập. Hình từ Mathworks - https://www.mathworks.com/discovery/convolutional-neural-network.html

Mặc dù CNN cũng có một MLP ở phần cuối, ở phần đầu nó chứa các tầng đặc biệt gọi là Tầng Tích chập và Tầng Gộp. Nói về Tầng Tích chập trước, chúng rất quan trọng vì chỉ nhìn vào các vùng cục bộ nhỏ của đầu vào tại một thời điểm bằng một bộ lọc (hay kernel).

Điều này rất hữu ích khi phân loại ảnh vì:

  • Các tầng dày đặc (dense) sẽ coi mỗi pixel như riêng lẻ, bỏ qua cấu trúc không gian.
  • Ngược lại, các tầng tích chập có thể phát hiện cạnh, kết cấu và hình dạng trong các miếng vá nhỏ — rồi kết hợp chúng thành mẫu phức tạp hơn khi đi sâu hơn.

Cùng với các tầng tích chập, CNN còn sử dụng tầng gộp (pooling).

Lưu ý rằng các tầng Gộp không học tham số, mà giảm mẫu bản đồ đặc trưng để làm chúng nhỏ hơn và dễ xử lý hơn.

  • Phổ biến nhất là Max Pooling, lấy giá trị lớn nhất từ mỗi vùng nhỏ (ví dụ: cửa sổ 2×2).
  • Pooling giúp mạng hiệu quả hơn và còn tạo tính bất biến theo tịnh tiến (mạng quan tâm nhiều hơn đến việc một đặc trưng có tồn tại hay không, chứ không phải chính xác nó ở đâu).

Ta có thể lập trình một CNN bằng PyTorch như sau:

class SimpleCNN(nn.Module): # Define our model as a class
    def __init__(self):
        super().__init__()
        self.conv = nn.Conv2d(1, 8, 3)     # 1→8 channels, 3x3 kernel
        self.pool = nn.MaxPool2d(2, 2)
        self.fc   = nn.Linear(8*13*13, 10) # flatten → 10 classes

    def forward(self, x): # Forward propagation function 
        x = self.pool(torch.relu(self.conv(x)))
        x = x.view(x.size(0), -1)          # flatten
        return self.fc(x)

Trong đoạn mã trên, chúng ta tạo một CNN rất đơn giản, gồm một tầng tích chập, một tầng gộp và một tầng tuyến tính. 

Các ví dụ khác về mạng lan truyền thẳng

Chúng ta đã đề cập hai ví dụ FFNN rất nổi tiếng và quan trọng, nhưng còn nhiều ví dụ khác mang tính cách mạng trong các lĩnh vực riêng, như:

  1. Transformers: mỗi khối chứa phần MLP/FFN (sau self-attention, “tầng feed-forward” mở rộng + thu hẹp kích thước).
  2. Vision Transformers (ViT): áp dụng các khối transformer (bên trong có FFNN) lên các miếng vá ảnh.
  3. Autoencoder (loại cơ bản): bộ mã hóa + giải mã đều xây dựng từ FFNN.
  4. Hệ thống gợi ý (dựa trên MLP): ví dụ mô hình Wide & Deep cho xếp hạng và dự đoán.

Kiến trúc Transformer. Hình từ Bài báo gốc - Attention is all you need.

Lời kết

Hy vọng bạn đã nhận ra tầm quan trọng của FFNN trong lĩnh vực AI. Không có chúng, bức tranh học sâu hiện đại đã không tồn tại.

Để tiếp tục, tôi rất khuyến nghị thành thạo lan truyền ngược và tìm hiểu sâu hơn về các hàm kích hoạt. Vì đây là nền tảng của Học Sâu, tôi cũng khuyên bạn học Deep Learning với PyTorch.

Câu hỏi thường gặp về Mạng Nơ-ron Lan Truyền Thẳng

FFNN và MLP có giống nhau không?

Không, đây là một ngộ nhận khá lớn! FFNN chỉ có nghĩa là dữ liệu chảy theo chiều tiến. MLP là một dạng FFNN có ít nhất một tầng ẩn.

Vì sao chúng ta dùng các hàm kích hoạt?

Chúng bổ sung tính phi tuyến. Nếu không có chúng, nhiều tầng sẽ hành xử như một tầng tuyến tính lớn và mạng không thể học các mẫu phức tạp.

FFNN được dùng ở đâu trong đời thực?

Ở khắp nơi, như hệ thống gợi ý, bộ phân loại ảnh (CNN), Transformers và autoencoder đều dựa vào chúng.

Làm sao tôi lập trình một FFNN trong PyTorch?

Ta có thể xếp chồng các tầng nn.Linear, thêm các kích hoạt như nn.ReLU, chọn một hàm mất mát và một bộ tối ưu rồi huấn luyện bằng các lượt lan truyền tiến + ngược.

Lan truyền ngược là gì?

Tóm gọn trong một câu, đó là cách mạng học — so sánh dự đoán với mục tiêu, đo lường lỗi và cập nhật trọng số bằng gradient descent.

Vaibhav Mehra

Tác giả

Vaibhav Mehra

Chủ đề

Liên quan