カスタムデータセットで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
# 読み込み元のObjects365 v2の名前(小文字化)-> 変換先のCOCO名
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のクラス名は先頭が大文字なので、小文字化した名前で照合します
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") # 事前学習済みモデルを読み込む
model.train(data="custom.yaml", epochs=50, imgsz=640)モデルサイズの選択#
大きなモデルは容量が大きい一方で、更新するパラメーターも多くなるため、学習データが限られている場合は過学習のリスクが高まります。小さなモデル(YOLO26nまたはYOLO26s)から始め、検証指標が頭打ちになった場合にのみサイズを大きくする方法が実用的です。最適なモデルサイズは、タスクの複雑さ、クラス数、データセットの多様性、デプロイに使用できるハードウェアによって異なります。利用可能なサイズと性能ベンチマークについては、YOLO26モデルページをご覧ください。
オプティマイザーと学習率の選択#
デフォルトのoptimizer=auto設定では、学習イテレーションの合計数に基づいてオプティマイザーと学習率が選択されます。
- 10,000イテレーション以下(小規模なデータセットまたは少ないエポック数):学習率が低く、自動計算されるAdamW
- 10,000イテレーション超(大規模なデータセット):lr=0.01のMuSGD(MuonとSGDを組み合わせたハイブリッドオプティマイザー)
ほとんどのファインチューニングタスクでは、デフォルト設定のままで適切に動作し、手動調整は不要です。次のような場合は、オプティマイザーを明示的に設定してください。
- 学習が不安定な場合(損失が急増する、または発散する):より安定して収束する
optimizer=AdamW, lr0=0.001を試してください - 小規模なデータセットで大きなモデルをファインチューニングする場合:
optimizer=AdamW, lr0=0.001など、学習率を下げたオプティマイザーを明示的に指定すると、事前学習済みの特徴を保持しやすくなります
optimizer=autoの場合、lr0とmomentumの値は無視されます。学習率を手動で制御するには、オプティマイザーを明示的に設定します:optimizer=SGD, lr0=0.005。
レイヤーの凍結#
凍結すると、学習中に特定のレイヤーが更新されなくなります。これにより学習が速くなり、データセットがモデル容量に比べて小さい場合の過学習を抑えられます。
freezeパラメーターには、整数またはリストを指定できます。整数のfreeze=10を指定すると、YOLO26のバックボーンの大部分を構成する最初の10レイヤー(インデックス0~9)が凍結されます。バックボーンはレイヤー0~10にわたるため、freeze=10では最後のC2PSAブロック(レイヤー10)が学習可能なままになります。バックボーン全体を凍結するには、freeze=11を使用してください。リストには、一部のバックボーンを凍結するfreeze=[0, 3, 5]のようなレイヤーインデックスや、レイヤー内の特定の分岐を細かく制御するfreeze=["23.cv2", "23.one2one_cv2"]のようなモジュール名の文字列を指定できます(この例では、検出ヘッドの2つのボックス回帰分岐の両方が対象です)。
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:ウォームアップでは、最初の数エポックにわたって学習率をスケジュールされた値まで徐々に上げるため、初期のバッチで事前学習済みの特徴が乱されにくくなります。ファインチューニングでは0以外の値を維持しますが、デフォルトの3エポックすべてを使う必要はありません。Objects365の重みから複数エポックにわたって継続学習する公式YOLO26 COCOファインチューニングの進化的探索では、すべてのモデルサイズでおよそ1エポックに落ち着きました。
学習パラメーターの全一覧については、学習設定リファレンスをご覧ください。レイヤーごとの学習率、勾配クリッピング、カスタム検証指標など、パラメーターでは設定できない動作を実装するには、トレーナーをサブクラス化してください。
2段階ファインチューニング#
2段階ファインチューニングでは、学習を2つのフェーズに分けます。第1段階ではバックボーンを凍結し、ネックとヘッドのみを学習させます。これにより、事前学習済みの特徴を損なわずに、検出レイヤーを新しいクラスに適応させられます。第2段階ではすべてのレイヤーの凍結を解除し、より低い学習率でモデル全体を学習させ、対象ドメインに合わせてバックボーンを調整します。
この方法は、対象ドメインがCOCO(医療画像、航空画像、顕微鏡画像など)と大きく異なり、バックボーンの適応が必要である一方、すべてを一度に学習させると不安定になる場合に特に有効です。コールバックを使って自動的に凍結を解除する方法については、バックボーンの凍結と凍結解除をご覧ください。
from ultralytics import YOLO
# 第1段階:バックボーンを凍結し、ヘッドとネックを学習します
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=20, freeze=10, name="stage1", exist_ok=True)
# 第2段階:すべての凍結を解除し、より低い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)よくある問題#
モデルが予測を出力しない#
-
学習データが不十分:サンプル数が非常に少ない状態での学習が最も一般的な原因です。データが少なすぎると、モデルは学習も汎化もできません。他の原因を調べる前に、各クラスについて十分な数の多様な例があることを確認してください。
-
データセットのパスを確認:画像パスが無効な場合、データセットエラーが発生します。個々のラベルファイルが見つからない場合や空の場合は、背景画像として扱われ、スキャン時に報告されます。学習用分割にラベルが1つもない場合はエラーが発生します。学習前にデータセットを検証してください。
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を試してください。
ファインチューニング後に元のクラスの性能が低下する#
これは破滅的忘却と呼ばれ、新しいデータだけでファインチューニングすると、モデルが以前に学習した知識を失う現象です。新しいデータとともに元のデータセットの画像を含めない限り、忘却を完全に防ぐことはほぼできません。影響を抑えるには、次の方法があります。
- データセットを統合:ファインチューニング時に、新しいクラスとともに元のクラスの例も含めてください。忘却を防ぐための、唯一信頼できる方法です。
- バックボーンとネックを凍結:バックボーンとネックの両方を凍結して検出ヘッドのみを学習させると、学習率を非常に低く設定した短時間のファインチューニングに有効です。
- エポック数を減らす:新しいデータだけで学習する時間が長いほど、忘却が進みます。
よくある質問#
固定の最小枚数はありません。結果はタスクの複雑さ、クラス数、ドメインがCOCOにどれほど似ているかによって異なります。画像の総数よりも、多様な画像(照明、角度、背景が異なるもの)のほうが重要です。手元にあるデータから始め、検証指標が不十分な場合はデータを増やしてください。
事前学習済みの
.ptファイルを読み込み、カスタムdata.yamlへのパスを指定して.train()を呼び出します。Ultralyticsが重みの転送、検出ヘッドの再初期化、オプティマイザーの選択を自動的に処理します。コード全体の例については、ファインチューニングの基本のセクションをご覧ください。最も一般的な原因は、無効な画像パス、ラベルファイルの欠落または空の状態、YAML内の
ncと実際のラベルファイルの不一致、または信頼度しきい値が高すぎることです。トラブルシューティングの全チェックリストについては、よくある問題をご覧ください。データセットのサイズとドメインの類似性によって異なります。COCOに近いドメインの小規模なデータセットでは、バックボーンを凍結すると(
freeze=10)、過学習を防げます。COCOとは大きく異なるドメインでは、すべてのレイヤーの凍結を解除すると(freeze=None)、バックボーンが適応できるようになります。詳しい推奨事項については、レイヤーの凍結をご覧ください。新しいクラスとともに、元のクラスの例もトレーニングデータに含めてください。それができない場合は、より多くのレイヤーを凍結し(
freeze=10以上)、学習率を下げることで、事前学習で得た知識を保持しやすくなります。詳しくは、元のクラスの性能が低下するをご覧ください。