Học AI & Lập trình

Từ Linear Classifier đến Neural Network

Từ hàm điểm f(x) = Wx + b: trọng số “nhìn” thấy gì, vì sao bắt buộc cần hàm kích hoạt và cách nhiều neuron ghép thành mạng nơ-ron sâu.

Từ Linear Classifier đến Neural Network
Nội dung bài viết
  1. Bài toán: từ pixel đến điểm số cho từng lớp
  2. Linear classifier: hàm điểm f(x) = Wx + b
  3. Linear classifier "nhìn" thấy gì?
  4. Từ linear classifier đến neuron
  5. Vì sao bắt buộc phải có hàm kích hoạt?
  6. Kiến trúc Neural Network
  7. Forward pass: lan truyền xuôi
  8. Ví dụ hoàn chỉnh: phân loại chữ số MNIST
  9. Deep Neural Network và định lý xấp xỉ vạn năng
  10. Tóm tắt
  11. Tài liệu tham khảo

Mọi mạng nơ-ron khổng lồ hiện nay, từ ResNet đến YOLO, đều được xây từ một phép toán rất khiêm tốn: nhân ma trận rồi cộng. Bài này đi từ bộ phân loại tuyến tính (linear classifier) đơn giản nhất, hiểu nó "nhìn" ảnh ra sao, vì sao nó chưa đủ, và làm thế nào ghép nhiều neuron thành một neural network thực thụ.

Số trang (ví dụ "trang 81") trong bài chỉ tới slide của bài giảng Deep Learning – Computer Vision – NLP (Thang Nguyen, Viet Nguyen); bài này giải thích chi tiết, kiểm chứng và đính chính các slide đó.

Bài toán: từ pixel đến điểm số cho từng lớp

Phân loại ảnh nghĩa là: cho một ảnh \(x\), trả về điểm số (score) cho từng lớp trong \(K\) lớp, lớp có điểm cao nhất là dự đoán. Sau khi chuẩn hoá thành xác suất, ta có kết quả kiểu "82% cat, 15% dog, 2% hat, 1% mug".

Trước hết, "duỗi" ảnh thành một vector cột: ảnh MNIST 28×28 thành vector \(D = 784\) phần tử; ảnh CIFAR-10 32×32×3 thành \(D = 3072\) phần tử.

Linear classifier: hàm điểm f(x) = Wx + b

\[ f(x_i; W, b) = W x_i + b, \qquad f: \mathbb{R}^D \rightarrow \mathbb{R}^K \]
  • \(x_i\): ảnh thứ \(i\), vector \(D\times1\).
  • \(W\): ma trận trọng số (weights) kích thước \(K\times D\).
  • \(b\): vector độ lệch (bias) \(K\times1\).
  • Kết quả: vector \(K\) điểm số, mỗi lớp một điểm.

Ví dụ tính tay (trang 11 của tài liệu)

Ảnh "đồ chơi" chỉ có 4 pixel \(x = [56, 231, 24, 2]^T\), 3 lớp cat/dog/ship:

W (3×4)
0.2-0.50.12.0
1.51.32.10.0
00.250.2-0.3
·
x
56
231
24
2
+
b
1.1
3.2
-1.2
=
scores
-96.8
437.9
60.75

Điểm cat: \(0.2\cdot56 - 0.5\cdot231 + 0.1\cdot24 + 2.0\cdot2 + 1.1 = -96.8\). Mô hình (với bộ trọng số tệ này) cho rằng ảnh mèo là… chó, vì dog có điểm cao nhất 437.9. Huấn luyện chính là tìm \(W, b\) để lớp đúng luôn có điểm cao nhất.

Ghi chú về con số 61.95Hình gốc (lấy từ CS231n) ghi điểm ship là 61.95, nhưng tính đúng là \(0.25\cdot231 + 0.2\cdot24 - 0.3\cdot2 - 1.2 = 60.75\). Hình gốc đã quên cộng bias. Một lời nhắc tốt: luôn tự kiểm tra lại các con số!

Hai cách nhìn cùng một phép tính

Tài liệu minh hoạ hai cách nhìn: nhân ma trận (cả \(W\) nhân vector \(x\)) và nhân từng phần tử (element-wise). Chúng là một: mỗi hàng \(w_k\) của \(W\) có cùng kích thước với ảnh; điểm của lớp \(k\) là tổng các tích từng phần tử giữa hàng đó và ảnh, tức tích vô hướng:

\[ s_k = w_k \cdot x + b_k = \sum_{j=1}^{D} w_{kj}\, x_j + b_k \]

Nếu xếp lại 784 trọng số của một hàng thành lưới 28×28, ta được một "ảnh trọng số" đặt chồng lên ảnh đầu vào: pixel nào có trọng số dương lớn mà ảnh sáng thì điểm tăng, trọng số âm thì điểm giảm.

Linear classifier "nhìn" thấy gì?

Góc nhìn 1: so khớp mẫu (template matching)

Mỗi hàng của \(W\) là một khuôn mẫu (template) cho một lớp. Hiển thị trọng số sau khi huấn luyện (trang 13–16 của tài liệu) cho thấy:

  • Với MNIST, khuôn mẫu của số 0 là một vòng tròn sáng với tâm tối: ảnh nào có nét quanh vòng và trống ở giữa sẽ được điểm cao.
  • Với CIFAR-10, khuôn của "airplane" ám màu xanh (bầu trời), "frog" ám xanh lục, "car" ám đỏ. Khuôn "horse" trông như ngựa có hai đầu vì dữ liệu có ngựa quay cả trái lẫn phải, trong khi mỗi lớp chỉ có một khuôn để "trung bình hoá" tất cả.

Góc nhìn 2: hình học

Mỗi ảnh là một điểm trong không gian \(D\) chiều. Với mỗi lớp, phương trình \(w_k\cdot x + b_k = 0\) là một siêu phẳng; bộ phân loại tuyến tính chia không gian bằng các mặt phẳng này. \(W\) quyết định hướng của mặt phẳng, \(b\) dịch chuyển nó (không có bias, mọi mặt phẳng buộc phải đi qua gốc toạ độ).

Giới hạn

  • Một khuôn mỗi lớp: không biểu diễn được các biến thể (ngựa trái, ngựa phải, ngựa nhìn thẳng).
  • Ranh giới tuyến tính: không tách được dữ liệu như bài toán XOR hay hai vòng tròn lồng nhau.
  • Nhạy với vị trí: chữ số dịch sang trái vài pixel là lệch khuôn hoàn toàn (đây là "Problems in Neural Network: Variations" ở trang 78, lý do ra đời CNN).

Từ linear classifier đến neuron

Một neuron sinh học nhận tín hiệu qua các sợi nhánh (dendrites), tổng hợp ở thân tế bào và "phát xung" theo sợi trục (axon) khi tín hiệu đủ mạnh. Neuron nhân tạo mô phỏng thô sơ điều đó:

x₁ x₂ x₃ w₁w₂w₃ Σ+ b bias b z f activation y = f(z)
Neuron = linear classifier (tổng có trọng số + bias) + hàm kích hoạt
\[ z = \sum_i w_i x_i + b, \qquad y = f(z) \]

Phần \(\sum w_i x_i + b\) chính là một hàng của linear classifier. Thêm vào một hàm kích hoạt (activation function) phi tuyến \(f\), ta được một neuron. Lưu ý phép so sánh với sinh học chỉ mang tính gợi hình; neuron thật phức tạp hơn rất nhiều.

Vì sao bắt buộc phải có hàm kích hoạt?

Thử xếp chồng hai lớp tuyến tính mà không có activation:

\[ y = W_2 (W_1 x + b_1) + b_2 = \underbrace{(W_2 W_1)}_{W'} x + \underbrace{(W_2 b_1 + b_2)}_{b'} \]

Kết quả vẫn chỉ là một phép biến đổi tuyến tính. Dù xếp 100 lớp, mạng vẫn mạnh ngang một linear classifier. Hàm kích hoạt phi tuyến chen giữa các lớp là thứ cho phép mạng "uốn cong" ranh giới quyết định và học các hàm phức tạp.

Bốn hàm kích hoạt cơ bản

HàmCông thứcMiền giá trịNhận xét nhanh
Sigmoid\(\sigma(z)=\dfrac{1}{1+e^{-z}}\)(0, 1)Hợp cho xác suất nhị phân ở đầu ra; ở lớp ẩn dễ gây vanishing gradient, không zero-centered.
Tanh\(\tanh(z)=\dfrac{e^z-e^{-z}}{e^z+e^{-z}}\)(−1, 1)Zero-centered nên tốt hơn sigmoid, nhưng vẫn bão hoà ở hai đầu.
ReLU\(\max(0, z)\)[0, +∞)Mặc định cho CNN: tính rẻ, không bão hoà phía dương. Có thể "chết" nếu \(z\) luôn âm.
Leaky ReLU\(\max(\epsilon z, z),\ \epsilon \ll 1\)(−∞, +∞)Giữ một gradient nhỏ cho phía âm (thường \(\epsilon = 0.01\)), tránh neuron chết.

Ta sẽ phân tích sâu vì sao ReLU thắng sigmoid trong bài vanishing/exploding gradient.

Kiến trúc Neural Network

Ghép nhiều neuron thành các lớp (layer), mỗi neuron của lớp sau nối với mọi neuron của lớp trước. Loại lớp này gọi là fully connected (FC), còn gọi là Dense hay Linear (tên trong PyTorch: nn.Linear).

  • Input layer: chính là dữ liệu đầu vào, không có tham số.
  • Hidden layers: các lớp ở giữa, thường có activation.
  • Output layer: cho ra điểm số các lớp (logits), thường không có activation (softmax được gộp vào hàm loss).

Quy ước đếm: "mạng N lớp" không tính input layer. Hai mạng ở trang 20 của tài liệu:

MạngSố trọng sốSố biasTổng tham số
3 → 4 → 2 (2 lớp)3·4 + 4·2 = 204 + 2 = 626
3 → 4 → 4 → 1 (3 lớp)3·4 + 4·4 + 4·1 = 324 + 4 + 1 = 941

Mạng không có vòng lặp, dữ liệu chỉ đi một chiều từ đầu vào đến đầu ra được gọi là feedforward neural network (hay MLP, multi-layer perceptron).

Forward pass: lan truyền xuôi

Tính đầu ra từ đầu vào, lần lượt qua từng lớp, gọi là forward propagation (forward pass). Với mạng 3 lớp và activation \(f\):

\[ h_1 = f(W_1 x + b_1), \quad h_2 = f(W_2 h_1 + b_2), \quad \text{out} = W_3 h_2 + b_3 \]

Nhờ biểu diễn bằng ma trận, cả lớp được tính bằng một phép nhân, rất hợp với GPU:

import numpy as np

relu = lambda z: np.maximum(0, z)

# Mạng 3 → 4 → 4 → 1, khởi tạo ngẫu nhiên
W1, b1 = np.random.randn(4, 3), np.zeros((4, 1))
W2, b2 = np.random.randn(4, 4), np.zeros((4, 1))
W3, b3 = np.random.randn(1, 4), np.zeros((1, 1))

x = np.random.randn(3, 1)          # một mẫu đầu vào
h1 = relu(W1 @ x + b1)             # (4, 1)
h2 = relu(W2 @ h1 + b2)            # (4, 1)
out = W3 @ h2 + b3                 # (1, 1)
print(out)

Khi xử lý cả một batch \(N\) mẫu, ta xếp chúng thành ma trận \(X\) kích thước \(N\times D\) và tính \(XW^T + b\) (đây đúng là việc nn.Linear làm).

Ví dụ hoàn chỉnh: phân loại chữ số MNIST

Ảnh chữ số 28×28 = 784 pixel (giá trị 0–255, chuẩn hoá về [0, 1]) được duỗi thành 784 neuron đầu vào, qua một lớp ẩn, ra 10 neuron ứng với các chữ số 0–9:

import torch
import torch.nn as nn

model = nn.Sequential(
    nn.Flatten(),            # (N, 1, 28, 28) -> (N, 784)
    nn.Linear(784, 128),     # lớp ẩn: 784*128 + 128 tham số
    nn.ReLU(),
    nn.Linear(128, 10),      # lớp ra: 10 logits
)

x = torch.rand(32, 1, 28, 28)   # batch giả 32 ảnh
logits = model(x)
print(logits.shape)              # torch.Size([32, 10])
print(sum(p.numel() for p in model.parameters()))  # 101770

Mạng nhỏ này, sau khi huấn luyện vài epoch, đạt khoảng 97–98% độ chính xác trên MNIST, vượt xa linear classifier (khoảng 92%).

Deep Neural Network và định lý xấp xỉ vạn năng

Universal Approximation Theorem (định lý xấp xỉ vạn năng) phát biểu: một mạng feedforward chỉ với một lớp ẩn, đủ nhiều neuron và activation phi tuyến phù hợp, có thể xấp xỉ mọi hàm liên tục trên một miền giới hạn với sai số nhỏ tuỳ ý.

Định lý này nghe như "một lớp là đủ", nhưng có ba điểm cần hiểu đúng:

  1. Nó chỉ nói tồn tại một bộ trọng số tốt, không nói làm sao tìm được (đó là việc của huấn luyện).
  2. Số neuron cần thiết có thể lớn theo cấp số mũ.
  3. Trên thực tế, mạng sâu biểu diễn cùng một hàm hiệu quả hơn nhiều so với mạng rộng nông, nhờ tái sử dụng đặc trưng theo tầng: cạnh → tổ hợp cạnh → bộ phận → đối tượng (trang 23 của tài liệu).
Thực hành ngay trên trình duyệtMở TensorFlow Playground (playground.tensorflow.org), chọn bộ dữ liệu hình xoắn ốc. Thử 0 lớp ẩn (linear), rồi 1, 2, 3 lớp ẩn; đổi activation giữa Linear, Tanh, ReLU. Bạn sẽ "thấy tận mắt" vì sao cần phi tuyến và độ sâu.

Tóm tắt

  • Linear classifier: \(f(x) = Wx + b\); mỗi hàng của \(W\) là khuôn mẫu cho một lớp.
  • Neuron = tổng có trọng số + bias + hàm kích hoạt phi tuyến.
  • Không có activation thì xếp bao nhiêu lớp cũng chỉ là tuyến tính.
  • Forward pass = nhân ma trận lần lượt qua các lớp; tính được số tham số bằng tay.

Mạng đã biết "đoán", nhưng làm sao biết nó đoán sai bao nhiêu và sửa \(W\) thế nào? Đó là chủ đề của bài Loss function, Gradient Descent và Optimizer.

Tài liệu tham khảo

  • CS231n: Linear classification và Neural Networks Part 1: Setting up the Architecture.
  • Cybenko (1989); Hornik (1991): các chứng minh định lý xấp xỉ vạn năng.
  • Goodfellow, Bengio, Courville. Deep Learning, chương 6 (deeplearningbook.org).
  • Dive into Deep Learning (d2l.ai), chương 4–5: Linear Neural Networks, Multilayer Perceptrons.
Ban biên tập HọcFree

Chúng tôi viết những bài hướng dẫn dễ hiểu, thực tế để ai cũng có thể tự học lập trình và ngoại ngữ, hoàn toàn miễn phí.