Trong quy trình tối ưu hóa mô hình AI cho các chip chuyên dụng như Horizon Journey 5 (J5) hoặc XJ3, Post-Training Quantization (PTQ) là bước quan trọng để chuyển đổi mô hình từ dấu phẩy động (Float32) sang định dạng điểm cố định (Fixed-point). Tuy nhiên, quá trình này thường dẫn đến sai số lượng tử hóa. Để giải quyết vấn đề này, bộ công cụ Horizon Toolchain cung cấp các tính năng Debug giúp xác định chính xác nguyên nhân gây giảm độ chính xác và đưa ra phương án tối ưu.
Nguyên nhân gây sụt giảm độ chính xác trong PTQ
Thông thường, sai số trong quá trình lượng tử hóa PTQ xuất phát từ hai nguyên nhân chính:
- Nút nhạy cảm (Sensitive Nodes): Một số lớp (layer) trong mạng neural cực kỳ nhạy cảm với việc giảm số bit biểu diễn, gây ra lỗi lớn ngay cả khi chỉ lượng tử hóa riêng lớp đó.
- Tích tụ sai số (Error Accumulation): Sai số nhỏ từ trọng số (weights) hoặc dữ liệu kích hoạt (activations) của từng lớp cộng dồn qua nhiều tầng, dẫn đến kết quả đầu ra cuối cùng bị sai lệch nghiêm trọng.
Quy trình chuẩn bị dữ liệu Debug
Để bắt đầu quá trình phân tích, bạn cần cấu hình tệp YAML để xuất dữ liệu hiệu chuẩn (calibration data). Trong phần thông số mô hình, hãy thêm cấu hình sau:
# Cấu hình trong tệp YAML của mô hình
model_parameters:
debug_mode: "dump_calibration_data"
Sau khi chạy biên dịch mô hình với mức tối ưu O0, công cụ sẽ tạo ra thư mục model_output chứa:
- calibrated_model.onnx: Mô hình chứa các nút
HzCalibrationlưu trữ tham số Scale và Threshold. - calibration_data: Dữ liệu đầu vào thực tế đã qua tiền xử lý ở định dạng
.npy, sẵn sàng để đưa vào mô hình hiệu chuẩn.
Sử dụng công cụ Debug tự động (One-click Run)
Cách nhanh nhất để nhận báo cáo tổng thể là sử dụng hàm runall. Hàm này sẽ thực hiện tuần tự việc tính toán độ nhạy, vẽ đường cong sai số và biểu đồ phân phối dữ liệu.
import horizon_nn.debug as hzn_dbg
# Chạy toàn bộ quy trình debug
hzn_dbg.runall(
model_or_file='./model_output/calibrated_model.onnx',
calibrated_data='./model_output/calibration_data',
save_dir='./debug_results'
)
Dữ liệu kết quả sẽ giúp bạn đánh giá nhanh mô hình theo thứ tự: phân tích sai số tích tụ -> xác định loại lỗi (trọng số hay kích hoạt) -> tìm nút nhạy cảm -> kiểm tra phân phối kênh.
Phân tích đường cong sai số tích tụ
Tính năng này cho phép bạn biết được sai số tăng lên như thế nào khi lần lượt lượng tử hóa các lớp. Bạn có thể cô lập chỉ lượng tử hóa trọng số hoặc chỉ lượng tử hóa kích hoạt để xem bên nào gây lỗi nhiều hơn.
import horizon_nn.debug as hzn_dbg
# Vẽ biểu đồ sai số tích tụ cho trọng số và kích hoạt
hzn_dbg.plot_acc_error(
model_or_file='calibrated_model.onnx',
calibrated_data='calibration_data',
quantize_node=['weight', 'activation'],
metric='cosine-similarity',
save_dir='./error_plots'
)
Phân tích kết quả: Nếu đường cong của activation dốc xuống nhanh hơn weight, mô hình của bạn đang gặp vấn đề với việc lượng tử hóa dữ liệu đầu ra của các lớp. Lúc này, việc chuyển đổi một số lớp sang định dạng Int16 hoặc chạy trên CPU có thể là giải pháp cần thiết.
Đánh giá độ nhạy của từng nút
Để biết chính xác lớp nào là "thủ phạm" gây lỗi, chúng ta sử dụng hàm tính toán độ nhạy. Kết quả trả về sẽ liệt kê các nút có sai số Cosine Similarity thấp nhất hoặc MSE cao nhất.
import horizon_nn.debug as hzn_dbg
import logging
logging.getLogger().setLevel(logging.INFO)
# Lấy danh sách các nút gây lỗi nhiều nhất
sensitivity_results = hzn_dbg.get_sensitivity_of_nodes(
model_or_file='calibrated_model.onnx',
calibrated_data='calibration_data',
node_type='node', # Phân tích lớp tổng quát
metrics=['cosine-similarity', 'mse'],
verbose=True
)
Kiểm tra phân phối dữ liệu theo kênh (Channel-wise)
Trong nhiều trường hợp, lỗi lượng tử hóa xảy ra do sự chênh lệch giá trị quá lớn giữa các kênh trong cùng một lớp. Biểu đồ hộp (Boxplot) sẽ giúp phát hiện các giá trị ngoại lai (outliers).
import horizon_nn.debug as hzn_dbg
# Phân tích phân phối theo từng channel của một nút cụ thể
hzn_dbg.get_channelwise_data_distribution(
model_or_file='calibrated_model.onnx',
calibrated_data='calibration_data',
nodes_list=['Conv_sample_node_1'],
save_dir='./distribution_results'
)
Nếu một kênh có phạm vi giá trị (range) lớn bất thường so với các kênh khác, phương pháp lượng tử hóa per-tensor sẽ không hiệu quả. Khi đó, bạn nên cân nhắc chuyển sang per-channel hoặc điều chỉnh cấu trúc mạng (như thêm BatchNorm) để làm mượt dữ liệu trước khi lượng tử hóa.
Chiến lược tối ưu hóa dựa trên kết quả Debug
- Nếu lỗi do Trọng số (Weight): Thường do phân phối trọng số không đều. Giải pháp là sử dụng QAT (Quantization Aware Training).
- Nếu lỗi do Kích hoạt (Activation): Thử tăng độ chính xác lên
Int16cho các nút nhạy cảm (đối với chip J5) hoặc đẩy nút đó xử lý trên CPU. - Nếu biểu đồ phân phối dữ liệu không có dạng hình chuông (Normal Distribution): Xem xét lại quy trình tiền xử lý dữ liệu đầu vào hoặc thêm các lớp chuẩn hóa vào mô hình.