Kフォールド・クロス・バリデーションUltralytics
はじめに
この包括的なガイドでは、Ultralytics エコシステム内のオブジェクト検出データセットに対する K-Fold Cross Validation の実装について説明します。YOLO 検出フォーマットと、sklearn、pandas、PyYaml などの主要なPython ライブラリを活用して、必要なセットアップ、特徴ベクトルの生成プロセス、K-Fold データセット分割の実行をガイドします。
このチュートリアルでは、Fruit Detectionのデータセットを使用するプロジェクトであれ、カスタムデータソースを使用するプロジェクトであれ、K-Foldクロスバリデーションを理解し、適用して、信頼性と堅牢性を強化することを目的としています。 機械学習 モデルを使用している。私たちは k=5
このチュートリアルでは、最適な回数はデータセットやプロジェクトの仕様によって異なることを念頭に置いています。
では、さっそく見ていこう!
セットアップ
-
注釈は、YOLO 検出フォーマットでなければなりません。
-
このガイドでは、注釈ファイルがローカルにあることを前提としています。
-
このデモでは、Fruit Detectionデータセットを使用する。
- このデータセットには合計8479枚の画像が含まれている。
- これは6つのクラス・ラベルを含み、それぞれのインスタンス総数は以下の通りである。
クラスラベル | インスタンス数 |
---|---|
アップル | 7049 |
ブドウ | 7202 |
パイナップル | 1613 |
オレンジ | 15549 |
バナナ | 3536 |
スイカ | 1976 |
-
必要なPython パッケージは以下の通り:
ultralytics
sklearn
pandas
pyyaml
-
このチュートリアルでは
k=5
回である。しかし、特定のデータセットに最適なフォールド数を決定する必要がある。 -
新しいPython 仮想環境 (
venv
)をプロジェクトに追加し、アクティベートする。使用方法pip
(またはお好みのパッケージ・マネージャー)でインストールする:- Ultralytics ライブラリー:
pip install -U ultralytics
.または、公式の レポ. - Scikit-learn、pandas、PyYAML:
pip install -U scikit-learn pandas pyyaml
.
- Ultralytics ライブラリー:
-
注釈がYOLO 検出フォーマットであることを確認してください。
- このチュートリアルでは、すべての注釈ファイルは
Fruit-Detection/labels
ディレクトリにある。
- このチュートリアルでは、すべての注釈ファイルは
物体検出データセットの特徴ベクトルの生成
-
新しい
example.py
Python ファイルを作成する。 -
データセットのすべてのラベルファイルを取得する。
-
さて、データセットのYAMLファイルの中身を読んで、クラスラベルのインデックスを抽出しましょう。
-
空の
pandas
データフレーム。 -
注釈ファイルに存在する各クラスラベルのインスタンスを数える。
from collections import Counter for label in labels: lbl_counter = Counter() with open(label) as lf: lines = lf.readlines() for line in lines: # classes for YOLO label uses integer at first position of each line lbl_counter[int(line.split(" ")[0])] += 1 labels_df.loc[label.stem] = lbl_counter labels_df = labels_df.fillna(0.0) # replace `nan` values with `0.0`
-
以下は、入力されたDataFrameのサンプルビューです:
0 1 2 3 4 5 '0000a16e4b057580_jpg.rf.00ab48988370f64f5ca8ea4...' 0.0 0.0 0.0 0.0 0.0 7.0 '0000a16e4b057580_jpg.rf.7e6dce029fb67f01eb19aa7...' 0.0 0.0 0.0 0.0 0.0 7.0 '0000a16e4b057580_jpg.rf.bc4d31cdcbe229dd022957a...' 0.0 0.0 0.0 0.0 0.0 7.0 '00020ebf74c4881c_jpg.rf.508192a0a97aa6c4a3b6882...' 0.0 0.0 0.0 1.0 0.0 0.0 '00020ebf74c4881c_jpg.rf.5af192a2254c8ecc4188a25...' 0.0 0.0 0.0 1.0 0.0 0.0 ... ... ... ... ... ... ... 'ff4cd45896de38be_jpg.rf.c4b5e967ca10c7ced3b9e97...' 0.0 0.0 0.0 0.0 0.0 2.0 'ff4cd45896de38be_jpg.rf.ea4c1d37d2884b3e3cbce08...' 0.0 0.0 0.0 0.0 0.0 2.0 'ff5fd9c3c624b7dc_jpg.rf.bb519feaa36fc4bf630a033...' 1.0 0.0 0.0 0.0 0.0 0.0 'ff5fd9c3c624b7dc_jpg.rf.f0751c9c3aa4519ea3c9d6a...' 1.0 0.0 0.0 0.0 0.0 0.0 'fffe28b31f2a70d4_jpg.rf.7ea16bd637ba0711c53b540...' 0.0 6.0 0.0 0.0 0.0 0.0
行はラベルファイルのインデックスを表し、それぞれがデータセット中の画像に対応し、列はクラスラベルのインデックスに対応する。各行は擬似的な特徴ベクトルを表し、データセットに存在する各クラスラベルのカウントを表す。このデータ構造により、物体検出データセットにK-Foldクロスバリデーションを適用することができる。
Kフォールド・データセット分割
-
では
KFold
クラスsklearn.model_selection
を生成する。k
データセットの分割。- 重要だ:
- セッティング
shuffle=True
は、分割におけるクラスのランダムな分布を保証します。 - セッティング
random_state=M
どこM
を整数にすれば、再現性のある結果を得ることができる。
- セッティング
- 重要だ:
-
データセットは現在、以下のように分割されている。
k
のリストを持つ。train
そしてval
インデックスを表示します。これらの結果をより明確に表示するために、DataFrameを作成する。 -
では、各フォールドのクラス・ラベルの分布を、次のように計算する。
val
に出席した。train
.fold_lbl_distrb = pd.DataFrame(index=folds, columns=cls_idx) for n, (train_indices, val_indices) in enumerate(kfolds, start=1): train_totals = labels_df.iloc[train_indices].sum() val_totals = labels_df.iloc[val_indices].sum() # To avoid division by zero, we add a small value (1E-7) to the denominator ratio = val_totals / (train_totals + 1e-7) fold_lbl_distrb.loc[f"split_{n}"] = ratio
理想的なシナリオは、すべてのクラスの比率が、各スプリットで、またクラス間で、適度に似ていることです。しかし、これはデータセットの仕様に依存します。
-
次に、各スプリットのディレクトリとデータセットのYAMLファイルを作成します。
import datetime supported_extensions = [".jpg", ".jpeg", ".png"] # Initialize an empty list to store image file paths images = [] # Loop through supported extensions and gather image files for ext in supported_extensions: images.extend(sorted((dataset_path / "images").rglob(f"*{ext}"))) # Create the necessary directories and dataset YAML files save_path = Path(dataset_path / f"{datetime.date.today().isoformat()}_{ksplit}-Fold_Cross-val") save_path.mkdir(parents=True, exist_ok=True) ds_yamls = [] for split in folds_df.columns: # Create directories split_dir = save_path / split split_dir.mkdir(parents=True, exist_ok=True) (split_dir / "train" / "images").mkdir(parents=True, exist_ok=True) (split_dir / "train" / "labels").mkdir(parents=True, exist_ok=True) (split_dir / "val" / "images").mkdir(parents=True, exist_ok=True) (split_dir / "val" / "labels").mkdir(parents=True, exist_ok=True) # Create dataset YAML files dataset_yaml = split_dir / f"{split}_dataset.yaml" ds_yamls.append(dataset_yaml) with open(dataset_yaml, "w") as ds_y: yaml.safe_dump( { "path": split_dir.as_posix(), "train": "train", "val": "val", "names": classes, }, ds_y, )
-
最後に、画像とラベルを各スプリットのディレクトリ('train'または'val')にコピーする。
- 注:コードのこの部分に要する時間は、データセットのサイズとシステムのハードウェアによって異なります。
import shutil from tqdm import tqdm for image, label in tqdm(zip(images, labels), total=len(images), desc="Copying files"): for split, k_split in folds_df.loc[image.stem].items(): # Destination directory img_to_path = save_path / split / k_split / "images" lbl_to_path = save_path / split / k_split / "labels" # Copy image and label files to new directory (SamefileError if file already exists) shutil.copy(image, img_to_path / image.name) shutil.copy(label, lbl_to_path / label.name)
レコードの保存(オプション)
オプションで、K-Fold分割とラベル配布のDataFrameのレコードをCSVファイルとして保存し、後で参照することができます。
folds_df.to_csv(save_path / "kfold_datasplit.csv")
fold_lbl_distrb.to_csv(save_path / "kfold_label_distribution.csv")
K-Fold データ分割を使用したトレーニングYOLO
-
まず、YOLO のモデルをロードする。
-
次に、データセットのYAMLファイルを反復処理してトレーニングを実行します。結果は
project
そしてname
引数で指定する。デフォルトでは、このディレクトリは'runs/detect/train#'であり、#は整数インデックスである。results = {} # Define your additional arguments here batch = 16 project = "kfold_demo" epochs = 100 for k, dataset_yaml in enumerate(ds_yamls): model = YOLO(weights_path, task="detect") results[k] = model.train( data=dataset_yaml, epochs=epochs, batch=batch, project=project, name=f"fold_{k + 1}" ) # include any additional train arguments
-
Ultralytics data.utils.autosplit関数を使用して、データセットを自動的に分割することもできます:
結論
このガイドでは、YOLO オブジェクト検出モデルのトレーニングに K-Fold 交差検証を使用するプロセスを探った。データセットをK個のパーティションに分割し、異なるフォールド間でバランスのとれたクラス分布を確保する方法を学びました。
また、レポートDataFramesを作成し、データの分割と分割されたラベル分布を視覚化する手順も検討した。
これは、大規模なプロジェクトや、モデルの性能をトラブルシューティングするときに特に役立つ。
最後に、各スプリットを使用した実際のモデル学習をループで実行し、さらなる分析と比較のために学習結果を保存した。
このK-Foldクロスバリデーションのテクニックは、利用可能なデータを最大限に活用するロバストな方法であり、モデルのパフォーマンスが信頼でき、異なるデータ・サブセット間で一貫していることを保証するのに役立ちます。その結果、特定のデータ・パターンに過剰適合する可能性が低く、より一般化可能で信頼性の高いモデルが出来上がります。
このガイドではYOLO を使用したが、これらのステップは他の機械学習モデルにもほとんど適用できることを忘れないでほしい。これらのステップを理解することで、あなた自身の機械学習プロジェクトでクロスバリデーションを効果的に適用することができます。ハッピー・コーディング!
よくあるご質問
K-Foldクロスバリデーションとは何か、なぜ物体検出に有用なのか?
Kフォールド交差検証は、モデルの性能をより確実に評価するために、データセットを「k」個のサブセット(フォールド)に分割する手法である。それぞれのフォールドはトレーニングデータと検証データの両方の役割を果たします。物体検出の文脈では、K-Fold Cross Validation を使用することで、Ultralytics YOLO モデルの性能がロバストで、異なるデータ分割にわたって一般化可能であることを確認し、その信頼性を高めることができます。K-Fold Cross Validation withUltralytics YOLO のセットアップの詳細な手順については、K-Fold Cross Validation withUltralytics を参照してください。
Ultralytics YOLO を使って K-Fold 交差検証を実装するには?
K-Fold Cross Validation をUltralytics YOLO で実施するには、以下のステップに従う必要がある:
- 注釈がYOLO 検出フォーマットであることを確認する。
- のようなPython ライブラリを使用する。
sklearn
,pandas
そしてpyyaml
. - データセットから特徴ベクトルを作成します。
- を使用してデータセットを分割します。
KFold
よりsklearn.model_selection
. - YOLO モデルを各スプリットでトレーニングする。
包括的なガイドについては、ドキュメントのK-Fold Dataset Splitセクションを参照してください。
なぜ物体検出にUltralytics YOLO を使う必要があるのか?
Ultralytics YOLO 、高精度で効率的な最先端のリアルタイム物体検出を提供します。検出、セグメンテーション、分類など、複数のコンピュータビジョンタスクをサポートする汎用性があります。さらに、Ultralytics HUBのようなツールとシームレスに統合し、コードなしでモデルのトレーニングやデプロイを行うことができます。詳細については、Ultralytics YOLO ページで利点と機能をご覧ください。
注釈がUltralytics YOLO の正しいフォーマットであることを確認するにはどうすればよいですか?
注釈は、YOLO の検出形式に従ってください。各アノテーションファイルには、画像内のバウンディングボックス座標とともにオブジェクトクラスを記載する必要があります。YOLO フォーマットは、オブジェクト検出モデルをトレーニングするための合理的で標準化されたデータ処理を保証します。適切なアノテーションフォーマットの詳細については、YOLO 検出フォーマットガイドをご覧ください。
フルーツ検出以外のカスタムデータセットでK-Foldクロスバリデーションを使用できますか?
注釈がYOLO 検出形式であれば、どのようなカスタムデータセットでも K-Fold Cross Validation を使用できます。データセットのパスとクラスラベルは、カスタムデータセット固有のものに置き換えてください。この柔軟性により、どのような物体検出プロジェクトでも、K-Fold Cross Validationを使用したロバストなモデル評価の恩恵を受けることができます。実用的な例として、特徴ベクトルの生成のセクションをご覧ください。