Ultralytics YOLO27: Tham gia danh sách chờ.
Get Started
Ultralytics YOLO trong môi trường production·Hiệu chuẩn và quan sát·Bài học 8/9
Bài họctrung cấp

Khả năng quan sát và drift

Ghi nhật ký các metric phát hiện tình trạng giảm độ chính xác âm thầm, kiểm tra phân phối confidence để phát hiện drift và chỉ cảnh báo về các tín hiệu có thể hành động.

Một dịch vụ thị giác máy tính có thể đang hoạt động, nhanh nhưng cho kết quả sai. Camera bị xê dịch, ánh sáng thay đổi, một dòng sản phẩm mới xuất hiện, nhưng model vẫn trả về các hộp bao quanh trong khi mọi dashboard hạ tầng đều báo trạng thái tốt. Trong bài học này, việc làm tối clip để mô phỏng chạng vạng chỉ khiến confidence trung bình thay đổi 0.01, khó nhận ra trên biểu đồ, nhưng kiểm định KS hai mẫu đã phát hiện thay đổi ở p = 0.007. Bạn sẽ xây dựng phép kiểm tra đó và hệ thống ghi nhật ký cung cấp dữ liệu cho phép kiểm tra.

Kết quả

Xuất metric JSON cho từng frame, chạy kiểm định drift KS so với baseline lúc triển khai, xác thực trên tập dữ liệu giữ lại và xác định các cảnh báo gắn với hành động cụ thể.

Lộ trình cấp tốc
Nếu bạn đã nắm rõ cách thực hiện, đây là phiên bản tóm tắt.
  1. Mỗi frame: camera, r.speed["inference"], số lượng detection, confidence trung bình, các giá trị confidence thô.

  2. Lưu confidence tại thời điểm triển khai làm baseline; mỗi ngày so sánh với scipy.stats.ks_2samp.

  3. Hằng tuần, xác thực một tập dữ liệu giữ lại đã gán nhãn bằng yolo val; cảnh báo nếu mAP giảm hơn 1 điểm.

  4. Chỉ cảnh báo về tín hiệu có hành động tiếp theo được ghi rõ; mọi thứ khác chỉ nên là một panel trên dashboard.

Thực hành

Ba lớp tín hiệu#

LớpCâu hỏiTín hiệu
Hạ tầngDịch vụ có hoạt động và xử lý kịp không?Độ trễ, thông lượng, frame bị mất, mức sử dụng CPU và GPU
Hành vi của modelModel có hoạt động như tuần trước không?Số detection mỗi frame, confidence trung bình, cơ cấu class, kích thước hộp
Độ chính xác của modelModel vẫn đưa ra kết quả đúng chứ?mAP trên tập giữ lại (metric hiệu năng), đánh giá thủ công trên mẫu, tỷ lệ cảnh báo giả

Hầu hết nhóm bao phủ lớp đầu tiên bằng các công cụ tiêu chuẩn rồi dừng lại. Lớp thứ hai và thứ ba là nơi các hệ thống thị giác máy tính gặp lỗi âm thầm; hướng dẫn giám sát model trình bày toàn bộ quy trình bảo trì.

Trang triển khai Ultralytics Platform tại tab Logs, với các bộ lọc Errors và All phía trên những dòng yêu cầu INFO có dấu thời gian phục vụ giám sát và gọi mẫu

Nếu triển khai qua Ultralytics Platform, trang triển khai cung cấp lớp hạ tầng (request, tỷ lệ lỗi, độ trễ P95) và nhật ký request có thể lọc theo lỗi như minh họa ở trên; bài học Giám sát tình trạng và độ chính xác trình bày các nội dung này. Bạn cần tự xây dựng lớp hành vi và độ chính xác; phần còn lại của bài học này sẽ hướng dẫn cách thực hiện.

Xuất metric cho từng frame#

Mỗi đối tượng Results đều chứa thông tin thời gian và hộp. Ghi một dòng JSON cho mỗi frame rồi gửi đến hệ thống metric bạn đang dùng:

import json
import time

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
with open("metrics.jsonl", "w") as log:
    for r in model.predict(video, stream=True, verbose=False):
        conf = r.boxes.conf
        record = {
            "ts": time.time(),
            "camera": "lobby-1",
            "inference_ms": round(r.speed["inference"], 1),
            "detections": len(r.boxes),
            "mean_conf": round(conf.mean().item(), 3) if len(conf) else None,
            "confs": [round(c, 3) for c in conf.tolist()],  # các giá trị thô dùng cho kiểm định drift
        }
        log.write(json.dumps(record) + "\n")
print({k: v for k, v in record.items() if k != "confs"})
{'ts': 1792003254.33, 'camera': 'lobby-1', 'inference_ms': 34.7, 'detections': 22, 'mean_conf': 0.543}

Công dụng của từng trường:

  • inference_ms: cảnh báo khi p95 vượt quá ngân sách.
  • detections: số lượng giảm đột ngột xuống gần bằng không thường có nghĩa camera bị chặn hoặc hỏng; tăng vọt nghĩa là cảnh đã thay đổi hoặc xuất hiện nhiều false positive.
  • mean_conf: đường xu hướng nhanh, nhưng quá thô để tự phát hiện drift.
  • confs: toàn bộ phân phối, cần thiết cho phép kiểm tra drift bên dưới.

Kiểm tra drift trong phân phối độ tin cậy#

Data drift thể hiện trong độ tin cậy từ lâu trước khi có người gán nhãn dữ liệu mới. Thu thập độ tin cậy lúc khởi chạy làm đường cơ sở, thu thập một cửa sổ dữ liệu gần đây, rồi so sánh hai phân phối bằng kiểm định Kolmogorov-Smirnov hai mẫu (pip install scipy). Script này mô phỏng thời điểm chạng vạng bằng cách làm tối cùng một đoạn video:

import cv2
import numpy as np
from scipy.stats import ks_2samp

from ultralytics import YOLO
from ultralytics.utils.downloads import safe_download

model = YOLO("yolo26n.pt")
video = str(safe_download("https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"))

def confidences(darken=1.0):
    """Collect every detection confidence from the clip, optionally darkened to simulate dusk."""
    cap, out = cv2.VideoCapture(video), []
    while True:
        ok, frame = cap.read()
        if not ok:
            break
        out += model((frame * darken).astype(np.uint8), verbose=False)[0].boxes.conf.tolist()
    return np.array(out)

baseline = confidences()  # what "normal" looked like at launch
for name, recent in (("same scene", confidences()), ("dusk (35% brightness)", confidences(darken=0.35))):
    stat, p = ks_2samp(baseline, recent)
    print(f"{name:22s} n={len(recent):4d} mean_conf={recent.mean():.3f} KS={stat:.3f} p={p:.2g}")
same scene             n=1376 mean_conf=0.519 KS=0.000 p=1
dusk (35% brightness)  n=1337 mean_conf=0.508 KS=0.064 p=0.0068

Đọc lần lượt từng dòng:

  • Cùng cảnh: các phân phối giống hệt nhau cho thống kê KS bằng 0 và p = 1, đây là trường hợp đối chứng.
  • Chạng vạng: số detections giảm 39 và giá trị trung bình chỉ thấp hơn 0.011, mức chênh lệch không ai nhận ra trên biểu đồ. Thống kê KS (khoảng cách lớn nhất giữa hai phân phối tích lũy) là 0.064, và p = 0.0068 < 0.01 cho thấy độ lệch là có thật.

Cảnh báo drift là lý do để xem các frame mẫu, không phải bằng chứng cho thấy hệ thống bị lỗi. Khi drift là có thật, hãy thu thập và gán nhãn frame từ các camera bị ảnh hưởng: hướng dẫn thu thập và chú thích dữ liệu trình bày những gì cần thu thập, còn hướng dẫn fine-tune trình bày quy trình huấn luyện lại. Kích thước bounding box (width × height) là một tín hiệu drift dễ theo dõi khác: các giá treo và ống kính mới thường thể hiện thay đổi ở đó trước tiên.

Xác thực tập holdout hằng tuần#

Các tín hiệu hành vi cho biết có điều gì đó đã thay đổi; chỉ nhãn mới cho biết độ chính xác có giảm hay không. Duy trì một tập holdout gồm 200–500 ảnh production đã gán nhãn và xác thực mọi phiên bản model, cũng như hằng tuần:

yolo val model=yolo26n.pt data=coco8.yaml > weekly_metrics.txt  # use your production model and holdout YAML

Ghi lại mAP50-95 và AP theo từng lớp theo thời gian, đồng thời cảnh báo khi mAP giảm hơn 1 điểm so với tuần trước. Nguyên nhân phổ biến nhất là thay model trong khi dự kiến không làm thay đổi kết quả; nguyên nhân thứ hai là drift. Confusion matrix trên cùng tập holdout giúp dễ nhận ra các hồi quy theo từng lớp.

Chất lượng model theo thời gian: chất lượng được duy trì khi dữ liệu mới được gán nhãn, sau đó suy giảm sau thời điểm dự kiến bắt đầu suy giảm, đặt ra câu hỏi nên huấn luyện lại ngay hay chờ thêm

Tập holdout giúp trả lời câu hỏi trong biểu đồ này. Hãy huấn luyện lại khi tập cho thấy chất lượng bắt đầu giảm, hoặc khi bạn có đủ dữ liệu mới được gán nhãn từ các điều kiện đã drift, thay vì theo một lịch cố định.

Cảnh báo dựa trên hành động, không phải con số#

Tín hiệuKích hoạt khiHành động
p95 inference_msVượt ngân sách trong hơn 3 phútMở rộng quy mô hoặc chuyển sang bản export đã tối ưu
Detections trên mỗi frameGiảm từ 50% trở lên trong 5 phútKiểm tra luồng camera, sau đó kiểm tra phiên bản model
Frame bị rớtVượt 5% trong 10 phútBổ sung capacity hoặc giảm FPS trên mỗi luồng
Kiểm định KS độ tin cậyp < 0.01 trên các cửa sổ dữ liệu hằng ngàyXem lại frame, sau đó chạy kiểm tra holdout
mAP50-95 trên tập holdoutGiảm từ 1 điểm trở lên so với tuần trướcThu thập dữ liệu, gán nhãn và fine-tune

Các lỗi thường gặp#

So sánh các khoảng thời gian không tương đồng

Triệu chứng: kiểm định KS kích hoạt vào mỗi buổi tối và thứ Hai hàng tuần. Cách khắc phục: chu kỳ theo ngày và tuần là những thay đổi phân phối thực sự. Hãy so sánh dữ liệu tương đồng (cùng camera, cùng giờ, cùng thứ trong tuần) và dùng các cửa sổ gồm hàng nghìn detection.

Tập holdout đã lỗi thời

Triệu chứng: mAP trên holdout có vẻ ổn nhưng người dùng báo bỏ sót đối tượng. Cách khắc phục: holdout phải phản ánh production hiện tại. Cập nhật mỗi quý bằng các frame mới được gán nhãn từ những camera quan trọng.

Nếu không ai hành động dựa trên cảnh báo, đừng gửi cảnh báo đó

Mỗi cảnh báo cần có hành động tiếp theo được ghi rõ. Tín hiệu bạn chỉ muốn theo dõi nên nằm trên dashboard, không phải trong hệ thống gửi cảnh báo đến người trực.

Dùng thử

Thêm phần ghi log JSON vào pipeline và chạy trong một giờ (hoặc trên một video dài). Giữ cửa sổ đầu tiên làm baseline.jsonl, sau đó chạy kiểm tra KS của giải pháp trên cửa sổ thứ hai: một thời điểm khác trong ngày, một camera khác hoặc một bản sao đã làm tối. Cung cấp thống kê KS và p-value, cùng bảng cảnh báo có hành động tương ứng cho từng hàng.

Điều kiện hoàn thành
Bạn đã hoàn thành bài học khi tất cả các điều kiện sau đều đúng.
  • Pipeline của bạn ghi một dòng JSON cho mỗi frame, gồm độ trễ, số lượng detection, độ tin cậy trung bình và độ tin cậy thô.

  • Bạn đã chạy kiểm định KS giữa đường cơ sở và một cửa sổ dữ liệu gần đây, đồng thời ghi lại thống kê và p-value.

  • Mỗi cảnh báo bạn xác định đều có ngưỡng, thời lượng và hành động tiếp theo được ghi rõ.

Hiển thị lời giải

Giữ cửa sổ đầu tiên có trạng thái ổn định từ đầu ra monitor.py làm baseline.jsonl, sau đó so sánh từng cửa sổ mới với cửa sổ đó:

import json

import numpy as np
from scipy.stats import ks_2samp

def load(path):
    """Flatten the per-frame 'confs' lists written by monitor.py."""
    with open(path) as f:
        return np.array([c for line in f for c in json.loads(line)["confs"]])

baseline, recent = load("baseline.jsonl"), load("metrics.jsonl")
stat, p = ks_2samp(baseline, recent)
print(f"KS={stat:.3f} p={p:.2g} -> {'review frames' if p < 0.01 else 'ok'}")
KS=0.000 p=1 -> ok

Đây là kết quả dự kiến khi cả hai tệp đều được tạo từ cùng một đoạn video. Chạy quy trình này hằng ngày bằng bộ lập lịch, gửi thống kê và p-value đến cùng hệ thống metrics dùng cho log theo từng frame, và chuyển review frames đến một người phụ trách thay vì hệ thống gọi báo động.

Tiếp theo là gì

Bài học cuối: khi dashboard cho biết độ trễ hoặc chi phí vượt ngân sách, cần điều chỉnh yếu tố nào trước tiên.

Đăng nhập để lưu tiến độ