ハイパーパラメータ
すべての学習引数はTrainConfig dataclassのフィールドです。基底クラスがフィールドとデフォルト値を定義し、各モデルファミリーがそれをサブクラス化して、公開レシピで異なるデフォルト値をオーバーライドします。
引数の設定
train()はキーワード引数を受け取り、CLIは同じ名前をkey=value形式で受け取ります。
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"])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を
出します。その後、デフォルト値を使って学習が開始されます。
# UserWarning: 不明な学習設定キー、無視: ['learning_rate']
model.train(data="my-dataset.yaml", learning_rate=0.001)何も失敗せず、実行は完了しますが、学習率は呼び出し元が要求した値にはなりません。新しい レシピの最初のエポックでは警告を確認してください。CLIは設定構築前にフラグ名を検証するため、 より厳密です。入力ミスのあるCLIフラグは直ちに拒否されます。
デフォルト値はファミリーごとに異なります
TrainConfigはフィールドと基本デフォルトを定義します。各ファミリーがそれをサブクラス化し、
公開レシピで異なる値をオーバーライドするため、「デフォルトの学習率は何か」に単一の正解は
ありません。
基本デフォルトはoptimizer="sgd"、lr0=0.01、momentum=0.937、
weight_decay=5e-4、scheduler="yoloxwarmcos"、epochs=300、batch=16、
imgsz=640、amp=Trueです。ファミリーがそこからどれほど変わるかを3例で示します。
| フィールド | 基本 | YOLOv9 | D-FINE | YOLO-NAS |
|---|---|---|---|---|
optimizer | sgd | sgd | adamw | adamw |
lr0 | 0.01 | 0.01 | 2e-4 | 5e-4 |
weight_decay | 5e-4 | 5e-4 | 1e-4 | 1e-5 |
scheduler | yoloxwarmcos | linear | flat_cosine | cos |
epochs | 300 | 300 | 132 | 300 |
amp | True | True | False | False |
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}")# ファミリーによる上書きを含め、train、val、predictのデフォルト値を表示libreyolo cfgバッチサイズ
batchはグローバルバッチです。マルチGPU学習では、各rankがbatch // world_sizeを読み込む
ため、渡す数値はGPU数にかかわらずoptimizerステップごとの画像数です。
マルチGPU学習を参照してください。
batch=-1は自動バッチを有効にします。学習器は学習モードのモデルに対して、2の累乗ごとに実際の
逆伝播を使って調査し、メモリ曲線へ直線を当てはめます。その後、総VRAMの60パーセント以内に
収まると推定された値を厳密に下回る、最大の2の累乗を選びます。
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # batch=-1はGPUメモリを調査し、具体的な2の累乗に解決model.train(data="my-dataset.yaml", batch=-1, imgsz=640)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)個のマイクロバッチを累積します。
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # optimizerステップごとに16のマイクロバッチを4回、実効バッチは64model.train(data="my-dataset.yaml", batch=16, nbs=64)デフォルトのNoneのままなら累積は無効で、学習は変わりません。
学習率とスケジュール
lr0は初期学習率で、optimizerはsgd、adam、adamwを受け取ります。momentumは
SGDのmomentumまたはAdamのbeta1、weight_decayはL2項で、nesterovはSGDに適用されます。
スケジュールの形状はscheduler、warmup_epochs、warmup_lr_start、min_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.ptとlast.ptに含まれるのはEMAの重みです。学習された生の重みも
train_modelキーに保存されるため、再開時は平均からではなく学習軌跡から継続します。
精度
amp=TrueはCUDA autocastの下で順伝播を実行します。amp_dtypeはfloat16(デフォルト)または
bfloat16を選択します。fp16とbf16という綴りも受け入れられます。
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は中断した実行を継続します。再開処理は別の引数ではなくモデルからチェックポイントを
読み取るため、先にチェックポイントを読み込む必要があります。
from libreyolo import LibreYOLO # 中断した実行のチェックポイントを読み込み、再開を要求model = LibreYOLO("runs/train/exp/weights/last.pt")model.train(data="my-dataset.yaml", epochs=100, resume=True)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=Trueはpretrainedと併用できず、例外を発生させます。また、
チェックポイントの最良指標キーが現在の実行と異なる場合、意味の違う値を比較せず、警告とともに
最良指標の追跡を0へリセットします。
ファイル内のレシピ
cfg=はTrainConfigフィールド名のYAMLマッピングを読み込み、明示的なキーワード引数の下に
マージします。そのため、常にkwargがファイルより優先されます。
from libreyolo import LibreYOLO # yamlのキーはTrainConfigフィールド名。明示的なkwargsが優先model = LibreYOLO("LibreYOLO9s.pt")model.train(data="my-dataset.yaml", cfg="my-recipe.yaml", epochs=50)モデルインスタンスがすでに所有するため、sizeとnum_classesはファイルから除去されます。
CLIには--cfgフラグがなく、ファイルパスはPython引数です。