7.8. Tensor I/O

Engine chấp nhận một tensor ở phía đầu vào và tạo ra một hoặc nhiều tensor ở phía đầu ra. Các tensor là các đối tượng ndarray với hình dạng, dtype và từ vựng bộ mô tả mà chương numpy đã giới thiệu. Hình dạng và dtype của chúng đến từ tệp mô hình (ML) và được báo cáo qua input_shape / output_shapeinput_dtype / output_dtype.

7.8.1. Lượng tử hóa

Hầu hết các mạng nơ-ron mà camera chạy hoạt động trên các tensor số nguyên được lượng tử hóa -- int8 hoặc uint8 -- để phù hợp với ngân sách RAM và tính toán của camera. Một tensor được lượng tử hóa mang các giá trị số nguyên biểu diễn các số thực thông qua tỷ lệ và điểm không theo từng tensor:

\[\text{real} = \text{scale} \times (q - \text{zero_point})\]
\[q = \mathrm{round}(\text{real} / \text{scale}) + \text{zero_point}\]

Tỷ lệ và điểm không đến từ hiệu chỉnh thời gian huấn luyện của mô hình (ML) và được lưu trong tệp mô hình (ML). Chúng được cung cấp qua input_scale, input_zero_point, output_scale, và output_zero_point -- mỗi cái là một danh sách với một phần tử cho mỗi tensor đầu vào hoặc đầu ra.

ml.utils.quantize()ml.utils.dequantize() áp dụng các công thức theo một chỉ số đầu ra được chỉ định:

import ml.utils

real_tensor = ml.utils.dequantize(model, q_tensor, index=0)
q_tensor    = ml.utils.quantize(model, real_tensor, index=0)

Cả hai hàm đều trả về giá trị không thay đổi khi dtype đầu ra tại chỉ số cho trước đã là float, vì vậy lời gọi an toàn bất kể trạng thái lượng tử hóa của mô hình (ML).

7.8.2. Những gì tập lệnh thấy ở phía đầu ra

Những gì predict() trả về phụ thuộc vào việc có bộ xử lý hậu kỳ nào được đăng ký hay không.

Khi không có bộ xử lý hậu kỳ, các đầu ra số nguyên thô của engine được tự động giải lượng tử hóa sang float và trả về dưới dạng danh sách các đối tượng ndarray float. Tập lệnh nhận được các số thực sẵn sàng để đọc. Đây là con đường phù hợp cho các mạng nơ-ron phân loại, có tensor đầu ra duy nhất đã là danh sách điểm tin cậy theo từng lớp mà ứng dụng duyệt qua -- không cần bước giải mã. Đây cũng là con đường dễ dàng để chạy nhanh một mô hình (ML) chưa biết hoặc để kiểm tra tùy tiện từ REPL.

Khi có bộ xử lý hậu kỳ được đăng ký (qua postprocess= trên hàm khởi tạo hoặc callback= trên lời gọi predict), các tensor số nguyên được lượng tử hóa thô được truyền trực tiếp đến callable của bộ xử lý hậu kỳ. Bộ xử lý hậu kỳ nhận các tensor được lượng tử hóa thô và chịu trách nhiệm về bất kỳ việc giải lượng tử hóa nào nó cần.

Sự phân tách là lựa chọn về hiệu suất. Tự động giải lượng tử hóa cấp phát một tensor float mới cho mỗi đầu ra và duyệt qua từng phần tử. Một bộ xử lý hậu kỳ chỉ cần một vài giá trị từ mỗi tensor -- áp ngưỡng điểm tin cậy, sau đó giải mã các hộp giới hạn cho những cái vượt qua -- bỏ qua chi phí giải lượng tử hóa phần còn lại. Các bộ giải mã hộp giới hạn trong ml.postprocessing đều đi theo con đường này, và ml.utils.threshold() được xây dựng chính xác cho trường hợp này: nó nhận một tensor điểm được lượng tử hóa và trả về các chỉ số có giá trị đã giải lượng tử hóa vượt qua ngưỡng thực, mà không giải lượng tử hóa toàn bộ tensor.