Ultralytics YOLO27: ウェイトリストに登録する。
Get Started
高性能YOLOデータセットの構築·ラベリング·レッスン 4/10
レッスン初級

アノテーションのベストプラクティス

ラベリングガイドを作成し、ツールを選び、精度をひそかに損なう10のミスを避け、スケールアップの前にスクリプトでアノテーター間の一致度を測定します。

ラベルの品質がモデルの品質の上限を決めます。10人のアノテーターがそれぞれ「パレット」の解釈を少しずつ変えると、データセットは10通りの解釈を同時に学習させることになり、どれだけ学習しても矛盾は解消されません。文書化されたガイド、測定可能なキャリブレーションラウンド、よくあるミスの簡潔なリストがあれば、1人で500枚にラベルを付ける場合も、チームで50,000枚に付ける場合も、一貫性を保てます。

成果

ラベリングガイドを作成し、スクリプトで2人のアノテーター間の一致度を測定して、すべての不一致を文書化したルールに反映します。

短期集中コース
すでに使い方をご存じの方は、こちらをご覧ください。
  1. ラベリングを始める前に、クラスの定義、描画ルール、オクルージョンのルールを作成します。

  2. すべての画像で関連するオブジェクトに漏れなくラベルを付け、見えている範囲を囲むタイトなボックスを付けます。

  3. 共通サンプルで一致度を測定し、90%以上になってから規模を拡大します。

  4. モデルが提案したラベルはすべて人手で確認し、自動承認はしません。

実践的

アノテーションツールを選ぶ#

適切なツールは、タスク、チーム、トレーニングを行う場所によって異なります。

ツール最適な用途説明
Ultralytics Platform7種類すべてのYOLOタスクに対応します。ボックス、ポリゴン、セマンティックマスク、キーポイント、回転ボックス、画像クラスを編集でき、深度マップのアップロードにも対応しています。SAMによるスマートアノテーションも利用できますラベル、データセットのグラフ、トレーニングを1か所で管理でき、エクスポートの手順が不要です
CVAT大規模チーム、動画、複雑なレビューのワークフローセルフホストまたはクラウド
Label Studioマルチモーダルプロジェクト(画像 + テキスト + 音声)柔軟に設定できますが、習得には時間がかかります
Labelme小規模チームでのポリゴンラベリングシンプルなデスクトップアプリ
LabelImgボックスのみの迅速なプロトタイプ作成軽量ですが、リポジトリはアーカイブされています

Ultralytics Platformでは、SAM 2.1、SAM 3、SAM 3.1によるスマートアノテーションを、detect、segment、semantic、OBBのデータセットで利用できます。どのツールを選ぶ場合も、タスクに必要なYOLO形式でエクスポートできることを確認してください。カスタムデータセットの準備では、ラベル形式と変換方法を説明しています。

7種類のラベル#

Ultralytics YOLOの7つのタスクを並べて表示:classify、detect、segment、semantic segmentation、pose、OBB、depth

ラベルの種類描画するものタスク
クラスラベル画像ごとに1つのラベル分類
バウンディングボックスオブジェクトごとの軸に平行な長方形検出
ポリゴン各オブジェクトインスタンスの輪郭インスタンスセグメンテーション
高密度マスクすべてのピクセルにクラスを割り当てますセマンティックセグメンテーション
キーポイント関節などの名前付きポイント姿勢
方向付きボックスオブジェクトごとの回転した長方形OBB
深度マップ描画するものはありません。深度センサーによるピクセルごとの距離マップで、各画像に対応付けられます深度推定

まずラベリングガイドを作成する#

誰かがボックスを描き始める前に、次の5つのセクションを含むガイドを作成します。

  1. クラスの定義:各クラスについて、該当する例、そのクラスに該当しない類似物、境界事例を含めて1段落で説明します。
  2. 描画ルール:見えているオブジェクトを囲むタイトなボックスを描き、ポリゴンは見えている輪郭に沿わせます。
  3. オクルージョンとサイズのルール:部分的に隠れたオブジェクトに対する基準(「クラスを識別できるならラベルを付ける」)と、小さなオブジェクトに対する基準(「高さ10ピクセルを超える人物にラベルを付ける」)をそれぞれ1つ定め、すべての画像に適用します。
  4. 曖昧なケースの記録:「これはどうする?」という質問ごとに、合意した回答とスクリーンショットを記録します。
  5. 除外するもの:このタスクでラベルを付ける価値がないものをすべて記載します。

スクリーンショット付きで1~2ページあれば十分です。このガイドを基に、ラベリングを大規模に始める前に短いループを実施します。

一部だけラベル付けすると、気付かないうちに学習が損なわれる

すべての画像で、関連する物体すべてにラベルを付けます。ラベルのないフォークリフトは、フォークリフトが背景になる場合もあるとモデルに学習させるため、検出漏れにつながります。一部しかラベル付けされていないデータセットは、学習するまで、完全にラベル付けされた小規模データセットと見分けがつきません。次の画像に進む前に、各画像の作業を完了します。

精度を損なう10のミス#

Ultralyticsのアノテーションチームがよく目にするエラーを、フォークリフト、人物、パレットの画像を使って説明します(Alexis Schutzgerの資料を基に編集)。これらをガイドの最初の項目として活用してください。

1. オブジェクトの形状を推測して補う。見えている部分だけをアノテーションします。この例では、フォークリフトは人物と木材の山の後ろにありますが、アノテーターがトラックの残りの部分を想像し、ボックスをその両方にまたがるように引いています。見えている部分だけを囲みます。

アノテーションのミス:フォークリフトの隠れた部分を推測して囲み、見えている部分だけを囲まず、手前の人物と木材の山にまたがるようにボックスを引いている

2. ボックスの精度が低い。ボックスはオブジェクトに沿わせる必要があります。この例では、上部ガードのライトを横切っています。オブジェクトの一部を切り取るボックスや、床との間に余白を残すボックスは、誤った範囲を学習させます。

アノテーションのミス:オブジェクト全体を囲まず、上端が上部ガードのライトを横切っている不正確なフォークリフトのボックス

3. 類似したオブジェクトに一貫性のないルールを適用する。左側のボックスにはフォークが含まれていますが、右側のボックスには含まれていません。同じ質問に対してモデルが異なる答えを学習するため、フォークを含めるのか、含めないのか、ルールを文書化します。

アノテーションのミス:類似した2台のフォークリフトに異なるルールでボックスが付けられ、一方はフォークを含み、もう一方は含んでいない

4. アノテーションの漏れ。フォークリフトの横に人物が2人立っていますが、ボックスが付いているのは1人だけです。ラベルのない人物は、「人物は背景である」という学習例になります。

アノテーションのミス:フォークリフトと1人目の農家にはボックスが付いているが、2人目の農家にはラベルが付いていない

5. クラスの誤り。 ボックスだけでなく、クラスも確認してください。フォークリフトを正しく囲んだボックスに person のタグが付いていると、両方のクラスが誤ってしまいます。これはたいてい、キーボードショートカットの誤操作です。

アノテーションの誤り: 正しく描画されたボックス内のフォークリフトに、誤ったクラスpersonが割り当てられている

6. 空のアノテーション、または余分なアノテーション。 すべてのアノテーションには、実在するオブジェクトと正しいクラスが必要です。余計なクリックをすると、ここの隅にあるような、ほぼ空のボックスが残ります。また、クラスなしで保存されたボックスは、None またはクラス0としてエクスポートされることがあります。修正するか、削除してください。

アノテーションの誤り: 実際のフォークリフトのボックスの横、画像の隅に残された、余計なほぼ空のフォークリフトのアノテーション

7. ボックスの重複。 1つのオブジェクトにボックスは1つです。同じフォークリフトに重なったボックスが2つあると、インスタンス数が水増しされ、モデルが重複を予測するように学習されます。

アノテーションの誤り: 1台のフォークリフトに重なって描かれた、重複する2つのボックス

8. ガイドラインが不明確。 文書化されたルールがないと、アノテーターは独自に判断します。ここでは、あるアノテーターが運転手の頭だけを囲み、forklift クラスを付けています。運転手はフォークリフトの一部ですか、それとも別の person ですか?ガイドに一度明記して、答えを定めてください。

アノテーションの誤り: 明確なガイドラインがないため、アノテーターがオペレーターの頭だけを囲み、フォークリフトとしてラベル付けしている

9. 外れ値画像。 デプロイ環境に合わない画像は除外してください。フォークリフトのデータセットに都市のスカイラインの写真を入れても役に立つ学習にはならず、ほかのすべての画像の価値を薄めてしまいます。

アノテーションの誤り: フォークリフトのデータセットに外れ値画像として混在した、高層ビルの写真

10. データ拡張による曖昧さ。 クロップによってクラスを定義する特徴が失われると、2つのクラスが同じに見えてしまいます。ハートのエースの隅のマークを切り取ると、unknown とラベル付けされたカードに見えます。修正方法については、データ拡張は慎重にをご覧ください。

アノテーションの誤り: 隅のマークがクロップされたハートのエースが、unknownとラベル付けされたカードに見えるトランプ

推測せずに一致度を測定する#

キャリブレーションでは、2人のアノテーターに同じ画像を渡し、オブジェクトごとにラベルを比較します。クラスが同じで、IoUが0.5以上なら、2つのラベルは一致しています。このスクリプトは、COCO8のval画像でスコアを計算します。2人目がいなくても実行できるよう、事前学習済みモデルをアノテーターBとして使います。実際のチームで実施する場合は、Bのボックスをその人のラベルファイルから読み込んでください。

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%

結果の読み方:

  • スコアは、一致したオブジェクト数を、どちらかのアノテーターが描いたすべてのオブジェクト数で割った値です。この例では17個中8個です。
  • 不一致は集中しています。 9件すべてが2枚の画像にあり、その大半はフレームの1%にも満たない大きさの人物です。これは無関係な誤りが9件あるのではなく、ルールが1つ不足しているということです。遠くにいる人物にもラベルを付けるのか?
  • 解決策はガイドへの記載です。 たとえば、「640ピクセルの画像で高さが10ピクセル以上の人物すべてにラベルを付ける」と記載します。2人のアノテーターがその2枚の画像を再ラベル付けし、スコアを再測定します。

判断基準は、一致度が90%に達した場合にのみ、ラベリングを拡大することです。 それを下回る状態では、アノテーターを増やすたびに不一致が増えていきます。

スマートアノテーションで作業を加速する#

スマートアノテーションでは、YOLOモデルやSAMがラベル候補を提案し、人が承認または修正することで、作業量を数倍に増やせます。段階的に開始します。レビュー済みのバッチで学習し、そのモデルで次のバッチのラベルを提案して、レビュー後に再学習します。これがアクティブラーニングのループです。スマートアノテーションとバッチラベリングでは、Ultralytics Platformでの手順を説明しています。

提案を自動承認すると、モデルの誤りがデータに定着する

小さな人物を見落とすモデルは、小さな人物のボックスを提案しません。レビュアーが「すべて承認」をクリックしても、そうした人物は追加されません。そのラベルで学習した次のモデルは、さらに自信を持って見落とすようになります。すべての画像をレビューし、モデルが描画したものを修正するだけでなく、モデルが見落としたものも追加します。

目視で確認する#

Ultralyticsのトレーニング実行では、毎回 labels.jpg と train_batch*.jpg が実行フォルダーに書き込まれます。前者はクラス数とボックスの位置・サイズをプロットし、後者はラベルを重ねた実際のトレーニング画像を表示します。最初のエポックが終わる前に開いて確認してください。メトリクスでは決して分からないことも、目視なら見つけられます。影を囲んだボックス、入れ替わったクラスID、閉じていないポリゴンなどです。

試してみる

上記の5つのセクションを含む、クラスごとの1ページのラベリングガイドを作成し、10個の誤りを参考例として加えてください。同じ20~50枚の画像を2人に渡し、それぞれ独立してラベル付けしてもらいます。agreement.py を調整して、2つのラベルフォルダーを比較してください。成果物は、ガイド、一致度スコア、不一致のまとまりごとに追加した新しいルールです。

完了条件
以下のすべてを満たすと、レッスンは完了です。
  • ガイドではすべてのクラスを定義し、描画、オクルージョン、サイズのルールを明記しています。

  • 2人のアノテーターが同じ画像にラベルを付け、推定ではなくスクリプトで一致度を測定しています。

  • 不一致のまとまりごとにルールが文書化され、再ラベル付け後の一致度が90%以上になっています。

解答を表示

COCO8での不一致は、次のようなガイドの記載に結び付きます。

不一致ガイドに追加したルール
000000000049.jpg 内の遠くにいる人物にAだけがラベル付け640ピクセルの画像で高さが10ピクセル以上の人物すべてにラベルを付け、それより小さい人物はすべての画像で対象外にします。
画像の端にある鉢植えにAだけがラベル付け画像の端で切れているオブジェクトでも、半分以上が見えていればラベルを付けます。
000000000061.jpg 内で別のゾウに一部隠れているゾウ頭部または胴体の半分が見えている場合は、オクルージョンされた動物にもラベルを付けます。見えている部分だけを囲みます。

人とモデルではなく2人のアノテーターを比較するには、スクリプトがAの行を読み取るのと同じ方法で、2つ目のラベルフォルダーからアノテーターBの行を読み込んでください(Path("labels_b", image.stem + ".txt"))。同じ2行を使って b_cls と b_box を作成し、スクリプトが b.cls と b.xyxyn を読み取る箇所でそれらを使用します。再ラベル付け後に再実行し、スコアが90%を超えたらそのラウンドは完了です。

次のステップ

ラベルが揃ったら、次のレッスンでは品質管理を実施し、トレーニング実行に影響が出る前にガイドで見落とした点を見つけます。