kohya-ss/sd-scriptsで貞光のLoRAを作ったので作り方とか

ご存知ない?

今をときめく、というより専ら「seoulシリーズ」のフロムソフトウェアが初代XBOXというハードの限界に挑んでた時の隠れた名作O・TO・GI-御伽-を!

名作なのはO・TO・GI 百鬼討伐なんだが*1、OTOGIシリーズ

名作たる所以は、破壊の爽快感と独特の浮遊感

その辺の木々、岩、壁など、フィールドオブジェクトをバンバン破壊しまくれる。 妖鬼を切り飛ばし投げ飛ばし叩きつけるとピンボールのように跳ねながら辺を破壊していく爽快感。

背景美術がきれいだからその破壊がなおのこと映える

空中戦闘ができるが、AC4系のように飛行しているのとは違って重力を感じる浮遊感。 例えるなら海中のような重力。

ふわふわ浮かびながら下降中のライコウの超ロン毛や貞光の振り袖がヒラヒラする様子は何者にも代えがたい美しさがある

でも、売れなかった

ソウルライクのようなOTOGIライクなアクションゲームも生まれなかった*2

2023年できれいなグラフィックスで見劣りしないアクションゲームを作るとなると開発リソースがとんでもない事になりそう

空前絶後のゲーム

無いなら作るよ! OTOGILoRA!

売れてない知られてないって事はファンアートもなく、Stable diffusionに学習されてもいないということ

俺がやれねば誰がやる

試行錯誤の連続の記録である

まずはクリアする

XBOX Series Xを買う

が、買った後にXでなくてもダウンロード販売があるので買わなくても良かったかもと思った

初代XBOXが壊れて久しいので楽しくプレイ

4Kアップスケールと自動HDRでキレイになるが、OTOGIらしさはちょっと減ってる

カメラ操作が標準反転してるのでやりにくいので、XBOX側の設定で右スティックは反転にするとすごく快適になる

プレイ画面は全録。 XBOX Series デフォルトの保存先では保存時間が短いからUSBメモリーにキャプチャーを保存

学習素材と考えると自動HDRは録画された画像は明るさがおかしいので、学習画像用に保存するときはHDRはOFFで

学習元画像の準備

一周二周クリアしたる後

学習したいシーンに当たりをつけて、録画

そしてバッチ処理で動画を1フレームごとに画像化

4K解像度60fpsの画像集は長い映像で使うととんでもない容量を食うので1本あたり2、3分程度に抑えておきたい

@echo off
setlocal enabledelayedexpansion

REM カレントディレクトリ内の動画ファイルに対して処理を行う
for %%F in (*.mp4) do (
    REM 動画ファイル名から拡張子を除いた名前を取得
    set "filename=%%~nF"

    REM 画像保存用のフォルダを作成
    mkdir "!filename!"

    REM FFmpegを使用して動画から画像ファイルを作成
    ffmpeg -i "%%F" -vcodec png "!filename!\image_%%06d.png"
)

endlocal

学習元画像の準備

画像があるので厳選せず、厳密なタグ付けをせず学習させた結果

バリバリ過学習のガビガビ画像になったがライコウの鎧が複雑すぎて特徴を掴みきれていない

動きのない画像を出してもOTOGIではない

お手本

タグの整備は丁寧に

GitHub - toshiaki1729/dataset-tag-editor-standalone: WebUI to edit dataset captions for txt2img models

ざっくり説明すると覚えてほしくないもの、明らかに間違ったものは消す

こだわりタグ編集でなくてもいい感じになったりもするのでざっくり編集でテストを回すのもいいかも

消すタグ

自動でタグ付けしてくれはするが、当然そのまま使えるものじゃない*3

覚えさせたい特徴を示すタグと明らかに間違ったタグ*4は消す

例えばOTOGIには絶対出て来ないmotorcycleとか

逆に残すのは似ているが覚えてほしくない特徴を、振り袖や狩衣の場合 「dress」とか

トリガーワード

トリガーワードはトークン数の少ない短くベースモデルが覚えていない単語がいいとされる

これは漢字が普通に使える

トークン数は増える*5がベースモデルはまず覚えていない単語だから

追加するタグ

画風

3Dのゲーム画面から学習させようって場合 「depth of field, blurry background, 3d」

OTOGIの場合*6モーションブラー多用して派手に見せてる演出多いので、ほぼ全ての画像に必要

構図

Looking Away | Danbooru

キャラLoRAの場合は必須

覚えさせたいキャラであって構図ではない

碓氷貞光を作ろう

ガビガビLoRAのを作ったりしながら一つの気づく

ライコウの鎧って超難しくない?

難易度低そうな貞光からやろう

他の奴ら見た目が人間じゃなかったり、鎧が複雑だったり

消したタグ

black hair, forehead, parted bangs, hair tubes, sidelocks,forehead mark 貞光の前髪、額の印

hair rings, ponytail 貞光の後ろ髪

作るのは画風LoRAから

最初は貞光の画像だけで学習させていたが、OTOGIのモデルやエフェクトごと再現される

貞光ではあるが汎用性はない

その問題を回避するためには、OTOGIのスクショを大量に学ばせた画風LoRAを作りベースモデルにマージの後に貞光を学ばせるという手法を取る

dim・rank・次元数/ alpha・アルファ

学習率の関係がまあ良くわからない

alphaは1でという話だが、オプティマイザーDAdaptationの推奨学習率は1前後とされてる

そうするとアンダーフローというLoRAの持つ値が全てゼロになってlossがNaNとなり真っ暗真っ黒の画像を吐き出すゴミがデッキる

学習率をガッツリ下げたがなんか行けそうな気がするやつになった

{
  "train_type": 1,
  "v2": false,
  "v_parameterization": false,
  "network_module": "networks.lora",
  "network_args": "",
  "network_dim": "64",
  "network_alpha": "1",
  "num_cpu_threads_per_process": "16",
  "max_data_loader_n_workers": "16",
  "persistent_data_loader_workers": false,
  "train_batch_size": "8",
  "cross_attention": "xformers",
  "lowram": false,
  "pretrained_model_name_or_path": "H:\\animefull-latest.ckpt",
  "vae": "",
  "tokenizer_cache_dir": "",
  "train_data_dir": "H:\\lora\\lora_train_data\\train_dir",
  "reg_data_dir": "",
  "in_json": "H:\\lora\\otogi_v02\\marge_clean.json",
  "caption_extension": ".txt",
  "network_weights": "",
  "resume": "H:\\lora\\otogi_v02\\02-08\\otogi_v02-08-state",
  "output_dir": "H:\\Git\\SDWebUISet\\lora_DIR",
  "output_name": "otogi_v02-081",
  "save_model_as": "safetensors",
  "save_precision": "fp16",
  "logging_dir": "H:\\lora\\otogi_v02\\log",
  "log_prefix": "otogi_v02-081",
  "output_config": true,
  "no_metadata": false,
  "save_state": true,
  "save_last_n_epochs_state": "1",
  "save_last_n_steps_state": "",
  "training_comment": "fsotogi_02-081",
  "resolution": "512,512",
  "enable_bucket": true,
  "min_bucket_reso": "256",
  "max_bucket_reso": "1024",
  "bucket_reso_steps": "64",
  "bucket_no_upscale": false,
  "cache_latents": false,
  "cache_latents_to_disk": false,
  "vae_batch_size": "1",
  "color_aug": true,
  "flip_aug": true,
  "random_crop": true,
  "use_face_crop": false,
  "face_crop_aug_range": "2.0,4.0",
  "max_train_mode": 1,
  "max_train_steps": "7000",
  "max_train_epochs": "10",
  "save_every_n_epochs": "",
  "save_n_epoch_ratio": "10",
  "save_last_n_epochs": "",
  "save_every_n_steps": "",
  "save_last_n_steps": "",
  "prior_loss_weight": "1.0",
  "dataset_repeats": "10",
  "train_block": 0,
  "learning_rate": "1e-1",
  "unet_lr": "",
  "text_encoder_lr": "",
  "max_grad_norm": "1.0",
  "seed": "23",
  "clip_skip": "2",
  "noise_offset": "0.1",
  "min_snr_gamma": "5",
  "lr_scheduler_type": "",
  "lr_scheduler_args": "",
  "lr_scheduler": "cosine_with_restarts",
  "lr_warmup_steps": "100",
  "lr_scheduler_num_cycles": "2",
  "lr_scheduler_power": "1",
  "gradient_checkpointing": true,
  "gradient_accumulation_steps": "4",
  "mixed_precision": "fp16",
  "full_fp16": false,
  "optimizer_type": "DAdaptation",
  "optimizer_args": "",
  "multires_noise_iterations": "",
  "multires_noise_discount": "",
  "max_token_length": "75",
  "shuffle_caption": true,
  "keep_tokens": "1",
  "weighted_captions": true,
  "caption_dropout_rate": "0.0",
  "caption_tag_dropout_rate": "0.1",
  "caption_dropout_every_n_epochs": "1",
  "sample_every_mode": 2,
  "sample_every_n_steps": "100",
  "sample_every_n_epochs": "1",
  "sample_prompts": "H:\\lora\\otogi_v02\\otogisample_v02.txt",
  "sample_sampler": "euler_a"
}

O・TO・GI-御伽- 百鬼討伐絵巻 - fromsofutowea XBOX - otogi_v02-081 | Stable Diffusion LoRA | Civitai

ベースモデルにマージ

GitHub - hako-mikan/sd-webui-supermerger: model merge extention for stable diffusion web ui

ここでもマージ比率とか階層マージとか試行錯誤の余地はあるんだろうけど、まだ良くわからない

とりあえずOTOGILoRAで生成するとx0.6あたりでいい感じで効いてるような気がする

OK貞光だ

目論見通りOTOGIのスクショ感は消え貞光の特徴は捉えた

お手本

{
  "train_type": 1,
  "v2": false,
  "v_parameterization": false,
  "network_module": "networks.lora",
  "network_args": "",
  "network_dim": "124",
  "network_alpha": "1",
  "num_cpu_threads_per_process": "16",
  "max_data_loader_n_workers": "16",
  "persistent_data_loader_workers": false,
  "train_batch_size": "8",
  "cross_attention": "xformers",
  "lowram": false,
  "pretrained_model_name_or_path": "H:\\NAI-otogiv02-081_v02.fp16.safetensors",
  "vae": "",
  "tokenizer_cache_dir": "",
  "train_data_dir": "H:\\lora\\lora_train_data\\train_dir",
  "reg_data_dir": "",
  "in_json": "H:\\lora\\sadamitsu_v04\\marge_clean.json",
  "caption_extension": ".txt",
  "network_weights": "",
  "resume": "",
  "output_dir": "H:\\Git\\SDWebUISet\\lora_DIR",
  "output_name": "sadamitsu_v04-05",
  "save_model_as": "safetensors",
  "save_precision": "fp16",
  "logging_dir": "H:\\lora\\sadamitsu_v04\\log",
  "log_prefix": "sadamitsu_v04-05",
  "output_config": true,
  "no_metadata": false,
  "save_state": true,
  "save_last_n_epochs_state": "10",
  "save_last_n_steps_state": "",
  "training_comment": "sadamitsu_v04-05_貞光,-OHsadamitsu-sadamitsu-1girl",
  "resolution": "512,512",
  "enable_bucket": true,
  "min_bucket_reso": "256",
  "max_bucket_reso": "1024",
  "bucket_reso_steps": "64",
  "bucket_no_upscale": true,
  "cache_latents": false,
  "cache_latents_to_disk": false,
  "vae_batch_size": "1",
  "color_aug": true,
  "flip_aug": true,
  "random_crop": false,
  "use_face_crop": false,
  "face_crop_aug_range": "2.0,4.0",
  "max_train_mode": 1,
  "max_train_steps": "7000",
  "max_train_epochs": "100",
  "save_every_n_epochs": "",
  "save_n_epoch_ratio": "100",
  "save_last_n_epochs": "",
  "save_every_n_steps": "",
  "save_last_n_steps": "",
  "prior_loss_weight": "1.0",
  "dataset_repeats": "10",
  "train_block": 0,
  "learning_rate": "5e-1",
  "unet_lr": "",
  "text_encoder_lr": "",
  "max_grad_norm": "1.0",
  "seed": "23",
  "clip_skip": "2",
  "noise_offset": "0.1",
  "min_snr_gamma": "5",
  "lr_scheduler_type": "",
  "lr_scheduler_args": "",
  "lr_scheduler": "cosine_with_restarts",
  "lr_warmup_steps": "100",
  "lr_scheduler_num_cycles": "2",
  "lr_scheduler_power": "1",
  "gradient_checkpointing": true,
  "gradient_accumulation_steps": "4",
  "mixed_precision": "fp16",
  "full_fp16": false,
  "optimizer_type": "DAdaptation",
  "optimizer_args": "",
  "multires_noise_iterations": "",
  "multires_noise_discount": "",
  "max_token_length": "75",
  "shuffle_caption": false,
  "keep_tokens": "4",
  "weighted_captions": false,
  "caption_dropout_rate": "0.0",
  "caption_tag_dropout_rate": "0.1",
  "caption_dropout_every_n_epochs": "1",
  "sample_every_mode": 2,
  "sample_every_n_steps": "100",
  "sample_every_n_epochs": "1",
  "sample_prompts": "H:\\lora\\sadamitsu_v04\\sadamitsu_v04_v03testprompt.txt",
  "sample_sampler": "euler_a"
}

着せ替えもできる*7

参考

note.com

note.com

終わり

リスペクトとかは分からないが、少し嫌悪感は共感した*8

*1:御伽はまだ見せ方が手探りで慣れてない時なのか百鬼プレイ後にやるとあまりOTOGIっぽくないと感じた

*2:知ってるならぜひとも教えて、お礼に焼肉おごってもいい

*3:タグ付けモデルの偏りでめっちゃ出るよ東方キャラ

*4:自動タグ付け機能でダークソウルのスクショとかダークタワーのスクショとか出てくるのは消すべきか消さざるべきか迷ったが消す

*5:増えると学習時間も増えるという話

*6:他の古い3Dゲームもそうかも

*7:マイナーな衣装とかと絡めた汎用性は確かめてない

*8:その嫌悪感も罪悪感もいずれ薄れゆく。 この世は夢か現かそれに善悪などあろうものか