2Máy tính biểu diễn số như thế nào#
Để hiểu quantization làm gì, trước hết phải hiểu dữ liệu vốn được lưu thế nào.
2.1Số nguyên#
Với bit:
- Không dấu (unsigned): biểu diễn . Ví dụ uint8: .
- Có dấu, dạng bù hai (two's complement): biểu diễn . Ví dụ int8: ; int4: .
Các số nguyên liền kề cách nhau đúng 1 đơn vị ở mọi vị trí. Ta nói số nguyên có độ chính xác tuyệt đối đều.
2.2Số dấu phẩy động theo chuẩn IEEE 754#
Một số dấu phẩy động gồm ba trường: bit dấu , phần mũ (exponent) và phần định trị (mantissa). Với số chuẩn hóa (normal), giá trị là
Chữ số 1 đứng trước dấu chấm là bit ẩn: nó không được lưu nhưng luôn có mặt, nên mantissa bit cho độ chính xác bit. Khi ta có số dưới chuẩn (subnormal) , cho phép biểu diễn các số rất gần 0.
Đoạn mã sau tách ba trường của một số FP32:
import struct
def fp32_fields(x):
bits = struct.unpack(">I", struct.pack(">f", x))[0]
s = f"{bits:032b}"
return s[0], s[1:9], s[9:], int(s[1:9], 2) - 127 # dấu, exponent, mantissa, số mũ thật
for x in [1993.0, 0.1, -6.5]:
print(x, fp32_fields(x))
1993.0 ('0', '10001001', '11110010010000000000000', 10)
0.1 ('0', '01111011', '10011001100110011001101', -4)
-6.5 ('1', '10000001', '10100000000000000000000', 2)
Diễn giải kết quả:
- . Exponent lưu ; mantissa lưu 10 chữ số sau dấu chấm, phần còn lại là số 0. Như vậy không có "bit dành cho phần nguyên" hay "bit dành cho dấu phẩy": vị trí dấu chấm được mã hóa gián tiếp qua số mũ.
- có biểu diễn nhị phân vô hạn tuần hoàn (), nên FP32 chỉ lưu được một giá trị xấp xỉ. Bản thân FP32 đã là một phép lượng tử hóa của tập số thực.
2.3Các kiểu dữ liệu dùng trong deep learning#

| Kiểu | Exp / Man | Bias | Giá trị lớn nhất | Số chuẩn nhỏ nhất | máy |
|---|---|---|---|---|---|
| FP32 | 8 / 23 | 127 | |||
| FP16 | 5 / 10 | 15 | |||
| BF16 | 8 / 7 | 127 | |||
| FP8 E4M3 (OCP) | 4 / 3 | 7 | |||
| FP8 E5M2 | 5 / 2 | 15 |
máy là khoảng cách từ 1 đến số biểu diễn được kế tiếp lớn hơn 1. Nó đo độ chính xác tương đối.
Nhận xét:
- FP16 có dải hẹp (tối đa 65 504), dễ tràn số khi huấn luyện. BF16 giữ nguyên 8 bit exponent của FP32 nên có cùng dải, đổi lại mantissa ngắn hơn. Đây là lý do BF16 được ưa dùng để huấn luyện.
- FP8 có hai biến thể (Micikevicius và cộng sự, 2022). E4M3 chính xác hơn, thường dùng cho trọng số và activation. E5M2 có dải rộng hơn, thường dùng cho gradient. Biến thể E4M3 của chuẩn OCP bỏ giá trị vô cực và chỉ giữ một mã NaN để nâng giá trị lớn nhất lên 448.
Có thể quan sát trực tiếp hiệu ứng làm tròn và tràn số của FP16:
import numpy as np
print(np.float16(1993.0), np.float16(1993.5), np.float16(2049.0), np.float16(70000.0))
# 1993.0 1994.0 2048.0 inf
Trong khoảng , các số FP16 cách nhau 1, nên được làm tròn về số chẵn gần nhất là . Trong khoảng khoảng cách là 2, nên . Còn vượt quá nên thành vô cực.
2.4Khác biệt cốt lõi: độ chính xác tương đối và tuyệt đối#

Số dấu phẩy động có lưới dày gần 0 và thưa dần khi ra xa: sai số tương đối xấp xỉ không đổi. Số nguyên có lưới cách đều: sai số tuyệt đối không đổi. Do đó, muốn dùng số nguyên để biểu diễn số thực, ta phải chọn khéo vị trí và độ rộng của lưới cách đều ấy sao cho khớp với dữ liệu. Đó chính là vai trò của hai tham số và trong chương sau.
Tự kiểm tra
3 câu. Chọn đáp án để xem ngay lời giải thích.
1Phát biểu nào đúng về cách FP32 lưu một số?
Vì sao: Không hề có "bit dành cho phần nguyên". Giá trị là , nên dấu chấm trôi theo số mũ — đó chính là nghĩa của "dấu phẩy động".2Vì sao BF16 được ưa dùng để huấn luyện hơn FP16?
Vì sao: Cả hai đều 16 bit. FP16 chỉ có 5 bit exponent, giá trị lớn nhất 65 504 nên rất dễ tràn. BF16 đánh đổi mantissa ngắn hơn (7 bit) để lấy dải rộng bằng FP32.3Khác biệt cốt lõi giữa lưới của số dấu phẩy động và của số nguyên là gì?
Vì sao: Chính vì số nguyên có lưới cách đều mà ta phải chọn khéo vị trí và độ rộng của lưới cho khớp dữ liệu — đó là vai trò của và .
Đã trả lời 0/3