Quantization trong Deep Learning
Quantization trong Deep Learning: giải thích từ A đến Z

Quantization là kỹ thuật dùng ít bit hơn để lưu mỗi con số trong model, nhờ đó model nhỏ hơn, chạy nhanh hơn và rẻ hơn, đổi lại một chút độ chính xác.
Model càng lớn, bộ nhớ càng thành nút thắt
Một model 7 tỷ tham số lưu ở FP16 (2 byte mỗi tham số) chiếm khoảng 14 GB chỉ riêng trọng số. Với model 70 tỷ tham số, con số này là khoảng 140 GB, nhiều hơn VRAM của một GPU 80 GB. Chưa kể KV cache, activations và các buffer khác khi chạy.
Muốn chạy được model như vậy, ta có hai hướng: mua thêm phần cứng, hoặc làm cho model nhẹ đi. Quantization là hướng thứ hai, và hiện là một trong những kỹ thuật phổ biến nhất trong AI engineering. Hầu hết model bạn chạy local bằng Ollama hay llama.cpp, hoặc model được serve với chi phí thấp, đều đã được quantize.
Bài viết này đi từ ý tưởng cơ bản đến các kỹ thuật thực tế: quantization là gì, vì sao hiệu quả, có những kiểu nào, và khi nào nên dùng.
Quantization là gì?
Quantization là ánh xạ các giá trị liên tục hoặc có độ chính xác cao (như số thực 16 bit) sang một tập giá trị rời rạc, nhỏ hơn (như số nguyên 4 hoặc 8 bit), kèm thông tin để khôi phục lại giá trị xấp xỉ khi cần.
Cách hình dung dễ nhất: thước kẻ. Một thước có vạch đến từng milimet đo chính xác hơn thước chỉ có vạch centimet. Quantization giống như thay thước mm bằng thước cm: ta ghi lại "vạch gần nhất" thay vì giá trị chính xác. Ít vạch hơn thì ghi nhớ nhẹ hơn, nhưng mỗi phép đo bị lệch một chút.
Công thức cơ bản
Với quantization đối xứng, ta chọn một hệ số scale rồi làm tròn:
Trong đó w là trọng số gốc, s là scale, q là số nguyên được lưu, q_max là giá trị nguyên lớn nhất (với INT4 đối xứng là 7), và ŵ là giá trị khôi phục xấp xỉ.
Ví dụ với 8 trọng số
Ta quantize 8 trọng số sang INT4. Giá trị tuyệt đối lớn nhất là 1.27, nên scale = 1.27 / 7 ≈ 0.1814.
Sai số lớn nhất là 0.076 và trung bình là 0.041, luôn nhỏ hơn hoặc bằng scale / 2 ≈ 0.091. Thay vì 8 số 16 bit (128 bit), ta lưu 8 số 4 bit (32 bit) cộng một scale. Đó là toàn bộ ý tưởng; mọi kỹ thuật phức tạp hơn đều xoay quanh việc chọn scale tốt hơn và giảm sai số này.
Vì sao quantization hiệu quả?
Quantization mang lại lợi ích ở bốn mặt, trong đó mặt thứ hai thường bị bỏ qua nhưng lại quan trọng nhất với LLM.
1) Tiết kiệm bộ nhớ. Model 7B: khoảng 14 GB ở FP16, 7 GB ở INT8, 3.5-4 GB ở INT4. Đủ để chạy trên laptop hoặc GPU consumer.
2) Giảm áp lực băng thông bộ nhớ. Khi sinh từng token, GPU phải đọc toàn bộ trọng số từ VRAM cho mỗi token. Quá trình decode thường bị giới hạn bởi tốc độ đọc bộ nhớ chứ không phải tốc độ tính toán, nên đọc ít byte hơn nghĩa là sinh token nhanh hơn.
3) Giảm chi phí serving. Cùng một GPU chứa được model lớn hơn, hoặc nhiều request song song hơn nhờ còn dư bộ nhớ cho KV cache.
4) Triển khai on-device. Điện thoại, laptop, thiết bị nhúng không có hàng chục GB VRAM.
Phần cứng hiện đại còn hỗ trợ phép nhân ma trận trực tiếp ở độ chính xác thấp (INT8, FP8) trên tensor core, nên khi quantize cả activations, phần tính toán cũng nhanh hơn chứ không chỉ tiết kiệm bộ nhớ.
Các kiểu dữ liệu hay gặp
Khi nói "quantize xuống 8 bit" hay "4 bit", thực tế có nhiều định dạng số khác nhau. Bảng dưới đây tóm tắt các định dạng phổ biến.
Một điểm cần phân biệt: dạng số thực (FP) có lưới giá trị thưa dần khi độ lớn tăng, trong khi số nguyên (INT) có các mức cách đều nhau và cần scale để ánh xạ trở lại. Do đó INT luôn đi kèm scale, còn FP thì tự mang sẵn một phần "scale" trong phần số mũ.
Các hướng tiếp cận chính
Có thể chia quantization theo hai câu hỏi: quantize khi nào (sau hay trong lúc train) và quantize cái gì (chỉ weights hay cả activations, KV cache).
Quantize khi nào
- PTQ (Post-Training Quantization): quantize model đã train xong, không cần train lại, thường chỉ cần một ít dữ liệu mẫu để hiệu chỉnh (calibration). Nhanh và rẻ, là lựa chọn mặc định cho LLM.
- QAT (Quantization-Aware Training): mô phỏng quantization trong lúc train hoặc fine-tune để model tự thích nghi với sai số làm tròn. Chất lượng tốt hơn ở mức bit rất thấp, nhưng tốn công sức và tài nguyên hơn nhiều.
Quantize cái gì
- Weight-only (ví dụ W4A16): chỉ nén weights, activations giữ ở 16 bit. Đơn giản, hiệu quả khi bị giới hạn bởi băng thông bộ nhớ.
- Weight + activation (W8A8, FP8): nén cả hai để dùng tensor core INT8/FP8, tăng tốc phần tính toán (hữu ích cho prefill và batch lớn). Khó hơn vì activations có nhiều giá trị ngoại lai (outlier).
- KV cache quantization: nén bộ nhớ lưu key-value của attention để hỗ trợ context dài hoặc batch lớn.
- QLoRA: giữ model gốc ở 4 bit (NF4) và chỉ train các adapter LoRA nhỏ, giúp fine-tune model lớn trên GPU nhỏ.
Một số phương pháp tiêu biểu
Những chi tiết kỹ thuật quyết định chất lượng
Cùng là "INT4", nhưng hai bản quantize có thể cho chất lượng rất khác nhau. Sự khác biệt nằm ở các lựa chọn sau.
Đối xứng hay bất đối xứng. Quantization đối xứng (như ví dụ ở trên) đặt số 0 của số nguyên đúng vào 0 của giá trị thực, chỉ cần scale. Quantization bất đối xứng thêm một zero-point để dịch dải giá trị, phù hợp khi dữ liệu lệch (ví dụ activations sau ReLU toàn số dương), vì không phí phạm các mức cho phần âm không tồn tại.
Độ mịn của scale (granularity). Một scale cho cả tensor (per-tensor) rẻ nhất nhưng nhạy với giá trị ngoại lai. Per-channel dùng một scale cho mỗi kênh đầu ra. Per-group (nhóm 64 hoặc 128 trọng số) cân bằng tốt giữa chất lượng và chi phí lưu scale, và là lựa chọn phổ biến ở 4 bit.
Outlier. Một vài giá trị rất lớn kéo scale lên cao, khiến hầu hết giá trị nhỏ bị làm tròn về 0. Đây là lý do chính khiến chia nhóm, SmoothQuant và LLM.int8() ra đời. Ví dụ minh họa: nếu một tensor có outlier 12.0 thì scale ≈ 12.0 / 7 ≈ 1.71, và trọng số 0.05 sẽ thành q = 0; khi chia nhóm, nhóm không có outlier có scale nhỏ hơn nhiều và giữ được chi tiết.
Calibration. Với PTQ, ta chạy một tập dữ liệu nhỏ (thường vài trăm mẫu) qua model để đo phân phối activations và chọn scale phù hợp. Dữ liệu calibration nên giống dữ liệu thật mà model sẽ gặp.
Các lớp giữ ở độ chính xác cao. Embedding, lớp output (lm_head) và đôi khi lớp đầu/cuối nhạy cảm hơn nên thường được bỏ qua khỏi quantization. Đây cũng là lý do file "4 bit" thực tế thường lớn hơn một chút so với phép tính lý thuyết.
Đánh đổi và rủi ro
Quantization không miễn phí. Chất lượng giảm ít hay nhiều phụ thuộc vào mức bit, kích thước model và loại tác vụ.
- Mức bit. 8 bit gần như không mất chất lượng; 4 bit thường chấp nhận được với model đủ lớn; dưới 4 bit (3, 2 bit) thường giảm rõ rệt nếu không có kỹ thuật đặc biệt hoặc QAT.
- Kích thước model. Model lớn "chịu nén" tốt hơn model nhỏ: cùng mức 4 bit, model 70B thường mất ít hơn model 1-3B.
- Loại tác vụ. Suy luận toán học, code phức tạp, tool calling và output có cấu trúc chặt (JSON) là những nơi sự giảm chất lượng dễ lộ ra hơn so với hội thoại thông thường.
- Perplexity không đủ. Perplexity chỉ đo khả năng dự đoán token, không phản ánh đầy đủ chất lượng trên tác vụ cụ thể. Nên đánh giá trên bộ test của chính bạn.
- Phần cứng và kernel. Quantize mà không có kernel tối ưu cho phần cứng thì có thể không nhanh hơn, thậm chí chậm hơn do phải dequantize.
- Không phải lúc nào cũng giúp tăng tốc. Nếu điểm nghẽn là tính toán (prefill, batch lớn), weight-only quantization giúp ít; khi đó nên cân nhắc W8A8 hoặc FP8.
Các nhận định trên mang tính quy luật chung từ thực tế triển khai, không phải con số cố định: mỗi model, phương pháp quantize và bộ dữ liệu cho kết quả khác nhau.
Nên chọn gì trong thực tế?
Quy trình đề xuất
1. Bắt đầu với model gốc (BF16/FP16) và đo chất lượng cũng như độ trễ trên bộ test đại diện cho use case thật.
2. Thử 8 bit trước. Nếu đủ bộ nhớ và đạt mục tiêu chi phí, dừng ở đây.
3. Nếu cần nhỏ hơn, thử 4 bit với nhóm 64 hoặc 128 và so sánh lại trên cùng bộ test.
4. Đo cả chất lượng lẫn tốc độ thực tế trên phần cứng đích, không suy từ lý thuyết.
5. Nếu chất lượng trên một tác vụ cụ thể tụt, cân nhắc mức bit cao hơn, phương pháp khác (AWQ thay GPTQ) hoặc giữ các lớp nhạy cảm ở độ chính xác cao.
Các tên công cụ và mức quantize trên là gợi ý phổ biến tại thời điểm viết; hỗ trợ thực tế thay đổi theo phiên bản thư viện và đời GPU, nên hãy kiểm tra tài liệu của công cụ bạn dùng.
Kết luận
Quantization đổi một chút độ chính xác lấy bộ nhớ, tốc độ và chi phí. Ý tưởng cốt lõi chỉ gồm ba bước: tính scale, làm tròn về số nguyên, và nhân lại với scale khi chạy. Phần còn lại của lĩnh vực là làm sao chọn scale tốt hơn, xử lý outlier và bảo vệ những phần quan trọng của model.
Quy tắc thực tế để nhớ: bắt đầu ở 8 bit, thử 4 bit nếu cần, và luôn đo trên tác vụ thật của bạn.
Tài liệu tham khảo
GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers
AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration
SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models
LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale
AI
Discussion
Comments
Loading comments…