Markdownで表示

ハイパーパラメータ

すべての学習引数はTrainConfig dataclassのフィールドです。基底クラスがフィールドとデフォルト値を定義し、各モデルファミリーがそれをサブクラス化して、公開レシピで異なるデフォルト値をオーバーライドします。

引数の設定

train()はキーワード引数を受け取り、CLIは同じ名前をkey=value形式で受け取ります。

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")results = model.train(    data="my-dataset.yaml",    epochs=100,    batch=16,    imgsz=640,    lr0=0.01,) print(results["best_mAP50_95"])
CLI
libreyolo train model=LibreYOLO9s.pt data=my-dataset.yaml \  epochs=100 batch=16 imgsz=640 lr0=0.01

どちらの経路も同じ場所に到達します。kwargsはTrainConfig.from_kwargs()へ渡され、 ファミリーの設定dataclassが構築されます。

入力ミスは例外になりません

from_kwargs()は設定のフィールドではないキーをすべて破棄し、その名前を示すUserWarningを 出します。その後、デフォルト値を使って学習が開始されます。

python
# UserWarning: 不明な学習設定キー、無視: ['learning_rate']
model.train(data="my-dataset.yaml", learning_rate=0.001)

何も失敗せず、実行は完了しますが、学習率は呼び出し元が要求した値にはなりません。新しい レシピの最初のエポックでは警告を確認してください。CLIは設定構築前にフラグ名を検証するため、 より厳密です。入力ミスのあるCLIフラグは直ちに拒否されます。

デフォルト値はファミリーごとに異なります

TrainConfigはフィールドと基本デフォルトを定義します。各ファミリーがそれをサブクラス化し、 公開レシピで異なる値をオーバーライドするため、「デフォルトの学習率は何か」に単一の正解は ありません。

基本デフォルトはoptimizer="sgd"lr0=0.01momentum=0.937weight_decay=5e-4scheduler="yoloxwarmcos"epochs=300batch=16imgsz=640amp=Trueです。ファミリーがそこからどれほど変わるかを3例で示します。

フィールド基本YOLOv9D-FINEYOLO-NAS
optimizersgdsgdadamwadamw
lr00.010.012e-45e-4
weight_decay5e-45e-41e-41e-5
scheduleryoloxwarmcoslinearflat_cosinecos
epochs300300132300
ampTrueTrueFalseFalse

D-FINEとDEIMはamp=Falseで提供されます。D-FINEデコーダーが、float16で最大の有限値である 65504にアクティベーションをクランプするためです。YOLO-NASとFOMOもデフォルトで無効です。 CLIの--ampフラグはすべてのファミリーでデフォルトがTrueなので、ユーザー指定として数えられ、 ファミリーのデフォルト値を上書きします。変更する意図がない限り、そのままにしてください。

推測せず、ファミリーの実際のデフォルト値を確認するには次のようにします。

ファミリーの解決済みデフォルト値を確認
from dataclasses import fields from libreyolo import LibreYOLO9from libreyolo.training.config import TrainConfig family_cfg = LibreYOLO9.TRAIN_CONFIG()base_cfg = TrainConfig() for f in fields(family_cfg):    family_value = getattr(family_cfg, f.name)    base_value = getattr(base_cfg, f.name, None)    if not hasattr(base_cfg, f.name) or family_value != base_value:        print(f"{f.name}: {family_value}")
CLI
# ファミリーによる上書きを含め、train、val、predictのデフォルト値を表示libreyolo cfg

バッチサイズ

batchはグローバルバッチです。マルチGPU学習では、各rankがbatch // world_sizeを読み込む ため、渡す数値はGPU数にかかわらずoptimizerステップごとの画像数です。 マルチGPU学習を参照してください。

batch=-1は自動バッチを有効にします。学習器は学習モードのモデルに対して、2の累乗ごとに実際の 逆伝播を使って調査し、メモリ曲線へ直線を当てはめます。その後、総VRAMの60パーセント以内に 収まると推定された値を厳密に下回る、最大の2の累乗を選びます。

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # batch=-1はGPUメモリを調査し、具体的な2の累乗に解決model.train(data="my-dataset.yaml", batch=-1, imgsz=640)
CLI
libreyolo train model=LibreYOLO9s.pt data=my-dataset.yaml batch=-1

重要なのは逆伝播を伴う学習モードで調査することです。推論モードの調査では、保持される アクティベーションと勾配テンソルが漏れます。深いCNNの場合、これらは推論時の占有量の数倍です。 RF-DETRは目標比率を45パーセントに下げます。調査用の合成逆伝播でも、そのcriterionと補助 デコーダー層のコストを過小評価するためです。

自動バッチはCUDAの機能です。CPUまたはMPSでは1行をログに記録し、デフォルトバッチを維持します。

勾配累積

nbsは公称、つまり実効バッチサイズを設定します。学習器はoptimizerステップごとに round(nbs / batch)個のマイクロバッチを累積します。

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # optimizerステップごとに16のマイクロバッチを4回、実効バッチは64model.train(data="my-dataset.yaml", batch=16, nbs=64)

デフォルトのNoneのままなら累積は無効で、学習は変わりません。

学習率とスケジュール

lr0は初期学習率で、optimizersgdadamadamwを受け取ります。momentumは SGDのmomentumまたはAdamのbeta1、weight_decayはL2項で、nesterovはSGDに適用されます。

スケジュールの形状はschedulerwarmup_epochswarmup_lr_startmin_lr_ratioで 決まります。no_aug_epochsは強いデータ拡張を使わずに実行する最後のエポック数を設定します。 一部のスケジュールでは終端の形状にも使うため、純粋なデータ拡張設定ではありません。各ファミリーが データ拡張の側でどのように扱うかはデータ拡張にあります。

一部のファミリーは独自の学習率設定を追加します。backbone_lr_multはヘッドに対するバックボーン グループの倍率を設定し、clip_max_normは勾配クリッピングを設定します。SegFormerは head_lr_multを使い、デコードヘッドをバックボーンの10倍の学習率で実行します。これらは基底 クラスではなく、ファミリーの設定サブクラスにあります。

EMA

ema=Trueは学習済みの重みと並行して、重みの指数移動平均を維持します。FOMO以外ではデフォルトで 有効です。

ema_decayは目標の減衰率です。減衰率は目標値から始まらず、徐々に増加します。更新nでの実効値は ema_decay * (1 - exp(-n / tau))で、tauのデフォルトは2000です。そのため、初期の更新は モデルをより密に追跡し、後期の更新では平滑化します。ファミリーのデフォルト値は、YOLO-NAS姿勢の 0.997からYOLOXの0.9998、YOLOv9とDETR系の0.9999まで異なります。

検証され、best.ptlast.ptに含まれるのはEMAの重みです。学習された生の重みも train_modelキーに保存されるため、再開時は平均からではなく学習軌跡から継続します。

精度

amp=TrueはCUDA autocastの下で順伝播を実行します。amp_dtypefloat16(デフォルト)または bfloat16を選択します。fp16bf16という綴りも受け入れられます。

Float16には動的損失スケーリングが必要で、有効なGradScalerを使います。Bfloat16は指数範囲が 広いため不要で、scalerは構築されますが無効です。これによりoptimizer経路が同一に保たれます。 bfloat16に対応しないCUDAデバイスで要求すると、通知なく機能を落とさず、設定時に例外を 発生させます。

出力、チェックポイント、停止

実行はproject/nameへ書き出されます。projectのデフォルトはどこでもruns/trainですが、 nameはファミリーごとに上書きされる項目の1つです。基本デフォルトはexpで、YOLOv9は yolo9_exp、D-FINEはdfine_expを使います。デフォルトのexist_ok=Falseでは、既存の ディレクトリが上書きされず、連番の接尾辞が付けられます。

save_periodはNエポックごとに追加のweights/epoch_<N>.ptを書き出します。さらに、各エポック後の weights/last.ptと、追跡対象の指標が改善するたびのweights/best.ptがあります。 eval_intervalは検証の実行間隔を設定し、patienceは改善なしでそのエポック数が続くと実行を 停止します。0は早期終了を無効にします。

cacheは、デコード済み画像をRAM(Trueまたは"ram")か、ソースの隣の.npyファイル ("disk")に保持して、エポックの繰り返しを高速化します。キャッシュからの読み取りは新規の 読み取りとバイト単位で同一です。データローダーのワーカーを使う場合は"disk"の方が安全です。

再開

resume=Trueは中断した実行を継続します。再開処理は別の引数ではなくモデルからチェックポイントを 読み取るため、先にチェックポイントを読み込む必要があります。

Python
from libreyolo import LibreYOLO # 中断した実行のチェックポイントを読み込み、再開を要求model = LibreYOLO("runs/train/exp/weights/last.pt")model.train(data="my-dataset.yaml", epochs=100, resume=True)
CLI
libreyolo train model=runs/train/exp/weights/last.pt \  data=my-dataset.yaml epochs=100 resume=true

再開時には、学習済みの重み、optimizerの状態、EMAの重みと更新回数、最良指標の追跡、 GradScalerのスケール、PyTorch、CUDA、NumPyの乱数状態が復元されます。チェックポイントの エポックに1を加えた位置から開始し、スケジュールをその位置まで早送りします。

2つの処理は行いません。resume=Truepretrainedと併用できず、例外を発生させます。また、 チェックポイントの最良指標キーが現在の実行と異なる場合、意味の違う値を比較せず、警告とともに 最良指標の追跡を0へリセットします。

ファイル内のレシピ

cfg=TrainConfigフィールド名のYAMLマッピングを読み込み、明示的なキーワード引数の下に マージします。そのため、常にkwargがファイルより優先されます。

Python
from libreyolo import LibreYOLO # yamlのキーはTrainConfigフィールド名。明示的なkwargsが優先model = LibreYOLO("LibreYOLO9s.pt")model.train(data="my-dataset.yaml", cfg="my-recipe.yaml", epochs=50)

モデルインスタンスがすでに所有するため、sizenum_classesはファイルから除去されます。 CLIには--cfgフラグがなく、ファイルパスはPython引数です。

関連項目

  • data=が受け取るものについてはデータセットを参照してください。
  • データ拡張の設定値と、それを尊重するファミリーについてはデータ拡張を参照してください。
  • 重みの一部を学習する方法については層の凍結LoRAを参照してください。
  • 実行が報告する内容については検証と指標を参照してください。

LibreYOLO v1.5.0で検証済みです。