Normalizing Flows
Normalizing flow ánh xạ nhiễu đơn giản thành dữ liệu phức tạp thông qua các lớp khả nghịch, nhờ đó một model có thể vừa lấy mẫu vừa tính likelihood chính xác. Tìm hiểu cách hoạt động.
Model normalizing flow là một model AI tạo sinh, biến đổi một phân phối cơ sở đơn giản, thường là phân phối Gaussian chuẩn, thành phân phối dữ liệu phức tạp thông qua chuỗi hàm khả nghịch và khả vi. Vì mọi layer đều có thể chạy ngược và tác động của nó lên thể tích được tính chính xác, một flow thực hiện được hai việc mà hầu hết model tạo sinh không thể kết hợp: tạo mẫu mới bằng cách truyền nhiễu xuôi qua các layer, và tính likelihood chính xác của một điểm dữ liệu quan sát được bằng cách truyền điểm đó ngược về phân phối cơ sở. Esteban Tabak và các cộng sự đã xây dựng flow cho việc ước lượng mật độ vào năm 2010 và 2013; Danilo Rezende và Shakir Mohamed tại DeepMind đưa thuật ngữ này vào deep learning với bài báo Variational Inference with Normalizing Flows tại ICML 2015. “Normalizing” nói đến việc biến phân phối dữ liệu thành phân phối chuẩn, hay Gaussian, và không liên quan đến batch normalization.
Công thức đổi biến#
Nếu hàm khả nghịch f ánh xạ một điểm dữ liệu x thành điểm latent z = f(x), log-likelihood của dữ liệu là log p(x) = log p_z(f(x)) + log |det J|, trong đó J là ma trận Jacobian của f và định thức đo mức độ f làm giãn hoặc co thể tích quanh x. Với hàm tổng quát gồm D biến, việc tính định thức cần số phép toán cỡ D³, quá chậm đối với ảnh có hàng trăm nghìn chiều. Vì vậy, các layer flow được thiết kế với Jacobian tam giác, trong đó định thức chỉ là tích các phần tử trên đường chéo. Xếp chồng nhiều layer như vậy sẽ hợp thành các phép biến đổi và cộng các log-determinant; quá trình huấn luyện trực tiếp tối đa hóa log-likelihood của dữ liệu huấn luyện.
Layer affine coupling của RealNVP là thiết kế kinh điển. Một nửa đầu vào được giữ nguyên và đưa vào một mạng neural nhỏ để xác định hệ số tỷ lệ và độ dịch cho nửa còn lại, như trong layer PyTorch này:
import torch
from torch import nn
torch.manual_seed(0)
# Affine coupling layer (RealNVP): x1 passes through unchanged and sets the scale and shift for x2
net = nn.Sequential(nn.Linear(2, 32), nn.Tanh(), nn.Linear(32, 4))
def coupling(x):
"""Map data x to z and return log|det J|, which is just the sum of the log-scales."""
x1, x2 = x.chunk(2, dim=-1)
log_s, t = net(x1).chunk(2, dim=-1)
return torch.cat([x1, x2 * log_s.exp() + t], dim=-1), log_s.sum(dim=-1)
x = torch.randn(4)
z, log_det = coupling(x)
jacobian = torch.autograd.functional.jacobian(lambda v: coupling(v)[0], x)
print(f"log|det J|: {log_det:.4f} from the formula, {torch.logdet(jacobian):.4f} from the full 4x4 Jacobian")
# Inverse: z1 equals x1, so the same scale and shift can be recomputed and undone
z1, z2 = z.chunk(2)
log_s, t = net(z1).chunk(2)
x_rec = torch.cat([z1, (z2 - t) * (-log_s).exp()])
print(f"Largest reconstruction error: {(x_rec - x).abs().max():.1e}")Công thức đơn giản và Jacobian đầy đủ đều cho log-determinant bằng 0.1489; phép nghịch đảo khôi phục đầu vào với sai số tối đa 1.2e-07, do làm tròn float32. Mạng bên trong layer không bao giờ cần được nghịch đảo, nên có thể có độ phức tạp tùy ý.
Các kiến trúc flow#
- Flow coupling: NICE (2014) và RealNVP (2016) của Laurent Dinh và các cộng sự luân phiên biến đổi từng nửa; Glow (2018) của OpenAI bổ sung các tích chập 1 x 1 khả nghịch được học và tạo ra khuôn mặt 256 x 256 chân thực. Cả lấy mẫu lẫn đánh giá mật độ đều nhanh.
- Flow tự hồi quy: Biến đổi từng chiều dựa trên các chiều đứng trước nó. Masked autoregressive flow đánh giá mật độ trong một lượt nhưng lấy mẫu từng chiều một; inverse autoregressive flow thì làm ngược lại. TarFlow (2024) của Apple xếp chồng các khối transformer tự hồi quy trên các patch ảnh và là flow độc lập đầu tiên có mẫu đạt chất lượng ngang với model diffusion.
- Flow liên tục: Định nghĩa phép biến đổi là nghiệm của phương trình vi phân thường, loại bỏ các ràng buộc về thiết kế layer; FFJORD (2018) theo dõi sự thay đổi của log-density bằng bộ ước lượng vết ngẫu nhiên.
Ứng dụng#
- Phát hiện bất thường: DifferNet (2021), CFLOW-AD và FastFlow khớp flow với các đặc trưng của mạng neural tích chập được tiền huấn luyện trên ảnh sản phẩm không lỗi, rồi gắn cờ những ảnh có likelihood thấp là ảnh lỗi. Năm 2021, FastFlow báo cáo AUC 99.4% cho phát hiện bất thường trên benchmark kiểm tra công nghiệp MVTec AD.
- Tổng hợp tiếng nói: WaveGlow (2018) của NVIDIA tạo âm thanh lời nói từ phổ mel trong một lượt xử lý song song.
- Lấy mẫu khoa học: Boltzmann generator (2019) của Frank Noé và các cộng sự lấy mẫu trạng thái cân bằng của phân tử và protein, sử dụng likelihood chính xác để gán lại trọng số cho mẫu theo phân phối vật lý thực.
Các bộ phát hiện này mô hình hóa đặc trưng thay vì pixel vì một lý do mà Eric Nalisnick và các cộng sự đã chứng minh vào năm 2019: model Glow được huấn luyện trên ảnh CIFAR-10 gán likelihood cao hơn cho ảnh số nhà SVHN chưa từng thấy; về sau, người ta xác định nguyên nhân là flow mô hình hóa tương quan pixel cục bộ nhiều hơn nội dung ảnh. Để phát hiện lỗi, đầu vào của flow có thể là embedding từ bất kỳ backbone nào được tiền huấn luyện: phương thức embed của Ultralytics YOLO26 trả về một vector đặc trưng trung bình theo pooling cho mỗi ảnh, mặc định lấy từ layer ngay trước detection head.
Normalizing flow và các thuật ngữ liên quan#
- Flow matching và rectified flow: Huấn luyện flow liên tục bằng cách hồi quy trường vận tốc, không cần log-determinant trong quá trình huấn luyện; hiện nay các phương pháp này là nền tảng cho những model tạo ảnh quy mô lớn.
- Variational autoencoder và model diffusion: Huấn luyện trên cận dưới của likelihood.
- GAN: Học cách đánh lừa bộ phân biệt và hoàn toàn không cung cấp likelihood.
- Mạng luồng sinh (GFlowNets): Cùng có từ “flow” trong tên nhưng xây dựng các đối tượng rời rạc theo từng bước, với xác suất tỷ lệ thuận với phần thưởng.










