Transformers documentation
Các khái niệm về lượng tử hóa
Các khái niệm về lượng tử hóa
Một số đã được lượng tử hóa chỉ có thể nhận một trong một tập hợp nhỏ các giá trị, 256 giá trị với int8 và 16 giá trị với int4, do đó mọi phương pháp lượng tử hóa đều gây ra sai số làm tròn. Các phương pháp khác nhau ở cách chúng ngăn chặn sai số đó làm ảnh hưởng đến đầu ra của mô hình. Trang này giải thích các lựa chọn đằng sau những khác biệt đó: cách các số được ánh xạ sang tập hợp nhỏ đó, những tensor nào được lượng tử hóa, các kiểu dữ liệu nào được sử dụng, và khi nào quá trình lượng tử hóa diễn ra.
Nếu bạn mới bắt đầu với lượng tử hóa trong Transformers, hãy bắt đầu với Tổng quan.
Ánh xạ giá trị sang ít bit hơn
Quantization ánh xạ một khoảng các giá trị độ chính xác cao lên tập hợp nhỏ các số nguyên mà kiểu bit thấp có thể biểu diễn. int8 có thể biểu diễn 256 số nguyên, [-128, 127], và int4 có thể biểu diễn 16.
Lượng tử hóa affine là phép ánh xạ phổ biến nhất. Phép ánh xạ này lấy giá trị nhỏ nhất và lớn nhất của một tensor rồi kéo giãn khoảng giá trị nguyên lên trên nó. Trong ví dụ dưới đây, một tensor có giá trị từ -1.8 đến 2.4 được ánh xạ sang int8, và 0.0 rơi vào vị trí -19.
bf16 -1.8 0.0 2.4
├────────────────┼──────────────────────┤
▼ ▼ ▼
int8 -128 -19 127Hai tham số xác định ánh xạ.
Thang đo scale
Slà kích thước của một bước nguyên trong đơn vị gốc.Điểm không
Zlà số nguyên đại diện cho0.0.
Một giá trị x được lượng tử hóa thành số nguyên q bằng cách chia cho scale và dịch đi zero point.
Dequantizing đảo ngược ánh xạ và cho lại một xấp xỉ của x. Sự khác biệt giữa x và xấp xỉ của nó là sai số làm tròn.
Trong ví dụ trên, S xấp xỉ 0.0165 và Z là -19. Giá trị 0.5 được lượng tử hóa thành 11, và 11 được khử lượng tử hóa thành xấp xỉ 0.494, với sai số làm tròn xấp xỉ 0.006.
┌─────┐ quantize ┌────┐ dequantize ┌───────┐ │ 0.5 │ ──────────▶ │ 11 │ ───────────▶ │ 0.494 │ └─────┘ └────┘ └───────┘
Lượng tử hóa affine có hai dạng.
- Asymmetric quantization sử dụng các công thức ở trên. Phương pháp này ánh xạ chính xác khoảng giá trị, nên không có giá trị biểu diễn nào bị lãng phí khi các trọng số không được căn giữa tại số 0.
- Symmetric quantization giả định khoảng giá trị là
[-a, a]và cố địnhZbằng 0, do đó chỉ lưu trữ scale. Phép toán rẻ hơn, nhưng một số giá trị có thể biểu diễn sẽ không được sử dụng khi các trọng số lệch về một phía của số 0.
Chọn mức độ chi tiết
Một thang đo duy nhất cho toàn bộ tensor thì rẻ về chi phí lưu trữ, nhưng một giá trị ngoại lai lớn sẽ làm giãn khoảng giá trị và khiến các giá trị có thể biểu diễn của mọi trọng số khác bị phân tán xa hơn. Các nhóm nhỏ hơn giúp mỗi thang đo chỉ cần bao phủ một khoảng giá trị hẹp hơn.
- Per-tensor sử dụng một scale và một zero point cho toàn bộ tensor.
- Per-channel sử dụng một scale cho mỗi kênh đầu ra, tương ứng với mỗi hàng của ma trận trọng số.
- Per-group, hoặc per-block, sử dụng một scale cho mỗi nhóm các giá trị liên tiếp, chẳng hạn như 128 trọng số. Mỗi nhóm tốn thêm bộ nhớ lưu trữ cho scale của nó.
Sơ đồ bên dưới hiển thị ba tùy chọn trên một ma trận trọng số có ba hàng. Mỗi s là một thang đo.
per-tensor per-channel per-group ┌────────────┐ ┌────────────┐ ┌──────┬──────┐ │ │ │ │ s0 │ s0 │ s1 │ │ │ ├────────────┤ ├──────┼──────┤ │ s │ │ │ s1 │ s2 │ s3 │ │ │ ├────────────┤ ├──────┼──────┤ │ │ │ │ s2 │ s4 │ s5 │ └────────────┘ └────────────┘ └──────┴──────┘
Hầu hết các phương pháp low-bit thực hiện lượng tử hóa theo nhóm. GPTQ mặc định dùng nhóm gồm 128 trọng số, còn Fine-grained FP8 mặc định dùng khối 128x128. Các định dạng FP4 trong Data types tích hợp kích thước khối ngay vào bản thân định dạng.
Lượng tử hóa trọng số hoặc kích hoạt
Các phương pháp khác nhau ở việc chúng lượng tử hóa những tensor nào, và điều đó quyết định phép nhân ma trận được thực hiện ở đâu.
- Chỉ trọng số Các phương pháp chỉ trọng số lưu trữ trọng số ở độ chính xác thấp và giữ các kích hoạt ở bf16 hoặc fp16. Trước mỗi phép nhân ma trận, kernel sẽ khử lượng hóa trọng số sang kiểu dữ liệu tính toán có độ chính xác cao hơn. bitsandbytes 4-bit, AWQ, GPTQ và HQQ hoạt động theo cách này. Trong bitsandbytes,
bnb_4bit_compute_dtypeđặt kiểu dữ liệu tính toán đó. - Weight-and-activation quantize cả activation, và phép nhân ma trận (matmul) được thực hiện trực tiếp ở độ chính xác thấp. Phương pháp này cần phần cứng hỗ trợ matmul ở độ chính xác thấp, chẳng hạn như FP8 trên các GPU đời mới. Phương án này thường được viết là W8A8 cho trọng số và activation 8-bit.
Các phương pháp chỉ nén trọng số giúp tiết kiệm bộ nhớ nhưng không phải lúc nào cũng chạy nhanh hơn, vì việc khử lượng hóa (dequantizing) làm tăng khối lượng công việc cho mỗi phép nhân ma trận (matmul). Chúng tăng tốc độ sinh khi mô hình bị giới hạn bởi bộ nhớ. Khi sinh từng token một, GPU dành phần lớn mỗi bước để đọc trọng số từ bộ nhớ thay vì tính toán. Đọc trọng số 4-bit chỉ di chuyển một phần tư lượng dữ liệu so với trọng số bf16, và khoản tiết kiệm này có thể lớn hơn chi phí của việc khử lượng hóa.
Các phương pháp lượng hóa trọng số và kích hoạt hữu ích khi mô hình bị giới hạn bởi tính toán, chẳng hạn như trong giai đoạn prefill hoặc với batch lớn, vì chính phép nhân ma trận độ chính xác thấp đã nhanh hơn. Một số phương pháp chuyển đổi giữa hai chế độ. NVFP4 thực hiện phép nhân ma trận với trọng số 4-bit và kích hoạt 4-bit cho prefill, và phép nhân ma trận với trọng số 4-bit và kích hoạt 16-bit cho decoding.
Các kiểu dữ liệu
Loại dữ liệu xác định các giá trị mà một số lượng tử hóa có thể biểu diễn.
int8 và int4
int8 và int4 đại diện cho các số nguyên cách đều và sử dụng ánh xạ affine ở trên. int4 chỉ có thể biểu diễn 16 giá trị, do đó mất độ chính xác nhiều hơn so với int8. Các phương pháp sử dụng int4 thường lượng tử hóa theo nhóm hoặc sử dụng hiệu chuẩn để duy trì độ chính xác.
Hầu phần cứng không có kiểu lưu trữ 4-bit, nên hai giá trị int4 được ghép vào một byte. Ví dụ, giá trị đầu tiên có thể chiếm 4 bit thấp và giá trị thứ hai chiếm 4 bit cao. Các kernel sẽ tách các giá trị này trước khi thực hiện tính toán.
┌──────┐ ┌──────┐ ┌──────┬──────┐ │ val1 │ │ val2 │ │ val2 │ val1 │ │ 0101 │ │ 0011 │ → │ 0011 │ 0101 │ 1 byte └──────┘ └──────┘ └──────┴──────┘ int4 int4 high low
Một số kiểu 4-bit phân bố các giá trị có thể biểu diễn không đều nhau để phù hợp với cách các trọng số được phân bố. bitsandbytes NF4 đặt nhiều giá trị hơn của nó gần với số không, nơi mà phần lớn các trọng số nằm ở đó.
FP8
FP8 giữ nguyên bố cục số dấu phẩy động gồm một bit dấu, một phần số mũ và một phần mantissa trong 8 bit. Các giá trị có thể biểu diễn của nó nằm gần nhau hơn khi gần 0 và xa nhau hơn ở các độ lớn lớn, phù hợp với sự phân bố giá trị trong trọng số và kích hoạt.
FP8 có hai biến thể.
- E4M3 có 4 bit số mũ và 3 bit phần thập phân. Định dạng này chính xác hơn nhưng phạm vi giá trị nhỏ hơn. Đây là lựa chọn thông thường cho trọng số và kích hoạt trong quá trình suy luận.
- E5M2 có 5 bit số mũ và 2 bit phần thập phân. Nó bao phủ một phạm vi rộng hơn với độ chính xác thấp hơn.
E4M3 ┌─┬───────┬─────┐
│S│E E E E│M M M│
└─┴───────┴─────┘
E5M2 ┌─┬─────────┬───┐
│S│E E E E E│M M│
└─┴─────────┴───┘
S sign E exponent M mantissaFP8 matmuls cần hỗ trợ phần cứng, chẳng hạn như GPU NVIDIA với compute capability 8.9 trở lên (Ada, Hopper, Blackwell), AMD Instinct MI300 và Intel XPU. Transformers hỗ trợ FP8 thông qua Fine-grained FP8, FBGEMM FP8 và compressed-tensors.
FP4 với thang đo khối
FP4 có 1 bit dấu, 2 bit số mũ và 1 bit phần thập phân (E2M1). Nó chỉ biểu diễn được các giá trị 0, 0.5, 1, 1.5, 2, 3, 4 và 6, cả dương lẫn âm. Với số lượng giá trị ít như vậy, các định dạng FP4 không thể hoạt động với một hệ số tỷ lệ cho mỗi tensor. Chúng gắn một hệ số tỷ lệ cho mỗi khối nhỏ các giá trị và lưu trữ các hệ số tỷ lệ này như một phần của định dạng.
| Định dạng | Kích thước khối | Thang đo theo khối | Thang đo bổ sung |
|---|---|---|---|
| MXFP4 | 32 giá trị | 8-bit lũy thừa của hai (E8M0) | Không |
| NVFP4 | 16 giá trị | FP8 | Một thang đo FP32 cho mỗi tensor |
MXFP4 là một định dạng microscaling. Một hệ số tỷ lệ là lũy thừa của hai chỉ dịch chuyển phần mũ, nên việc áp dụng nó có chi phí thấp, nhưng nó chỉ có thể rơi vào các lũy thừa của hai. NVFP4 sử dụng các khối nhỏ hơn và một hệ số tỷ lệ FP8 có thể nhận các giá trị nằm giữa các lũy thừa của hai. Điều này giữ lại độ chính xác cao hơn, với cái giá là một hệ số tỷ lệ cho từng tensor để giữ các hệ số tỷ lệ khối FP8 trong phạm vi cho phép. Four Over Six và FP-Quant cũng tạo ra các trọng số NVFP4 hoặc MXFP4.
Ý tưởng khối tương tự cũng xuất hiện ở 8 bit. MXFP8 lưu trữ các giá trị FP8 với các thang đo khối là lũy thừa của hai, và Fine-grained FP8 nạp chúng.
Codebooks
Dưới 4 bit, một số phương pháp không còn làm tròn từng trọng số đến giá trị biểu diễn gần nhất. Chúng lượng tử hóa các nhóm trọng số cùng nhau dưới dạng vector. Một codebook chứa một tập hợp các vector đã học, và mỗi nhóm trọng số được lưu dưới dạng chỉ số của vector gần nhất với nó. AQLM mặc định sử dụng các nhóm gồm 8 trọng số và một chỉ số 16-bit, tương đương với 2 bit cho mỗi trọng số. VPTQ cũng sử dụng codebook. Việc tìm ra các codebook tốt đòi hỏi một quá trình tối ưu hóa kéo dài trên dữ liệu hiệu chuẩn, do đó các mô hình này được lượng tử hóa trước và được nạp dưới dạng checkpoint.
Khi lượng tử hóa diễn ra
Một mô hình được lượng tử hóa sau khi huấn luyện hoặc trong quá trình huấn luyện. Hầu hết các phương pháp trong Transformers thực hiện lượng tử hóa sau khi huấn luyện.
Lượng tử hóa sau huấn luyện
Lượng tử hóa sau huấn luyện (PTQ) lượng tử hóa một mô hình đã được huấn luyện, mà không thay đổi những gì mô hình đã học. Các phương pháp PTQ khác nhau ở chỗ chúng có cần dữ liệu hay không, và điều này quyết định phương pháp đó thuộc nhóm nào trong mục lục của tài liệu.
- Khi không có dữ liệu hiệu chuẩn, các thang đo được suy ra chỉ từ trọng số, và quá trình lượng tử hóa đủ nhanh để chạy trong khi mô hình đang được nạp. bitsandbytes, HQQ và torchao hoạt động theo cách này. Các phương pháp này được liệt kê dưới Lượng tử hóa trong khi nạp.
- Với dữ liệu hiệu chuẩn, phương pháp này chạy một tập dữ liệu nhỏ qua mô hình và sử dụng các kích hoạt để quyết định cách lượng tử hóa từng lớp. Hiệu chuẩn thường cho độ chính xác tốt hơn ở 4 bit và thấp hơn, nhưng mất từ vài phút đến vài giờ.
Các phương pháp hiệu chỉnh sử dụng các kích hoạt theo những cách khác nhau. GPTQ lượng tử hóa một lớp theo từng cột một và điều chỉnh các cột còn lại để bù đắp cho sai số làm tròn của mỗi cột. AWQ tìm các kênh trọng số có kích hoạt lớn nhất và tăng tỷ lệ của chúng trước khi làm tròn để bảo vệ chúng.
Nơi các lần chạy hiệu chuẩn quyết định cách bạn sử dụng phương pháp trong Transformers.
- GPTQ thực hiện hiệu chuẩn bên trong
from_pretrainedkhi bạn truyền mộtdatasetvào GPTQConfig, do đó nó được liệt kê dưới mục Quantize while loading. - Các phương pháp hiệu chuẩn khác, như AWQ, AutoRound, AQLM và VPTQ, thực hiện hiệu chuẩn trong các thư viện riêng của chúng. Transformers chỉ tải kết quả, do đó chúng được liệt kê dưới Tải checkpoint đã lượng tử hóa trước.
Huấn luyện nhận thức lượng tử hóa
Quantization-aware training (QAT) mô phỏng lượng tử hóa trong quá trình huấn luyện. Trong bước truyền thẳng, các giá trị được làm tròn giống như lượng tử hóa, trong khi gradient cập nhật trọng số độ chính xác đầy đủ, nhờ đó mô hình học cách dung sai cho lỗi làm tròn. QAT thường cho độ chính xác tốt nhất ở các độ rộng bit rất thấp, nhưng đòi hỏi phải huấn luyện mô hình.
Các mô hình BitNet được huấn luyện theo cách này, với trọng số 1.58-bit của chúng nằm trong vòng lặp, và Transformers nạp các checkpoint đã được huấn luyện.
Tài nguyên
- Nền tảng lượng tử hóa với Hugging Face
- Đi sâu vào Lượng tử hóa
- Giới thiệu về Quantization được nấu bằng 🤗 với 💗🧑🍳
- Bài giảng 5 của EfficientML.ai - Lượng tử hóa Phần I
- Đẩy mạnh Deep Learning từ những nguyên lý cơ bản
- Tăng tốc AI tạo sinh bằng PyTorch Phần 2: Tối ưu hóa LLM