Data Cleaning
データクリーニングでは、学習前にデータセット内の破損ファイル、重複、欠損値、ラベルの誤りを検出して修正します。手法、ツール、コードを解説します。
データクリーニング(データクレンジングまたはデータスクラビングとも呼ばれます)とは、データセット内の破損、重複、不完全、不整合、誤ラベルのレコードを見つけて修正または削除するプロセスです。機械学習(ML)では、モデルはエラーも含めて学習データに含まれるものを学習するため、データ前処理と学習の前に行います。自転車の半数に「オートバイ」とラベル付けされた画像で学習した検出器は、その混同を学習します。また、誤ったラベルを含むテストセットでは、モデルの性能が誤って評価されます。データクリーニングはデータ中心AIの中核的な実践であり、アーキテクチャではなくデータを改善することでモデルの性能を高めます。
データ品質がモデルの性能を制限する理由#
データのエラーは、いくつかの形で精度を損ないます。誤ラベルの例は誤った入出力の対応関係を教え、ノイズを記憶することでモデルを過学習に向かわせます。重複データは一部の例に過剰な重みを与え、複製データが学習用と評価用の両方に入ると、スコアを水増しするデータリークを引き起こします。破損ファイルはデータローダーをクラッシュさせるか、気づかれないままスキップされます。また、クラス名の不整合により、1つのカテゴリが複数に分割されます。ベンチマークも影響を受けます。広く使われるテストセット10種を対象にした研究では、平均で少なくとも3.3%の例にラベルエラーがあり、ImageNet検証セットでは少なくとも6%にエラーがあると推定されました。修正済みラベルで評価すると、元のテスト例に占める誤ラベルの割合がわずか6%増えただけで、ResNet-18はResNet-50を上回ります。
一般的なデータクリーニング作業#
表形式データは通常、pandasなどのライブラリでクリーニングします。一方、ビジョンデータセットでは、画像ファイルとそのアノテーションを確認し、ピクセルからバウンディングボックスの座標まで検査する必要があります。埋め込みを比較して類似画像を検出し、ベクトル検索を使って数百万枚の画像にも比較を拡張できます。
- 欠損値: 空欄のあるレコードは削除するか、列の統計量や最近傍データから補完します。ビジョンデータセットでは、ラベルファイルのない画像が意図的な背景画像なのか、単に誰もアノテーションしていない画像なのか判別できない場合があります。
- 重複と類似画像: バイト単位で同一のファイルは同じハッシュ値を持ちます。リサイズや再圧縮を行ったコピー、連続する動画フレームは同じ値にならないため、知覚ハッシュまたは埋め込みの類似度を使う必要があります。
- 破損ファイルと無効ファイル: ダウンロードの切り詰め、未対応形式、想定外のカラーモード、極端に小さい画像は、デコードに失敗するか、利用可能な情報を含みません。
- ラベルエラー: クラスの誤り、オブジェクトの見落とし、緩すぎるボックスや位置のずれたボックスは、教師ありビジョンデータにおける最もコストの高いエラーであり、目視で見つけるのも最も困難です。
- カテゴリの不整合: 「Car」と「car」のような表記の違いや、「automobile」と「vehicle」のように重複するクラスは、1つの概念に1つのラベルが対応するよう、1つの分類体系に統合します。
- 外れ値: 負の年齢や画像の境界を越えるボックスなど、あり得ない値は修正すべきエラーです。一方、まれでも妥当なケースは残します。こうした例外的なケースこそ、モデルが学習する必要性の高い例であることが多いためです。
モデルを使ったラベルエラーの検出#
すべてのラベルを手作業で確認する方法は規模を拡大できないため、クリーニングパイプラインでは学習済みモデルを使って確認対象の優先順位を付けます。オープンソースのcleanlabライブラリに実装された信頼性学習では、交差検証によるアウトオブサンプル予測確率を使い、与えられたラベルとは異なるクラスをモデルが高い確信度で予測する例にフラグを付けます。最終判断は人が行います。前述のテストセット研究では、クラウドソーシングのレビュアーがアルゴリズムによってフラグ付けされた候補の51%を実際のラベルエラーと確認しました。
ファイルチェックの自動化#
ファイル単位のチェックは、新しいデータバッチごとに実行しても十分低コストです。データセット品質管理のレッスンで扱うラベルとクラスバランスの監査と併せて実施できます。次のスクリプトは、画像1枚、完全なコピー、途中で切れたファイルを含む小さなフォルダーを作成し、Pillowとコンテンツハッシュを使ってコピーと破損ファイルを検出します。
import hashlib
from pathlib import Path
from PIL import Image
# A tiny image folder: one original, one exact copy, and one truncated download
folder = Path("images")
folder.mkdir(exist_ok=True)
Image.new("RGB", (640, 480), "orange").save(folder / "a.jpg")
(folder / "b.jpg").write_bytes((folder / "a.jpg").read_bytes())
(folder / "c.jpg").write_bytes((folder / "a.jpg").read_bytes()[:1000])
seen = {}
for path in sorted(folder.glob("*.jpg")):
try:
Image.open(path).load() # decode every pixel; a truncated file raises OSError
except OSError as error:
print(f"{path.name}: corrupt ({error})")
continue
digest = hashlib.md5(path.read_bytes()).hexdigest() # identical bytes give identical hashes
if digest in seen:
print(f"{path.name}: duplicate of {seen[digest]}")
seen.setdefault(digest, path.name)スクリプトはb.jpg: duplicate of a.jpgとc.jpg: corrupt (image file is truncated (5 bytes not processed))を出力します。各画像を完全にデコードすることが重要です。ファイルを開いただけではヘッダーしか読み込まれず、切り詰められたファイルでもその段階を通過することがあるためです。Ultralytics YOLOは、データセットのラベルキャッシュを作成する際に同様のチェックを実行します。終端マーカーがないJPEGを再保存し、重複したラベル行を削除します。また、画像の寸法が10ピクセル未満、座標が画像の範囲外、クラスIDがデータセットのYAMLに定義された範囲外の画像とラベルのペアをスキップし、スキャン概要に画像、背景、破損データの件数を報告します。
データクリーニングと関連用語の比較#
- データ前処理: 画像のリサイズやピクセル値の正規化など、すでに正しいデータをモデルが期待する形式に変換します。どのデータが正しいかを判断するのがクリーニングです。
- データ拡張: 学習中に、反転や色の変更などの意図的な変化をクリーニング済みデータに加えます。
- データラベリング: ラベルのないデータにラベルを作成します。一方、クリーニングでは既存のラベルを監査して修正します。
- データセットバイアス: データセットにエラーがなくても、一部の条件やグループが十分に含まれていない場合があります。バイアスを修正するには、クリーニングだけでは不十分で、異なるデータを収集する必要があります。










