技術 約10分で読めます

SenseNova U1 8BのLoRA trainerは32GB GPUのbf16学習を前提にする

いけさん目次

Laxhar/sensenova-u1-lora-trainer が出ていた。
SenseNova-U1-8B-MoT 用の単一GPU LoRA trainerで、設定はほぼ YAML 1枚から動かす形になっている。

「8B級なら軽い」とはいかず、README は 32GB GPU と bf16 学習を前提にしている。
モデルカードでは RTX 5090、A100 40GB、RTX 6000 Ada のような 32GB 以上の CUDA 12 系カードを対象にし、2048px四方の学習データでピーク VRAM は約20GBと書いている。
24GBカードはサンプル生成なら通るが、デフォルトのバケット設定では学習対象外という扱いだ。

2026年6月9日時点で周辺情報を見直した。
Laxhar の単一GPU LoRA / partial-finetune trainer のほかに、SenseNova 公式の 8B-MoT と 8-step LoRA、それに OpenSenseNova 本体に追加された full-parameter fine-tuning 用の training/ がある。
公式 training/ は重要な追加だが、8Bでも標準起動は80GB GPUを8枚使う分散学習で、Laxhar trainer の「32GB単一GPUで小さな style LoRA を焼く」用途とは別物だ。

このブログで最近触っていた AnimaLoraToolkitでWAI-Anima向けLoRAを学習した話 は、Anima 系の 2B DiT + Qwen3 TE を RunPod で焼く話だった。
今回の U1 trainer は、同じ画像生成 LoRA でも対象が SenseNova U1 に変わる。
ComfyUI で読ませるための LoRA というより、公式の examples/t2i/inference.py にそのまま渡せる upstream 形式の safetensors を作る道具だ。

4bit学習ではなくbf16オフロードに振っている

README と docs/SETUP.md を読むと、軽量化の方向がかなりはっきりしている。
4bit nf4 や 8bit base での LoRA 学習も試したが、gen tower 側に格子模様、走査線、手足の崩れが出たため、学習時の base は bf16 に戻したと説明している。

代わりに、重い部分を CPU と GPU の間で分ける。
prefix tower はプロンプトと画像条件 prefix のエンコードに使い、gen tower は flow matching の拡散ループで使う。
両方を同時に GPU に載せ続けるのではなく、prefix tower を一度 GPU に出して prefix-forward を済ませ、静的な prefix-KV cache を作ってから CPU に戻す。

その後の学習ステップでは、gen tower 側を GPU に置いて回す。
SETUP では 56 samples で prefix-KV cache が約3.3GB、bf16 base、bf16 LoRA、paged AdamW8bit、部分的な gradient checkpointing の組み合わせで、32GBカード上のピークが約20GBになると書いている。

U1 の画像生成側で低ビット学習が崩れたため、weight は bf16 のまま tower offload と cache で VRAM を削る構成になっている。

flowchart TD
    A["画像 + キャプション"] --> B["prefix towerをGPUへ<br/>prefix-forward"]
    E["bf16 base weights<br/>CPU上に保持"] -.->|offload| B
    B --> C["static prefix-KV cache<br/>56 samples 約3.3GB"]
    B --> D["prefix towerをCPUへ戻す"]
    E -.->|gen tower| F["gen towerをGPUに固定<br/>flow matching学習"]
    C --> F
    F --> G["LoRA attn+mlp<br/>+ 一部full fine-tune"]
    G --> H["trainable_state.safetensors"]

    style F fill:#1d4ed8,color:#fff
    style C fill:#065f46,color:#fff

prefix側を一度だけ処理して cache にし、学習ループでは gen tower と trainable surface だけが GPU に残る。
base を量子化して詰める方向とは違い、tower 単位の offload で VRAM を空ける設計だ。

小さいスタイルデータ向けのdefault.yaml

デフォルト設定は、モデルカードでも small-data style baseline と呼ばれている。
configs/default.yamlx0 loss、uniform timestep、condition dropout なし、短いキャプション、attn+mlp の LoRA、timestep/noise embedder、gen vision bridge、fm_head の部分 fine-tune という組み合わせだ。

データ配置は単純で、画像と同名の .txt キャプションを横に置く。
SETUP では、スタイル転写の作業範囲として 16〜256 枚を挙げている。
キャプションは画像内容を説明し、スタイル名は style.trigger として trainer 側が前に付ける。

README 側は少し進んでいて、paired folder だけでなく Parquet / Arrow shard も扱えるようになっている。
ただし Parquet は >= ~10k images のような大きいデータ向けで、最初の style LoRA では同名 .txt を置く flat folder のほうが扱いやすい。
---think--- 区切りで think label も入れられるが、default は use_think_labels: false。低品質な推論文が prefix を支配して style binding を壊す可能性があると書いている。

Anima 系でキャラ LoRA を焼いたときは、Danbooru タグと自然言語キャプションの混ぜ方がかなり問題になった。
WAI-Anima向けキャラLoRAの学習キャプションを書き直した記事でも、Qwen3 TE に方向情報を渡すためにキャプションを作り直した。
U1 trainer の説明もそこに近く、style そのものを各キャプションに書くのではなく、trigger と content のキャプションを分ける。

ただし、これは実験済みの便利 GUI ではない。
install 手順では、OpenSenseNova/SenseNova-U1 の modeling code を特定 commit df86ca90 に固定し、Hugging Face snapshot にコピーする。
trust_remote_code=True を使うため、trainer 側は sha256 を見て modeling file を検証してから上書きする構成になっている。

default の名前が2箇所で別の意味を持つ。
LoRA parser の default preset は公式8-step LoRAと同じ coverage に寄せる名前だが、configs/default.yaml が実際に使う preset は attn_mlp_no_headfm_head は LoRA ではなく full fine-tune surface として扱う。

見る場所実際の意味
configs/default.yamlsmall-data style baseline。LoRAはattn+mlp、fm_headなどはfull fine-tune
lora.preset: defaultattn+mlp+fm_headをLoRA化する coverage 名
official_r128公式8-step LoRA形状に寄せる r128 coverage

保存される trainable_state.safetensors も、単純な「どのUIにも投げられるLoRA」とは限らない。
lora_down / lora_up / .alpha の upstream LoRA naming に加えて、default では full fine-tune した plain parameter も同居する。
公式 examples/t2i/inference.py 系へ渡す前提なら筋が通るが、ComfyUI node や別UIが純粋なLoRA tripleだけを期待している場合は、keys と loader 側の対応を先に確認する。

公式training codeとは別の道具

OpenSenseNova/SenseNova-U1 本体では、2026年5月21日に full-parameter fine-tuning の training/ が公開されている。
この点だけ見ると、Laxhar README末尾の「upstream training code は未公開」という注記は、古い記述が残っているとみられる。

ただし、公式 training/README.md の最小構成はかなり重い。
出荷状態の shell/train_u1/8B.sh は 8枚の80GB GPU、A3B.sh は16枚の80GB GPUを前提にしている。
対応タスクも text-to-image、image editing、interleaved generation、OCR/VQA などの混合タスクで、checkpoint は internevo shard から Hugging Face 形式へ変換する流れになる。

公式 sample dataset も出ているが、これは各タスクの dataloader と loss code path を通すための smoke test で、学習用 corpus ではない。
つまり、公式training codeの公開は重要な更新だが、「32GB GPUで自分の小さい style LoRA を焼く」実用経路を直接置き換えるものではない。
Laxhar trainer は分散 full fine-tuning ではなく、公式推論形式へ落とすための単一GPU LoRA / partial-finetune 用ツールだ。

公式8-step LoRAの上に重ねられる

SenseNova U1 側では、2026年5月6日に公式の SenseNova-U1-8B-MoT-LoRA-8step-V1.0 が公開されている。
ベースモデルのカードでも、8 step、cfg_scale=1.0num_steps=8 で使う案内がある。

Laxhar の trainer には、この公式 8-step LoRA の上に自分の style LoRA を重ねる設定も入っている。
configs/stack_8step.yaml では、学習時に公式 8-step delta を bf16 base に bake-in し、fm_head は skip してから自分の LoRA を巻く。
サンプル時は同じ upstream LoRA を渡し、8 steps、CFG 1.0、timestep shift 3.0 で生成する流れだ。

Z-Image-Turboの蒸留を外してLoRA学習する話でも、蒸留済み高速モデルに LoRA を焼くと、少ないステップでの生成経路が崩れる問題が出ていた。
U1 trainer の 8-step stack は別の実装だが、扱う問題は近い。
公式 8-step LoRA に重ねると、対象のスタイルだけでなく、短い推論ステップ用の挙動も変わる。

ここはまだ比較できていない。
通常の default 学習と 8-step stack 学習で、同じ style dataset、同じ seed、同じ prompt を置き、50 step と 8 step の両方で比べないと、どこが壊れたのか分からなくなる。

A3B向けMoE指定は互換レイヤー扱い

モデルカードには A3B / MoE Status も書かれている。
gen_moe_mlpgen_moe_routermlp_mot_gen.experts.*.gate_proj のような LoRA target を指定できる実験的な grammar が入っている。

ただし、ここは安定した学習パスではない。
README では、安定対象は SenseNova-U1-8B-MoT のままで、A3B training は public MoE runtime support が対象 module を instantiate できることに依存すると明記している。
現時点の MoE 指定は、A3B で LoRA サイズを metadata から見積もる互換レイヤーだ。

ベースの SenseNova U1 カード側では、Lite series として 8B-MoT と A3B-MoT が並んでいる。
8B-MoT は dense backbone、A3B-MoT は MoE backbone。
同じ U1 系でも、LoRA をどの module に差すかは 8B と A3B で分岐する。

公式 training/ は A3B MoE の full-parameter training surface を持つが、これは16枚の80GB GPUを想定する分散学習の話だ。
それが出たからといって、Laxhar trainer の A3B LoRA grammar が単一GPUで安定動作する、という意味にはならない。

いま試すならRunPodの32GB以上が起点になる

手元の Mac や 24GB VRAM で軽く試す道具ではなさそうだ。
公式 README の線に沿うなら、32GB 以上の CUDA GPU、CPU RAM 64GB 以上、ディスク 80GB 以上を用意する。
Hugging Face snapshot だけで約17GBあり、checkpoint も残る。

自分の手元だと、まず RunPod の RTX 6000 Ada か A100 40GB で default.yaml をそのまま回す。
Blackwell の RTX 5090 は README 上の対象に入っているが、torch 2.9 と CUDA runtime の組み合わせ、cu128 wheel、bitsandbytes の対応まで揃えることになる。
以前 AnimaLoraToolkit で xformers が torch を cu130 に上げて Ada 環境を壊したので、この手の trainer は GPU 世代より Python/CUDA stack の固定を先に決める。

最初は、キャラ LoRA ではなく小さい画風 dataset を使う。
trainer 側のアブレーションは small style dataset を前提にしており、default もその条件で組まれている。
キャラの同一性、手足、顔の再現まで一気に評価すると、U1 trainer の問題なのか dataset の問題なのか切れにくい。

その前に確認するなら、次の順番になる。

確認項目見る理由
CUDA / torch / bitsandbytesRTX 5090 は cu128 wheel 前提になりやすい
trainable_state.safetensors の keypure LoRA ではなく full-FT param が混じる可能性を見る
default と 8-step stack の比較50 step向けと8 step向けの崩れ方を分ける
キャプションと triggerstyle をキャプションへ重複して焼かない
24GB環境デフォルトバケットの学習対象外、サンプル確認用と割り切る

まだ自分では実学習を回していないので、ピークVRAM約20GBや4/8-bit学習の崩れは README / SETUP の記述として扱っている。
特にキャラLoRAでの同一性、手足、顔の崩れ、8-step stack時の画風と高速推論の両立は未確認だ。

参考リンク