カスタムデータセットでYOLOをファインチューニングする方法#
ファインチューニングでは、ランダム初期化ではなく学習済みの重みから開始することで、学習済みモデルを新しいクラスの認識に適応させます。数百エポックをゼロから学習する代わりに、学習済みのCOCO特徴量を活用し、わずかな時間でカスタムデータに収束します。
このガイドでは、基本的な使い方から、レイヤーの凍結や2段階学習などの高度なテクニックまで、カスタムデータセットでのYOLO26のファインチューニングについて説明します。
ファインチューニングとゼロからの学習の比較#
学習済みモデルは、数百万枚の画像から、エッジ検出、テクスチャ認識、形状理解などの一般的な視覚特徴をすでに学習しています。ファインチューニングによる転移学習では、この知識を再利用し、新しいクラスの見た目だけをモデルに学習させます。そのため、より速く収束し、必要なデータも少なくなります。ゼロからの学習では、これらすべてを破棄し、ピクセルレベルのパターンからすべてを学習させるため、大幅に多くのリソースが必要です。アーキテクチャのみの.yamlファイルとチェックポイントの違いについては、モデルYAML設定ガイドを参照してください。
| ファインチューニング | ゼロからの学習 | |
|---|---|---|
| 開始時の重み | COCOで事前学習済み(80クラス) | ランダム初期化 |
| コマンド | YOLO("yolo26n.pt") | YOLO("yolo26n.yaml") |
| 収束 | 高速 - バックボーンはすでに学習済み | 低速 - すべてのレイヤーがゼロから学習 |
| データ要件 | 低い - 学習済み特徴量が少ないデータを補完 | 高い - モデルがデータセットだけからすべての特徴量を学習する必要がある |
| 使用する場面 | 自然画像を使用するカスタムクラス | COCOとは根本的に異なるドメイン(医療、衛星、レーダー) |
.ptファイルをYOLO("yolo26n.pt")で読み込むと、学習済みの重みがモデルに格納されます。その後に.train(data="custom.yaml")を呼び出すと、互換性のあるすべての重みが新しいモデルアーキテクチャに自動的に転送され、一致しないレイヤー(クラス数が異なる場合の検出ヘッドなど)が再初期化されて、学習が開始されます。手動での重みの読み込み、レイヤー操作、カスタム転移学習コードは必要ありません。
学習済み重みの転送の仕組み#
学習済みモデルを、クラス数が異なるデータセット(たとえば、COCOの80クラスから5つのカスタムクラス)でファインチューニングすると、Ultralyticsは形状を考慮して重みを転送します。
- バックボーンとネックは完全に転送 - これらのレイヤーは一般的な視覚特徴を抽出し、形状はクラス数に依存しません。
- 検出ヘッドは部分的に再初期化 - 分類出力レイヤー(
cv3、one2one_cv3)の形状はクラス数(80対5)に依存します。クラス名が一致する互換性のある行は、未一致の行を初期化する前に再マッピングされます。ヘッド内のボックス回帰レイヤー(cv2、one2one_cv2)はクラス数にかかわらず形状が固定されているため、通常どおり転送されます。 - クラス数を変更する場合でも、重みの大部分が転送されます。たとえば、COCO(80クラス)で学習したYOLO26nを5クラスのデータセットにファインチューニングすると、708個の重みテンソルのうち606個が転送され、名前が一致する互換性のある分類行も転送されます。
学習済みモデルと同じクラス数のデータセット(たとえば、COCOで事前学習した重みを別の80クラスデータセットでファインチューニングする場合)では、検出ヘッドを含む重みの100%が転送されます。
名前の別名を使用したクラスの転送#
Ultralyticsは、データセット間でクラス名が一致する分類ヘッドの行を、大文字と小文字および前後の空白を無視して転送します。同等のクラスで異なる名前が使われている場合は、読み込み前にメモリ上で元のチェックポイントのクラス名を変更します。これにより、未一致として扱われてランダムに初期化されるはずだった共有概念の学習済み分類重みを保持できます。
このObjects365 v2からCOCOへの例では、読み込んだチェックポイント上で元のクラス名を変更し、その後train()が学習済みの重みとして引き継ぎます。
from ultralytics import YOLO
# Source Objects365 v2 name (lowercased) -> target COCO name
ALIASES = {
"wild bird": "bird",
"handbag/satchel": "handbag",
"luggage": "suitcase",
"bowl/basin": "bowl",
"orange/tangerine": "orange",
"monitor/tv": "tv",
"stuffed toy": "teddy bear",
"hair dryer": "hair drier",
}
model = YOLO("path/to/yolo26s-objects365.pt")
# Objects365 class names are Title-Cased, so match on the lowercased name
model.model.names = {i: ALIASES.get(name.lower(), name) for i, name in model.model.names.items()}
model.train(data="coco.yaml", epochs=100, imgsz=640)cls_remap設定では、この名前ベースの転送がデフォルトで有効になります。互換性のある行がコピーされると、学習時にRemapped N/M cls head rows from pretrained weights by class nameが出力されます。無効にするにはcls_remap=Falseを設定してください。
基本的なファインチューニングの例#
from ultralytics import YOLO
model = YOLO("yolo26n.pt") # load pretrained model
model.train(data="custom.yaml", epochs=50, imgsz=640)モデルサイズの選択#
大きいモデルは容量が大きい一方で、更新するパラメータも多いため、学習データが限られている場合は過学習のリスクが高まります。小さいモデル(YOLO26nまたはYOLO26s)から始め、検証メトリクスが頭打ちになった場合にのみスケールアップする方法が実用的です。最適なモデルサイズは、タスクの複雑さ、クラス数、データセットの多様性、デプロイに使用できるハードウェアによって異なります。利用可能なサイズと性能ベンチマークについては、YOLO26モデルページ全体を参照してください。
オプティマイザーと学習率の選択#
デフォルトのoptimizer=auto設定では、学習イテレーションの総数に基づいてオプティマイザーと学習率が選択されます。
- 10,000イテレーション以下(小規模データセットまたは少ないエポック数):低い自動計算学習率のAdamW
- 10,000イテレーション超(大規模データセット):MuSGD(Muon+SGDのハイブリッドオプティマイザー)、lr=0.01
ほとんどのファインチューニングタスクでは、手動調整を行わなくてもデフォルト設定が適切に機能します。次の場合は、オプティマイザーを明示的に設定することを検討してください。
- 学習が不安定(損失が急上昇または発散する):より安定した収束のために
optimizer=AdamW, lr0=0.001を試してください - 小規模データセットで大規模モデルをファインチューニングする場合:
optimizer=AdamW, lr0=0.001のような低い学習率を使用する明示的なオプティマイザーにより、学習済み特徴量の保持に役立つ場合があります
optimizer=autoの場合、lr0とmomentumの値は無視されます。学習率を手動で制御するには、オプティマイザーを明示的に設定します:optimizer=SGD, lr0=0.005。
レイヤーの凍結#
凍結すると、学習中に特定のレイヤーが更新されなくなります。これにより学習が高速化し、データセットがモデル容量に対して小さい場合の過学習を軽減できます。
freezeパラメータには、整数またはリストを指定できます。整数のfreeze=10を指定すると、最初の10レイヤー(インデックス0~9)が凍結され、YOLO26のバックボーンの大部分が対象になります。バックボーンはレイヤー0~10にまたがるため、freeze=10では最後のC2PSAブロック(レイヤー10)が学習可能なままになります。バックボーン全体を凍結するにはfreeze=11を使用してください。リストには、部分的なバックボーンの凍結に使用するfreeze=[0, 3, 5]のようなレイヤーインデックスや、レイヤー内の特定の分岐を細かく制御するためのfreeze=["23.cv2", "23.one2one_cv2"]のようなモジュール名文字列を指定できます(ここでは検出ヘッドの両方のボックス回帰分岐)。
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=50, freeze=10)適切な凍結深度は、対象ドメインが学習済みデータにどの程度類似しているか、および利用可能な学習データ量によって決まります。
| シナリオ | 推奨事項 | 理由 |
|---|---|---|
| 大規模データセット、類似ドメイン | freeze=None(デフォルト) | 過学習せずにすべてのレイヤーを適応させるのに十分なデータがある |
| 小規模データセット、類似ドメイン | freeze=10 | バックボーンの特徴量を保持し、学習可能なパラメータを削減する |
| 非常に小規模なデータセット | freeze=23 | 検出ヘッドのみを学習し、過学習のリスクを最小限に抑える |
| COCOから大きく異なるドメイン | freeze=None | バックボーンの特徴量がうまく転送されず、再学習が必要になる可能性がある |
凍結深度はハイパーパラメータとして扱うこともできます。いくつかの値(0、5、10)を試して検証mAPを比較することは、特定のデータセットに最適な設定を見つける実用的な方法です。
ファインチューニングの主要なハイパーパラメータ#
ファインチューニングでは、一般にゼロから学習する場合ほど多くのハイパーパラメータ調整は必要ありません。最も重要なパラメータは次のとおりです。
epochs:ファインチューニングはゼロからの学習より速く収束します。適度な値から始め、検証メトリクスが頭打ちになったときに早期停止するにはpatienceを使用します。patience:デフォルトの100は長時間の学習向けに設計されています。これを10~20に減らすと、すでに収束した実行に時間を浪費せずに済みます。warmup_epochs:ウォームアップにより、最初のエポック中に学習率がスケジュールされた値へ段階的に移行するため、初期バッチによって学習済み特徴量が乱されにくくなります。ファインチューニングではゼロ以外にしてください。ただし、3エポックというデフォルト全体は必須ではありません。公式YOLO26 COCOファインチューニング(Objects365の重みから複数エポック継続する学習)の背後にある進化的探索では、各モデルサイズについて約1エポックに落ち着きました。
学習パラメータの完全な一覧については、学習設定リファレンスを参照してください。レイヤーごとの学習率、勾配クリッピング、カスタム検証メトリクスなど、パラメータで公開されていない動作については、トレーナーをサブクラス化してください。
2段階ファインチューニング#
2段階ファインチューニングでは、学習を2つのフェーズに分けます。第1段階ではバックボーンを凍結し、ネックとヘッドのみを学習します。これにより、学習済み特徴量を損なうことなく、検出レイヤーを新しいクラスに適応させることができます。第2段階ではすべてのレイヤーの凍結を解除し、低い学習率でモデル全体を学習して、対象ドメインに合わせてバックボーンを調整します。
この方法は、対象ドメインがCOCO(医療画像、航空画像、顕微鏡画像)と大きく異なる場合に特に有効です。このような場合、バックボーンの適応が必要になる可能性がありますが、すべてを一度に学習すると不安定になることがあります。コールバックベースの方法で自動的に凍結を解除するには、バックボーンの凍結と凍結解除を参照してください。
from ultralytics import YOLO
# Stage 1: freeze backbone, train head and neck
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=20, freeze=10, name="stage1", exist_ok=True)
# Stage 2: unfreeze all, fine-tune with lower lr
model = YOLO("runs/detect/stage1/weights/best.pt")
model.train(data="custom.yaml", epochs=30, optimizer="AdamW", lr0=0.001, name="stage2", exist_ok=True)よくある問題#
モデルが予測を生成しない#
-
学習データが不十分:サンプルが非常に少ない状態での学習は、最も一般的な原因です。データが少なすぎると、モデルは学習も汎化もできません。他の原因を調査する前に、クラスごとに十分な数の多様な例があることを確認してください。
-
データセットのパスを確認:無効な画像パスはデータセットエラーを発生させます。個々のラベルファイルが見つからない、または空の場合は背景画像として扱われ、スキャン中に報告されます。ラベルのない学習分割ではエラーが発生します。学習前にデータセットを検証してください。
yolo detect val model=yolo26n.pt data=custom.yaml -
信頼度しきい値を下げる:予測は存在するもののフィルタリングされている場合は、推論時に
conf=0.1を試してください。 -
クラス数を確認:
data.yaml内のncが、ラベルファイル内の実際のクラス数と一致していることを確認してください。
検証mAPが早期に頭打ちになる#
- データを追加:ファインチューニングは、特に角度、照明、背景が多様な例など、追加の学習データから大きな恩恵を受けます。
- クラスのバランスを確認:データ数の少ないクラスではAPが低くなります。例を追加するか、検証セットで
cls_pwを調整してください。 - データ拡張を減らす:非常に小規模なデータセットでは、強いデータ拡張が効果よりも悪影響を与える場合があります。
mosaic=0.5またはmosaic=0.0を試してください。 - 解像度を上げる:小さな物体を含むデータセットでは、詳細を保持するために
imgsz=1280を試してください。
ファインチューニング後に元のクラスの性能が低下する#
これは壊滅的忘却と呼ばれます。新しいデータだけでファインチューニングすると、モデルが以前に学習した知識を失います。新しいデータとともに元のデータセットの画像を含めない限り、忘却を完全に防ぐことはほぼ不可能です。軽減するには、次の方法があります。
- データセットを統合:ファインチューニング中に、新しいクラスとともに元のクラスの例を含めます。これは忘却を防ぐ唯一の信頼できる方法です。
- バックボーンとネックを凍結:バックボーンとネックの両方を凍結して検出ヘッドのみを学習すると、非常に低い学習率で短時間のファインチューニングを行う場合に役立ちます。
- 少ないエポック数で学習:モデルが新しいデータだけで学習する時間が長いほど、忘却が進みます。
FAQ#
固定の最小枚数はありません。結果は、タスクの複雑さ、クラス数、ドメインがCOCOにどの程度類似しているかによって異なります。多様な画像(さまざまな照明、角度、背景)のほうが、単純な枚数より重要です。まずは手元のデータで始め、検証メトリクスが不十分な場合に規模を拡大してください。
学習済みの
.ptファイルを読み込み、カスタムdata.yamlへのパスを指定して.train()を呼び出します。Ultralyticsは、重みの転送、検出ヘッドの再初期化、オプティマイザーの選択を自動的に処理します。完全なコード例については、基本的なファインチューニングセクションを参照してください。最も一般的な原因は、無効な画像パス、存在しないまたは空のラベルファイル、YAML内の
ncと実際のラベルファイルの不一致、または高すぎる信頼度しきい値です。完全なトラブルシューティングチェックリストについては、よくある問題を参照してください。データセットのサイズとドメインの類似性によって異なります。COCOに近いドメインの小規模データセットでは、バックボーン(
freeze=10)を凍結すると過学習を防げます。COCOとは大きく異なるドメインでは、すべてのレイヤーの凍結を解除したまま(freeze=None)にすると、バックボーンを適応させることができます。詳しい推奨事項については、レイヤーの凍結を参照してください。新しいクラスとともに、元のクラスの例を学習データに含めてください。それが不可能な場合は、より多くのレイヤー(
freeze=10以上)を凍結し、低い学習率を使用すると、学習済みの知識を保持しやすくなります。詳しくは、ファインチューニング後に元のクラスの性能が低下するを参照してください。