現実を反映するデータセット
追加のラベル付けを行う前に、実データセットのカバレッジ不足を監査し、その不足をハードネガティブを含むデータ収集計画に落とし込みます。
期待外れのビジョンモデルの多くは、モデル自体が悪いのではありません。導入先の環境を反映しないデータセットで学習した、優れたモデルです。前のレッスンでは、COCOの船が側面から撮影されているため、COCOの検出モデルはドローンから船をまったく検出できませんでした。5分間の監査で、ラベル付けに費用をかける前に、こうした不足を見つけられます。
実践的
モデルが学習するのは世界ではなくデータセットです#
モデルは、見たことのある例の間を補間します。晴れた日中の道路で学習し、夜の霧がかかったガレージに導入すると、モデルは失敗します。車の見た目が違うからではなく、そうした条件下の車を見たことがないからです。この不一致はドメインシフトと呼ばれます。検証画像も同じ偏りのあるデータから取得されている場合、検証ではこの問題を予測できません。
解決策はアルゴリズムではなく、データ構成にあります。ラベル付けの前に、導入先の環境から意図的にサンプルを収集します。データ収集とアノテーションのガイドで具体的な手順を説明しています。
実データセットを監査する#

上のmedical-pillsデータセットは、すべての錠剤にボックスを付けたブリスターパックのクローズアップ画像で、監査に適した題材です。Ultralytics Platformでは、データセットページに主要な件数が表示されます。以下のスクリプトでは、ultralyticsに同梱されているコピーを使って、カバレッジを明らかにする数値を計算します。
from collections import Counter
from pathlib import Path
from PIL import Image, ImageStat
from ultralytics.data.utils import check_det_dataset
data = check_det_dataset("medical-pills.yaml") # downloads the dataset on first use
for split in ("train", "val"):
images = sorted(Path(data[split]).glob("*.jpg"))
labels = [Path(str(p).replace("/images/", "/labels/")).with_suffix(".txt") for p in images]
rows = [line.split() for f in labels if f.exists() for line in f.read_text().splitlines()]
classes = Counter(data["names"][int(r[0])] for r in rows)
backgrounds = sum(not f.exists() or not f.read_text().strip() for f in labels)
areas = sorted(float(r[3]) * float(r[4]) for r in rows) # box area as a share of the image
sizes = Counter(Image.open(p).size for p in images)
brightness = [ImageStat.Stat(Image.open(p).convert("L")).mean[0] for p in images]
print(f"{split}: {len(images)} images, {backgrounds} backgrounds, {dict(classes)}, sizes {dict(sizes)}")
print(f" boxes: median {areas[len(areas) // 2]:.1%} of the image, {sum(a < 0.01 for a in areas)} of {len(areas)} under 1%")
print(f" brightness: {min(brightness):.0f} to {max(brightness):.0f} (0 = black, 255 = white)")train: 92 images, 0 backgrounds, {'pill': 1623}, sizes {(1920, 1080): 92}
boxes: median 1.4% of the image, 320 of 1623 under 1%
brightness: 171 to 198 (0 = black, 255 = white)
val: 23 images, 0 backgrounds, {'pill': 399}, sizes {(1920, 1080): 23}
boxes: median 1.4% of the image, 79 of 399 under 1%
brightness: 171 to 198 (0 = black, 255 = white)カバレッジレポートとして、1行につき1つの所見を読み取ります。
| 所見 | 意味 | 判断 |
|---|---|---|
| 解像度は1種類、1920×1080 | カメラと撮影設定が1種類 | 導入予定のすべてのカメラモデルから収集します |
| 明るさは171~198のみ | 明るく均一なスタジオ照明のみで、暗い画像はありません | 薬局のカウンターに導入する前に、暗所、逆光、混合照明の画像を収集します |
| 背景画像は0枚 | モデルは錠剤のないシーンを一度も見ていません | 錠剤のないブリスターパック、別の錠剤、何も置かれていないカウンターをハードネガティブとして追加します |
| ボックスの中央値は画像の1.4%で、5個に1個のボックスが1%未満です | 小さい物体 | imgszを十分に高く保ち、遠くから撮影した画像も意図的に含めます |
クラスは1つ、pill | 錠剤の種類は区別されていません | 個数を数えるだけなら問題ありません。判断に必要な場合にのみクラスを追加します |
検証データにも同じ条件がすべて含まれているため、これらの不足は検証スコアに現れません。
カバレッジを構成する4つの軸#
| 軸 | 収集するデータ | 不足時に起こりやすい失敗 |
|---|---|---|
| 照明 | 夜明け、正午、夕暮れ、夜、グレア、逆光、ちらつく蛍光灯 | 交代勤務の時間帯や直射日光下で再現率が大幅に低下します |
| 天候と大気の状態 | 雨、霧、雪、ほこり、レンズの結露 | 水滴を誤検出し、かすみの中で見逃します |
| オクルージョンと混雑 | 一部が隠れた対象、混雑したシーン、フレーム端で一部が切れた物体 | 対象が完全に見えない場合に見逃します |
| カメラと視点 | レンズ、取り付け高さと角度、解像度、圧縮、モーションブラー | パイロット導入先のカメラでは動作しても、次の導入先では失敗します |
マリーナの例で不足していた軸は視点です。同じクラスでも新しい角度から見ると、再現率はゼロになりました。
ハードネガティブと背景画像#
検出器は、何が対象ではないのかも学習する必要があります。ハードネガティブとは、一見すると対象に似ているものです。フォークリフト検出器の場合、ハンドパレットトラック、シザーリフト、磨かれた床に映るフォークリフトの反射、フォークリフトが印刷された安全ポスターなどが該当します。
YOLO形式では、背景画像はラベルファイルのない画像、つまり何も描画するものがない画像です。Ultralyticsの学習のヒントでは、誤検出を減らすために背景画像を約0~10%含めることを推奨しています。COCO自体にも約1%含まれています。その割合分には、ランダムな空のフレームではなく、自分の環境から収集したハードネガティブを含めます。データ拡張で明るさや角度を変えることはできますが、モデルが見たことのないハンドパレットトラックを新たに作り出すことはできません。
よくある落とし穴#
症状: ラベル付け済みの画像が1万枚あるものの、すべて昼間にパイロットカメラで撮影されています。対処法: 配備先のカメラで、あらゆる条件を網羅するよう数週間撮影して、カバレッジを監査してから、ラベル付けに費用をかけます。合成データで既知の不足を補うことはできますが、実際の撮影データの代わりにはなりません。
症状: 検証時のmAPは高いのに、初めての拠点では結果が悪くなります。対処法: 検証データにもデータセットの見落としが反映されることを忘れないでください。ランダムに選んだ学習画像10枚と本番フレーム10枚を取り出し、同僚に見分けてもらいます。見分けられるなら、ドメインギャップがあります。
条件ごとの目標件数を定めたサンプリング計画を作成するには、高性能YOLOデータセットの構築の高品質で代表性のあるデータを収集するに進んでください。
解答を表示
薬局のカウンターで、店舗のさまざまな照明の下にmedical-pillsをデプロイする場合は、監査結果(明るさ171~198、1920×1080のソースが1つ、背景画像が0枚)と画像をざっと確認した結果からグリッドを埋めます。同じ明るい面の上に同じパッケージが写っており、手が写っていないことが分かります。
| クラス | 明るいスタジオ照明 | 暗めまたは暖色系の店舗照明 | 逆光/グレア | 手で一部が隠れている | スマートフォンのカメラ |
|---|---|---|---|---|---|
pill | 2,022 | 0 | 0 | 0 | 0 |
| 背景 | 0 | 0 | 0 | — | 0 |
優先順位を付けた収集計画:
- 暗めまたは暖色系の店舗照明 — カウンターで通常見られる条件ですが、現在の画像は0枚です。
- 手で一部が隠れている — 実際のやり取りのほぼすべてで発生します。
- スマートフォンのカメラ — 2つ目のセンサーと解像度です。
- 逆光/グレア — アルミ箔のパッケージは窓や天井照明を反射します。
ハードネガティブ:空のブリスターパック(同じアルミ箔で、錠剤は入っていないもの)と、カウンター上のその他の丸い物体(硬貨、ボタン、キャンディー)。背景画像としてデータセットの約5~10%を追加します。