7.15. Viết bộ xử lý của riêng bạn¶
Khi danh mục không bao gồm một mô hình -- một mạng nghiên cứu có bố cục đầu ra tùy chỉnh, một biến thể của kiến trúc hiện có, một tensor có cách diễn giải ngữ nghĩa phụ thuộc vào ứng dụng -- ứng dụng cung cấp bộ xử lý hậu kỳ của riêng mình. Giao thức rất đơn giản: một callable nhận (model, inputs, outputs) và trả về bất cứ điều gì ứng dụng mong đợi từ predict().
Một lớp có __call__ là dạng thông thường:
class MyPostprocessor:
def __init__(self, threshold=0.5):
self.threshold = threshold
def __call__(self, model, inputs, outputs):
...
return result
Một hàm đơn thuần cũng hoạt động -- engine chỉ kiểm tra rằng đối tượng có thể gọi được.
7.15.1. Kết nối vào hệ thống¶
Hai điểm gắn kết. Tham số keyword postprocess= trên constructor ràng buộc callable cho mỗi lần gọi predict() trên mô hình:
model = ml.Model("/rom/my_model.tflite",
postprocess=MyPostprocessor())
Để ghi đè ràng buộc cho một lần gọi duy nhất -- hoán đổi bộ giải mã mà không cần tải lại mô hình -- truyền callback= trực tiếp vào predict:
result = model.predict([img], callback=MyOtherPostprocessor())
Chữ ký callable giống nhau trong cả hai trường hợp.
7.15.2. Những gì callable nhận được¶
model-- thực thểModel, hữu ích cho các tham số lượng tử hóa (output_scale,output_zero_point,output_dtype) và kích thước đầu vào (input_shape).inputs-- danh sách các đầu vào mà ứng dụng đã truyền vàopredict(). Phần tử đầu tiên thường là thực thểNormalizationđã được ràng buộc; thuộc tínhroicủa nó là những gìNMSmong đợi để ánh xạ lại các hộp về ảnh gốc.outputs-- các tensor đầu ra thô dưới dạng danh sách các đối tượngndarray, theo dtype gốc của chúng. Các đầu ra float đến nguyên vẹn; các đầu ra số nguyên đến dưới dạng đã lượng tử hóa.
7.15.3. Số học lượng tử hóa¶
Tất cả các bộ giải mã đi kèm đều sử dụng cùng các hàm trợ giúp trong ml.utils, và một bộ xử lý tùy chỉnh thường muốn cùng mẫu: quantize() chuyển ngưỡng float vào không gian lượng tử hóa của mô hình, threshold() lọc mà không cần lượng tử hóa toàn bộ tensor, và dequantize() chạy một lần trên các ứng viên sống sót. sigmoid() và logit() có sẵn cho các mạng có kênh đầu ra là logit trước sigmoid (các bộ phát hiện MediaPipe là trường hợp điển hình).
Đối với các mô hình có đầu ra float -- regression head, các mô hình có lớp dequantize cuối cùng được tích hợp sẵn -- các hàm trợ giúp lượng tử hóa truyền qua không thay đổi, do đó cùng một mã bộ xử lý hậu kỳ hoạt động với cả hai dtype mà không cần xử lý đặc biệt.
7.15.4. Giá trị trả về¶
Bất cứ điều gì callable trả về chính là những gì predict() trả về. Đối với các bộ giải mã phát ra hộp, quy ước là đẩy các ứng viên qua NMS và trả về danh sách theo lớp của nó -- hình dạng gọi mà non-max suppression ghi lại và hướng dẫn YOLOv8 xây dựng trong ngữ cảnh. Đối với bất cứ điều gì khác, trả về bất cứ điều gì ứng dụng thấy thuận tiện: một ndarray duy nhất, một chuỗi nhãn, một tuple (class, score, embedding), một từ điển.