Ultralytics YOLO27: Tham gia danh sách chờ.
Get Started
Xây dựng Dataset YOLO Hiệu năng Cao·Gán nhãn·Bài học 4/10
Bài họcngười mới bắt đầu

Các phương pháp gán nhãn tốt nhất

Viết hướng dẫn gán nhãn, chọn công cụ, tránh mười lỗi âm thầm làm giảm độ chính xác và đo lường mức độ nhất quán giữa những người gán nhãn bằng script trước khi mở rộng quy mô.

Chất lượng nhãn giới hạn chất lượng model. Mười người gán nhãn, mỗi người hiểu "pallet" hơi khác nhau, sẽ tạo ra một dataset dạy cùng lúc cả mười cách hiểu, và dù huấn luyện bao nhiêu cũng không thể giải quyết mâu thuẫn đó. Hướng dẫn bằng văn bản, một vòng hiệu chuẩn có đo lường và danh sách ngắn các lỗi đã biết giúp nhãn nhất quán dù một người gán nhãn 500 ảnh hay cả nhóm gán nhãn 50.000 ảnh.

Kết quả

Viết hướng dẫn gán nhãn, đo lường mức độ nhất quán giữa hai người gán nhãn bằng script và chuyển mọi bất đồng thành quy tắc bằng văn bản.

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. Viết định nghĩa lớp, quy tắc vẽ và quy tắc xử lý vật thể bị che khuất trước khi bắt đầu gán nhãn.

  2. Gán nhãn mọi đối tượng liên quan trong từng ảnh, với bounding box ôm sát phần nhìn thấy được.

  3. Đo mức độ nhất quán trên một mẫu dữ liệu chung; chỉ mở rộng quy mô khi đạt ít nhất 90%.

  4. Kiểm tra thủ công mọi nhãn do model đề xuất; tuyệt đối không tự động chấp nhận.

Thực hành

Chọn công cụ gán nhãn#

Công cụ phù hợp phụ thuộc vào tác vụ, nhóm và nơi diễn ra quá trình huấn luyện:

Công cụPhù hợp nhất choGhi chú
Ultralytics PlatformCả bảy tác vụ YOLO: trình chỉnh sửa bounding box, polygon, semantic mask, keypoint, bounding box xoay và lớp ảnh, cùng với depth map đã tải lên; gán nhãn thông minh bằng SAMNhãn, biểu đồ dataset và huấn luyện tập trung tại một nơi; không cần bước xuất dữ liệu
CVATNhóm lớn, video, quy trình đánh giá phức tạpTự lưu trữ hoặc trên cloud
Label StudioDự án đa phương thức (ảnh + văn bản + âm thanh)Cấu hình linh hoạt, nhưng cần nhiều thời gian học hơn
LabelmeGán nhãn polygon cho nhóm nhỏỨng dụng desktop đơn giản
LabelImgTạo nhanh prototype chỉ dùng bounding boxGọn nhẹ; repository đã được lưu trữ

Trên Ultralytics Platform, tính năng gán nhãn thông minh SAM 2.1, SAM 3 và SAM 3.1 hoạt động với dataset detect, segment, semantic và OBB. Dù chọn công cụ nào, hãy xác nhận công cụ đó xuất được định dạng YOLO mà tác vụ của bạn cần; Chuẩn bị dataset tùy chỉnh trình bày định dạng nhãn và cách chuyển đổi.

Bảy loại nhãn#

Các tác vụ YOLO của Ultralytics được minh họa cạnh nhau: phân loại, phát hiện, phân đoạn, phân đoạn ngữ nghĩa, ước lượng tư thế, OBB và độ sâu

Loại nhãnNội dung cần vẽTác vụ
Nhãn lớpMột nhãn cho mỗi hình ảnhPhân loại
Bounding boxHình chữ nhật song song với trục cho từng đối tượngPhát hiện
PolygonĐường viền của từng đối tượngPhân đoạn đối tượng
Mask dày đặcMột class cho mỗi pixelPhân đoạn ngữ nghĩa
KeypointCác điểm được đặt tên, chẳng hạn như khớpPose
Bounding box định hướngHình chữ nhật xoay cho từng đối tượngOBB
Depth mapKhông cần vẽ: bản đồ khoảng cách theo từng pixel từ cảm biến độ sâu, đi kèm với mỗi ảnhƯớc tính độ sâu

Viết hướng dẫn gán nhãn trước#

Trước khi bất kỳ ai vẽ bounding box, hãy viết hướng dẫn gồm năm phần:

  1. Định nghĩa lớp: một đoạn cho mỗi lớp, gồm ví dụ phù hợp, các đối tượng trông tương tự nhưng không thuộc lớp đó và các trường hợp ngoại lệ.
  2. Quy tắc vẽ: bounding box ôm sát đối tượng nhìn thấy được; polygon bám theo đường viền nhìn thấy.
  3. Quy tắc về che khuất và kích thước: một ngưỡng cho đối tượng bị che khuất một phần ("gán nhãn nếu có thể nhận diện lớp") và một ngưỡng cho đối tượng rất nhỏ ("gán nhãn người cao hơn 10 pixel"), áp dụng nhất quán ở mọi nơi.
  4. Nhật ký trường hợp mơ hồ: ghi lại mọi câu hỏi kiểu "trường hợp này thì sao?" cùng câu trả lời đã thống nhất và ảnh chụp màn hình.
  5. Những gì cần bỏ qua: mọi thứ không đáng gán nhãn cho tác vụ này.

Một hoặc hai trang kèm ảnh chụp màn hình là đủ. Sau đó, hướng dẫn sẽ là cơ sở cho một vòng lặp ngắn cần thực hiện trước khi mở rộng quy mô gán nhãn:

Gán nhãn không đầy đủ âm thầm phá hỏng quá trình huấn luyện

Gán nhãn mọi đối tượng liên quan trong mọi ảnh. Xe nâng không được gán nhãn sẽ dạy model rằng đôi khi xe nâng là nền, khiến model học cách bỏ sót chúng. Dataset chỉ được gán nhãn một phần trông hệt như một dataset nhỏ hơn nhưng được gán nhãn đầy đủ cho đến khi bạn huấn luyện. Hoàn tất từng ảnh trước khi chuyển sang ảnh tiếp theo.

Mười lỗi làm giảm độ chính xác#

Những lỗi mà nhóm gán nhãn của Ultralytics thường gặp nhất, được minh họa bằng ảnh xe nâng, người và pallet (phỏng theo bộ slide của Alexis Schutzger). Hãy dùng các lỗi này làm những mục đầu tiên trong hướng dẫn của bạn.

1. Tự suy diễn hình dạng của đối tượng. Chỉ gán nhãn phần bạn nhìn thấy. Ở đây, xe nâng ở phía sau một người và một đống gỗ, nhưng bounding box lại kéo dài qua cả hai đến vị trí mà người gán nhãn tưởng tượng phần còn lại của xe tải. Chỉ đóng khung phần nhìn thấy được.

Lỗi gán nhãn: bounding box của xe nâng kéo dài qua người và đống gỗ phía trước, suy diễn phần bị che khuất thay vì chỉ đóng khung phần nhìn thấy được

2. Bounding box không chính xác. Bounding box phải ôm sát đối tượng. Bounding box này cắt qua đèn trên khung bảo vệ phía trên; bounding box cắt mất một phần đối tượng hoặc chừa một khoảng sàn đều khiến model học sai phạm vi của đối tượng.

Lỗi gán nhãn: bounding box xe nâng không chính xác, cạnh trên cắt qua đèn trên khung bảo vệ phía trên thay vì bao trọn đối tượng

3. Quy ước không nhất quán giữa các đối tượng tương tự. Bounding box bên trái bao gồm càng nâng; bounding box bên phải lại không. Model nhận được hai câu trả lời cho cùng một câu hỏi, vì vậy hãy ghi rõ quy ước: có bao gồm càng nâng hay không.

Lỗi gán nhãn: hai xe nâng tương tự được đóng khung theo các quy ước khác nhau, một bounding box bao gồm càng nâng còn bounding box kia thì không

4. Thiếu nhãn. Có hai người đứng cạnh xe nâng, nhưng chỉ một người được đóng khung. Người không có nhãn trở thành ví dụ dạy model rằng "người là nền".

Lỗi gán nhãn: xe nâng và một người nông dân được đóng khung, nhưng người nông dân thứ hai không được gán nhãn

5. Sai class. Kiểm tra class, không chỉ kiểm tra bbox. Một bbox chính xác quanh xe nâng nhưng được gán nhãn person sẽ làm sai cả hai class, thường do nhấn nhầm phím tắt.

Lỗi gán nhãn: bbox được vẽ chính xác quanh xe nâng nhưng lại được gán sai class, người

6. Annotation rỗng hoặc thừa. Mỗi annotation cần có một object thực và một class thực. Một cú nhấp chuột lạc tạo ra bbox gần như rỗng như ở góc ảnh này; bbox được lưu mà không có class có thể được export thành None hoặc class 0. Hãy sửa hoặc xóa chúng.

Lỗi gán nhãn: một annotation xe nâng lạc, gần như rỗng ở góc ảnh bên cạnh bbox xe nâng thực

7. Bbox trùng lặp. Một object, một bbox. Hai bbox chồng lên nhau trên cùng một xe nâng làm tăng số lượng instance và khiến model học cách dự đoán các bản trùng lặp.

Lỗi gán nhãn: hai bbox trùng lặp chồng lên nhau trên một xe nâng

8. Hướng dẫn không rõ ràng. Không có quy tắc bằng văn bản, người gán nhãn sẽ tự ứng biến: ở đây, một người chỉ khoanh đầu tài xế và gán class forklift. Tài xế thuộc xe nâng hay là một person riêng biệt? Hãy trả lời câu hỏi đó một lần trong tài liệu hướng dẫn.

Lỗi gán nhãn: do không có hướng dẫn rõ ràng, người gán nhãn chỉ khoanh đầu người vận hành và gán nhãn là xe nâng

9. Ảnh ngoại lệ. Loại bỏ những ảnh không phù hợp với môi trường triển khai. Một bức ảnh đường chân trời thành phố trong dataset xe nâng không mang lại thông tin hữu ích và làm loãng giá trị của mọi dữ liệu khác.

Lỗi gán nhãn: ảnh tòa nhà chọc trời bị trộn vào dataset xe nâng như một ảnh ngoại lệ

10. Mơ hồ do augmentation. Khi crop có thể loại bỏ đặc điểm định nghĩa một class, hai class sẽ trở nên giống hệt nhau. Cắt mất biểu tượng ở góc của lá ace cơ và lá bài đó trông giống các lá được gắn nhãn unknown. Sử dụng Augmentation Cẩn thận trình bày cách khắc phục.

Lỗi gán nhãn: các lá bài trong đó lá ace cơ bị cắt mất biểu tượng ở góc trông giống những lá được gắn nhãn không xác định

Đo mức độ nhất quán, đừng phỏng đoán#

Một vòng hiệu chuẩn cung cấp cho hai người gán nhãn cùng một bộ ảnh rồi so sánh nhãn của họ theo từng object. Hai nhãn được xem là nhất quán khi có cùng class và độ chồng lấp đạt ít nhất 0.5 theo IoU. Script này tính điểm trên các ảnh val của COCO8. Để có thể chạy mà không cần người thứ hai, một model đã huấn luyện trước đóng vai người gán nhãn B; với một nhóm thực tế, hãy đọc bbox của B từ các file nhãn của họ:

from pathlib import Path

import torch

from ultralytics import YOLO
from ultralytics.data.utils import check_det_dataset, img2label_paths
from ultralytics.utils.metrics import box_iou
from ultralytics.utils.ops import xywh2xyxy

data = check_det_dataset("coco8.yaml")
model = YOLO("yolo26n.pt")  # stands in for a second annotator; compare two label folders the same way
names = data["names"]

matched = total = 0
for image in sorted(Path(data["val"]).glob("*.jpg")):
    rows = [r.split() for r in Path(img2label_paths([str(image)])[0]).read_text().splitlines() if r.strip()]
    a_cls = torch.tensor([int(r[0]) for r in rows])  # annotator A: the dataset labels
    a_box = xywh2xyxy(torch.tensor([[float(v) for v in r[1:]] for r in rows]))
    b = model(image, conf=0.5, verbose=False)[0].boxes  # annotator B: confident model proposals
    iou = box_iou(a_box, b.xyxyn)
    used = set()
    for i in range(len(rows)):  # pair each A object with the best unused same-class B box at IoU >= 0.5
        ok = [j for j in range(len(b)) if j not in used and b.cls[j] == a_cls[i] and iou[i, j] >= 0.5]
        if ok:
            used.add(max(ok, key=lambda j: iou[i, j]))
        else:
            print(f"{image.name}: {names[int(a_cls[i])]} labeled by A only")
    for j in set(range(len(b))) - used:
        print(f"{image.name}: {names[int(b.cls[j])]} labeled by B only")
    matched += len(used)
    total += len(rows) + len(b) - len(used)

print(f"agreement: {matched}/{total} objects = {matched / total:.0%}")
000000000049.jpg: person labeled by A only
000000000049.jpg: person labeled by A only
000000000049.jpg: potted plant labeled by A only
000000000049.jpg: person labeled by A only
000000000049.jpg: person labeled by A only
000000000049.jpg: person labeled by A only
000000000061.jpg: person labeled by A only
000000000061.jpg: elephant labeled by A only
000000000061.jpg: person labeled by A only
agreement: 8/17 objects = 47%

Cách đọc kết quả:

  • Điểm số là số object được ghép khớp chia cho tổng số object mà cả hai người gán nhãn đã vẽ: 8 trên 17.
  • Các điểm bất đồng tập trung thành cụm. Cả chín trường hợp đều nằm trong hai ảnh, và phần lớn là người chiếm ít hơn nhiều so với 1% khung hình. Đây không phải chín lỗi ngẫu nhiên; chúng xuất phát từ một quy tắc còn thiếu: có gán nhãn người ở xa không?
  • Cách khắc phục là bổ sung một mục vào hướng dẫn, chẳng hạn: "gán nhãn mọi người cao ít nhất 10 pixel ở độ phân giải 640 pixel". Cả hai người gán nhãn gán nhãn lại hai ảnh đó rồi đo lại điểm số.

Quy tắc ra quyết định: chỉ mở rộng quy mô gán nhãn khi mức độ nhất quán đạt 90%. Nếu thấp hơn, mỗi người gán nhãn mới sẽ làm mức độ không nhất quán tăng lên.

Dùng gán nhãn thông minh để tăng tốc#

Gán nhãn thông minh cho phép model YOLO hoặc SAM đề xuất nhãn để một người chấp nhận hoặc chỉnh sửa, nhờ đó năng suất có thể tăng gấp nhiều lần. Khởi động theo từng vòng: huấn luyện trên một batch đã được rà soát, dùng model đó đề xuất batch tiếp theo, rà soát rồi huấn luyện lại. Đây là vòng lặp học chủ động, và Gán nhãn Thông minh và Gán nhãn theo Batch hướng dẫn quy trình này trên Ultralytics Platform.

Tự động chấp nhận các đề xuất khiến lỗi của model bị tích hợp vào dữ liệu

Model bỏ sót người nhỏ sẽ không đề xuất hộp cho người nhỏ, và người đánh giá nhấp "chấp nhận tất cả" sẽ không bao giờ bổ sung họ. Model tiếp theo, được huấn luyện trên những nhãn đó, sẽ bỏ sót họ với độ tin cậy cao hơn. Hãy xem xét mọi ảnh, đồng thời bổ sung những gì model bỏ sót và sửa những gì model đã vẽ.

Kiểm tra bằng mắt#

Mỗi lần chạy huấn luyện Ultralytics ghi labels.jpg và train_batch*.jpg vào thư mục run. File đầu tiên vẽ biểu đồ số lượng class, vị trí và kích thước bbox; các file còn lại hiển thị ảnh huấn luyện thực tế cùng nhãn được vẽ chồng lên. Hãy mở chúng trước khi epoch đầu tiên kết thúc. Mắt người phát hiện được những gì metric không bao giờ thấy: bbox vẽ quanh bóng, ID class bị hoán đổi và polygon chưa khép kín.

Dùng thử

Viết hướng dẫn gán nhãn một trang cho các class của bạn, gồm năm phần ở trên và lấy mười lỗi làm ví dụ. Cung cấp cùng 20–50 ảnh cho hai người, yêu cầu họ gán nhãn độc lập, rồi điều chỉnh agreement.py để so sánh hai thư mục nhãn. Sản phẩm bàn giao: tài liệu hướng dẫn, điểm số mức độ nhất quán và một quy tắc mới cho mỗi cụm bất đồ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.
  • Tài liệu hướng dẫn định nghĩa mọi class và nêu rõ các quy tắc vẽ bbox, che khuất và kích thước.

  • Hai người gán nhãn cùng một bộ ảnh và đo mức độ nhất quán bằng script, không ước lượng.

  • Mỗi cụm bất đồng đã được chuyển thành một quy tắc bằng văn bản, và sau khi gán nhãn lại, mức độ nhất quán đạt ít nhất 90%.

Hiển thị lời giải

Các điểm bất đồng trên COCO8 được chuyển thành những mục trong tài liệu hướng dẫn như sau:

Điểm bất đồngQuy tắc bổ sung vào hướng dẫn
Người ở xa trong 000000000049.jpg chỉ được A gán nhãnGán nhãn mọi người cao ít nhất 10 pixel ở độ phân giải 640 pixel; bỏ qua người thấp hơn trong mọi ảnh.
Chậu cây ở mép khung hình chỉ được A gán nhãnGán nhãn object bị mép khung hình cắt nếu nhìn thấy ít nhất một nửa object.
Voi bị một con voi khác che khuất một phần trong 000000000061.jpgGán nhãn động vật bị che khuất nếu nhìn thấy đầu hoặc một nửa thân; chỉ vẽ bbox quanh phần nhìn thấy.

Để so sánh hai người thay vì một người với một model, hãy đọc các dòng của người gán nhãn B từ thư mục nhãn thứ hai, đúng như cách script đọc dữ liệu của A (Path("labels_b", image.stem + ".txt")), tạo b_cls và b_box từ dữ liệu đó bằng cùng hai dòng lệnh, rồi dùng chúng ở mọi nơi script đọc b.cls và b.xyxyn. Chạy lại sau khi gán nhãn lại; vòng này hoàn tất khi điểm số vượt 90%.

Tiếp theo là gì

Khi đã có nhãn, bài học tiếp theo sẽ chạy quy trình kiểm soát chất lượng để tìm những gì tài liệu hướng dẫn còn bỏ sót trước khi chúng làm lãng phí một lần huấn luyện.

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