OFTv2 / BOFT Training / OFTv2・BOFT の学習

September 9, 2026 · View on GitHub

This document explains how to train OFTv2 and BOFT adapters with train_network.py (SD1.x / SD2.x) and sdxl_train_network.py (SDXL). Both are orthogonal fine-tuning methods: instead of adding a low-rank update like LoRA, they multiply the input side of each target layer by a learned orthogonal (rotation) matrix. The pre-trained weights are only rotated, so the norm and pairwise angles of the weight vectors are preserved.

These modules were contributed by umisetokikaze in PR #2357. The implementation follows the PEFT OFT / BOFT layers, and weights in PEFT format can be loaded.

The legacy networks.oft module (output-side rotation, different weight format) is unchanged and remains available.

日本語

このドキュメントでは、train_network.py(SD1.x / SD2.x)および sdxl_train_network.py(SDXL)で OFTv2 と BOFT のアダプタを学習する方法を説明します。いずれも直交変換によるファインチューニング手法で、LoRA のように低ランクの差分を加えるのではなく、対象層の入力側に学習した直交(回転)行列を掛けます。事前学習済み重みは回転されるだけなので、重みベクトルのノルムと相互の角度が保存されます。

これらのモジュールは umisetokikaze 氏により PR #2357 で追加されました。実装は PEFT の OFT / BOFT 層に準拠しており、PEFT 形式の重みを読み込めます。

従来の networks.oft モジュール(出力側の回転、異なる重み形式)は変更されておらず、引き続き利用できます。

1. Overview / 概要

ModuleMethodTrainable parameters per layer
networks.oft_v2OFTv2 (block-diagonal orthogonal transform, Cayley parameterization)oft_R.weight
networks.boftBOFT (butterfly-factorized orthogonal transform with per-output scale)boft_R, boft_s

Supported models: SD1.x, SD2.x, SDXL (U-Net and Text Encoders). FLUX.1, SD3, Lumina, HunyuanImage and Anima are not supported.

Target layers are the same as networks.lora: all Linear and 1x1 Conv2d layers inside Transformer2DModel blocks of the U-Net, and attention / MLP layers of the Text Encoders. 3x3 Conv2d layers can be added with enable_conv=true.

日本語
モジュール手法層ごとの学習パラメータ
networks.oft_v2OFTv2(ブロック対角の直交変換、Cayley パラメータ化)oft_R.weight
networks.boftBOFT(バタフライ分解した直交変換と出力ごとのスケール)boft_Rboft_s

対応モデル: SD1.x、SD2.x、SDXL(U-Net と Text Encoder)。FLUX.1、SD3、Lumina、HunyuanImage、Anima には対応していません。

対象層は networks.lora と同じで、U-Net の Transformer2DModel ブロック内の全 Linear と 1x1 Conv2d、Text Encoder の attention / MLP 層です。enable_conv=true で 3x3 Conv2d も対象に追加できます。

2. Command Line Arguments / コマンドライン引数

Specify the module with --network_module. --network_alpha is ignored by both modules.

Note on --network_dim: for networks.oft_v2 and networks.boft, --network_dim is interpreted as the block size (the size of each orthogonal block). This differs from the legacy networks.oft, where it means the number of blocks. If --network_dim is omitted, the default block size is 32 for OFTv2 and 4 for BOFT.

--network_dropout is mapped to the multiplicative dropout of the rotation blocks (randomly replacing blocks with the identity during training).

日本語

--network_module でモジュールを指定します。--network_alpha はどちらのモジュールでも無視されます。

--network_dim について: networks.oft_v2networks.boft では、--network_dimブロックサイズ(直交ブロック 1 つの大きさ)として解釈されます。ブロック数を意味する従来の networks.oft とは異なります。--network_dim を省略した場合のデフォルトは OFTv2 が 32、BOFT が 4 です。

--network_dropout は回転ブロックの乗算的ドロップアウト(学習中にブロックをランダムに単位行列へ置き換える)に対応付けられます。

2.1. networks.oft_v2 options (--network_args)

ArgumentDefaultDescription
block_size (or oft_block_size)--network_dim (32)Size of each orthogonal block. Overrides --network_dim.
coft (or oft_coft)falseEnable constrained OFT (COFT). The rotation is projected onto an ε-ball each step.
coft_eps6e-5Constraint radius for COFT.
block_share (or oft_block_share)falseShare one rotation block across all blocks of a layer (fewer parameters).
dropout (or dropout_probability)0.0Block dropout probability. --network_dropout takes precedence if given.
enable_convfalseAlso apply to 3x3 Conv2d layers (ResNet blocks, up/down samplers).
auto_adjusttrueIf in_features is not divisible by the block size, pick the nearest divisor automatically. If false, an error is raised instead.
include_patterns / exclude_patternsnonePython list of regular expressions matched (full match) against the module name, e.g. "exclude_patterns=['.*attn2.*']".
日本語
引数デフォルト説明
block_size(または oft_block_size--network_dim(32)直交ブロック 1 つの大きさ。--network_dim より優先されます。
coft(または oft_coftfalse制約付き OFT (COFT) を有効にします。毎ステップ回転を ε 球へ射影します。
coft_eps6e-5COFT の制約半径。
block_share(または oft_block_sharefalse層内の全ブロックで 1 つの回転ブロックを共有します(パラメータ数が減ります)。
dropout(または dropout_probability0.0ブロックドロップアウトの確率。--network_dropout が指定されていればそちらが優先されます。
enable_convfalse3x3 Conv2d 層(ResNet ブロック、up/down サンプラー)にも適用します。
auto_adjusttruein_features がブロックサイズで割り切れない場合、最も近い約数を自動で選びます。false の場合はエラーになります。
include_patterns / exclude_patternsなしモジュール名に対して完全一致で照合する正規表現の Python リスト。例: "exclude_patterns=['.*attn2.*']"

2.2. networks.boft options (--network_args)

ArgumentDefaultDescription
block_size (or boft_block_size)--network_dim (4)Size of each orthogonal block. Specify either this or block_num, not both.
block_num (or boft_block_num)noneNumber of blocks per layer. The block size is derived from in_features.
boft_n_butterfly_factor1Number of butterfly factors. 1 is a plain block-diagonal OFT with a scale; larger values add butterfly permutations. With values above 1, the block size and block count must be even and in_features must be divisible by block_size * 2^(factor-1).
dropout (or boft_dropout)0.0Block dropout probability. --network_dropout takes precedence if given.
enable_convfalseAlso apply to 3x3 Conv2d layers.
auto_adjusttrueAutomatically pick a valid block shape when the requested one does not fit the layer.
include_patterns / exclude_patternsnoneSame as OFTv2.
日本語
引数デフォルト説明
block_size(または boft_block_size--network_dim(4)直交ブロック 1 つの大きさ。block_num とどちらか一方のみ指定します。
block_num(または boft_block_numなし層ごとのブロック数。ブロックサイズは in_features から求めます。
boft_n_butterfly_factor1バタフライ因子の数。1 はスケール付きの単純なブロック対角 OFT で、大きくするとバタフライ置換が加わります。1 より大きい場合、ブロックサイズとブロック数は偶数、in_featuresblock_size * 2^(factor-1) で割り切れる必要があります。
dropout(または boft_dropout0.0ブロックドロップアウトの確率。--network_dropout が指定されていればそちらが優先されます。
enable_convfalse3x3 Conv2d 層にも適用します。
auto_adjusttrue指定した形状が層に合わない場合、有効なブロック形状を自動で選びます。
include_patterns / exclude_patternsなしOFTv2 と同じです。

3. Example / 実行例

SDXL, OFTv2, U-Net only:

accelerate launch --num_cpu_threads_per_process 1 sdxl_train_network.py \
  --pretrained_model_name_or_path="/path/to/sdxl_model.safetensors" \
  --dataset_config="/path/to/config.toml" \
  --output_dir="./output" --output_name="sdxl_oftv2" --save_model_as=safetensors \
  --network_module=networks.oft_v2 --network_dim=32 \
  --network_args "coft=false" "block_share=false" \
  --network_train_unet_only \
  --learning_rate=1e-4 --max_train_steps=1000 --train_batch_size=1 \
  --mixed_precision=fp16 --sdpa --gradient_checkpointing --cache_latents

BOFT with two butterfly factors:

  --network_module=networks.boft --network_dim=8 \
  --network_args "boft_n_butterfly_factor=2"

Other options (--unet_lr, --text_encoder_lr, --network_weights, sample generation, etc.) work the same way as for LoRA. See train_network.md and sdxl_train_network.md.

日本語

SDXL、OFTv2、U-Net のみの学習例は上記のとおりです。BOFT でバタフライ因子を 2 にする場合は 2 つ目の例のように指定します。

その他のオプション(--unet_lr--text_encoder_lr--network_weights、サンプル生成など)は LoRA と同様に動作します。train_network.mdsdxl_train_network.md を参照してください。

4. Weight Format and Compatibility / 重み形式と互換性

Weights are saved with the same key prefixes as LoRA (lora_unet_..., lora_te_..., lora_te1_..., lora_te2_...), followed by the parameter name, for example lora_unet_down_blocks_1_attentions_0_transformer_blocks_0_attn1_to_q.oft_R.weight.

When loading (--network_weights, gen_img.py, merging), the following key formats are recognized in addition to the native one:

  • OMI-style prefixes unet. / clip_l. / clip_g. with the original dotted module name.
  • PEFT adapter format base_model.model.<module name>.oft_R.weight / .boft_R / .boft_s. A PEFT adapter directory containing adapter_model.safetensors can be passed directly.

Keys that do not match any target module are ignored with a warning. When loading PEFT weights into SDXL, note that PEFT keys do not distinguish the two Text Encoders.

日本語

重みは LoRA と同じプレフィックス(lora_unet_...lora_te_...lora_te1_...lora_te2_...)にパラメータ名を付けたキーで保存されます。例: lora_unet_down_blocks_1_attentions_0_transformer_blocks_0_attn1_to_q.oft_R.weight

読み込み時(--network_weightsgen_img.py、マージ)には、native 形式に加えて次のキー形式を認識します。

  • OMI 風のプレフィックス unet. / clip_l. / clip_g. と、元のドット区切りモジュール名。
  • PEFT アダプタ形式 base_model.model.<モジュール名>.oft_R.weight / .boft_R / .boft_sadapter_model.safetensors を含む PEFT アダプタのディレクトリを直接指定できます。

対象モジュールに一致しないキーは警告を出して無視されます。PEFT 形式の重みを SDXL に読み込む場合、PEFT のキーは 2 つの Text Encoder を区別しない点に注意してください。

5. Notes / 注意点

  • Speed: the rotation matrices are rebuilt from the parameters at every forward pass with many small matrix operations. Per-step overhead is therefore higher than LoRA, and GPU utilization may stay low at small batch sizes. Larger batch sizes amortize this overhead. --gradient_checkpointing recomputes the rotations during backward as well.
  • Merging: merge_to is supported, so the adapters can be merged into the base weights (for example in gen_img.py). The merged weights are exactly the rotated original weights.
  • auto_adjust=true (default) may silently choose a different block size for some layers when the requested size does not divide in_features. The chosen shapes are inferred from the saved weights when loading, so this does not affect compatibility with your own checkpoints.
日本語
  • 速度: 回転行列は毎 forward でパラメータから多数の小さな行列演算により再構築されます。そのため LoRA よりステップあたりのオーバーヘッドが大きく、小さいバッチサイズでは GPU 使用率が上がらないことがあります。バッチサイズを大きくするとこのオーバーヘッドは相対的に小さくなります。--gradient_checkpointing を使うと backward 時にも回転の再計算が行われます。
  • マージ: merge_to に対応しているため、アダプタをベースの重みにマージできます(gen_img.py など)。マージ後の重みは元の重みを回転したものそのものです。
  • auto_adjust=true(デフォルト)では、指定したブロックサイズが in_features を割り切らない層で、別のブロックサイズが自動的に選ばれます。読み込み時には保存された重みから形状を推定するため、自分で学習したチェックポイントとの互換性には影響しません。