世の中でのびのびと生きていると、
たまに、難しい課題をこなさなくてはならないときがあります。
たとえば、あれです。
全然知らんリポジトリを使って、こう、「いい感じにやってくれ」、という時などがあります。
「ローカルでFlux.1のLoRAをしてほしい。
SimpleTuner、試してみて」
「なんすかそれ?」
「えーっとね、これ」
「……? えーっと、なん、ですか?」
「README.mdが、これね」
「あの……」
「どうしたの?」
「『SimpleTunerを使ってみました!手順は以下の通りです(コピペで済む、完璧な手順)。設定が足りなかったので、足しました(どうしてそこをいじれば解決するのかがわかったのかはまるでわからないが、なんか良い感じになる設定)いかがでしたか?』日本語ブログみたいな、ものは……」
「ないね~、あ、これ、今日のお給料のどんぐり」
「……。…………。ハイ!」
ないが、ないんだけど、ないよぉ~、日本語の情報がないよ~、うおえっ(嗚咽)ごえっ(嗚咽)えええん(嗚咽)。
目的
今回の目的は、画像生成AI、Flux.1[dev]のLoRAを作成し、適用することです。
(ネタバレ:最終的に、SimpleTunerを動かせはしましたが、いったんFluxGymで行いました。)
SimpleTuner
SimpleTunerは画像生成AIのファインチューニングをお手軽に行うためのコードや、ツール群をまとめたリポジトリのようです。Qiitaには1件、海外のYoutuberのアップロードした動画がいくつか、という感じでした。
カンカンカンカン(警鐘)。
ざっとリポジトリのドキュメントを読みましたが、TutorialにはThis tutorial is a work-in-progress.
とか書かれてるし、Quickstart Guideはもっとそっけない。
まずは、INSTALL.mdを読みつつ、これをすべてChatGPTに投げ込み、適宜アドバイスを求めます。
ただし、ChatGPTはこういう、新しめの便利ツール群に詳しいわけではないので、話は半分くらいにして聞くことにしてください。
git clone --branch=release https://github.com/bghira/SimpleTuner.git
cd SimpleTuner
# if python --version shows 3.11 you can just also use the 'python' command here.
python3.11 -m venv .venv
source .venv/bin/activate
pip install -U poetry pip
# Necessary on some systems to prevent it from deciding it knows better than us.
poetry config virtualenvs.create false
ここまでは……大丈夫。
# MacOS
poetry install -C install/apple
# Linux
poetry install
# Linux with ROCM
poetry install -C install/rocm
えーっと、今日はLinuxだから……。
なんだ、Linux with ROCMってなんだ。知らない言葉を使うな。
えーっと、調べてみたら、GPU向けソフトウェアらしい?
たぶん、ない。
最適化に関することっぽいので、このへんはあとあと考えていくことにします。
# Linux
poetry install
poetryのインストールが、一生終わらない
このpoetryのインストールが一生終わらないんです……(一敗)。
おしまいだ、と思ってふてくされて寝ようと思いましたが
-
poetry cache list
でキャッシュの一覧を表示 poetry cache clear --all [キャッシュ名]
でうまくいくという情報をみかけたので、やってみたらうまくいくようになりました。
ここでpip install poetory -vvv
で詳細を確認し、問題がありそうなパッケージを手動でなんとかして、ちょっと回り道をしました。キリがない。
poetry installやpoetry lockが動かない場合の対処法
あと、「poetry update が一生終わらない」というエントリがヒットしてそれはそれとしてみんな一生終わらないんだと思って元気をもらいました。
俺たちのpoetryは、もう一生終わらない。ここで一生、みんなで朽ちていこうな、と思ったんですが、解決したので、毛糸球を片手に女装しながらこのミノタウロスの迷宮に足を踏み入れていきたい。うそ。出たい。もういやだ。
続きは……。
……。
え~っとね~。
なんか、そのまま、ファインチューニングのトレーニングが始まりそうな気配があったので、いったんおしまいにしましょう。
今回のファインチューニングのターゲットはFluxなので、FLUX専用のドキュメントに移ります。
いったん、小さいゴールを作ってビバーク(とりあえず、モデルをダウンロードして、画像を1枚出す)
タスクがやばいくらいビクともしない場合、そして「おしまいだ……」と思った場合、何かしら騙されています。レベルが高すぎる。セーブポイントをつくらなきゃなりません。
「ファインチューニングの前に、ファインチューニングしてないモデルで画像を出す」というステップを踏みましょう。
これに気が付くまで、「エーン書いてある通りにやってるつもりなのに、学習できないよ~(レバガチャ)」してました。
まず、モデルをダウンロードします。
FLUXのモデルが置いてあるのは、Huggingfaceなので、Huggingfaceにログインします。
huggingface-cli login
huggingface-cli download black-forest-labs/FLUX.1-dev --local-dir=flux-base
こういうエラーが返ってきました。
huggingface_hub.errors.LocalEntryNotFoundError: An error happened while trying to locate the file on the Hub and we cannot find the requested files in the local cache. Please check your connection and try again or make sure your Internet connection is on.
あび~~~~~~~~~おしまいだ~~~~~~~~~~~~~~~~~~~~おしまいだ~~~~~~~~~~。
おしまいになりかけましたが、冷静に確認してみましょう。
FLUXは同意が必要なモデルです。
ふー……。
それはOK。ちゃんとファイルが見れる状態になっています。
HuggingFaceでトークンの発行で権限が足りなかったので権限を足してやります。
すると、ダウンロードできました。
ChatGPTをたたき起こして、「画像を出すスクリプトを書いて」と言いつけます。
すると、ChatGPTは、スクリプトを書いてくれはしましたが、どうもローカルモデルのパスを指定していそうではない。
こちらにはすでに「flux1-dev.safetensors」が存在するんですが、
HuggingFaceにログインして、モデルをどうこうしようとしています。
「違う。そうじゃない。ローカルにあるから、それでやってくれ」と言っても、ぜんぜん書いてくれません。
しかし、一つの手がかりを得ました。どうもdiffusers
の、DiffusionPipeline
を使用するようです。これを手掛かりにして調べて、以下のコードを書きました。
import torch
from diffusers import DiffusionPipeline
import time
# モデルのロード
print("Loading model...")
pipe = DiffusionPipeline.from_pretrained(
"./flux-dev", # ローカルモデルのパス。
torch_dtype=torch.float16 # GPU向けの軽量化
)
pipe.enable_model_cpu_offload() # モデルの一部をCPUにオフロード
# GPUにモデルを転送(GPUが利用可能な場合)
if torch.cuda.is_available():
pipe = pipe.to("cuda")
print("Model loaded to GPU.")
else:
print("CUDA is not available. Using CPU.")
# プロンプトの指定
prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
# 画像生成の開始
print(f"Generating image for prompt: {prompt}")
start_time = time.time()
image = pipe(
prompt=prompt,
guidance_scale=7.5, # 画像生成の指示強度
num_inference_steps=20 # ステップ数(多いほど品質向上)
).images[0]
end_time = time.time()
print(f"Image generated in {end_time - start_time:.2f} seconds.")
# 画像を保存
output_path = "output.png"
image.save(output_path)
print(f"Image saved to {output_path}.")
以下のエラーが出ました。
torch.OutOfMemoryError: CUDA out of memory. Tried to allocate 32.00 MiB. GPU 0 has a total capacity of 23.54 GiB of which 14.50 MiB is free.
メモリが、足りなかった、ああ……。
README.md的には、それほど大きい画像を生成させようとしなければ、RTX 4090でなんとかなるはずではあります。
泣きながら飲んだくれていたところでふと思い出します。
FLUXには、軽いモデルがある。
devではなくて、schnellというバージョンが。
ただし、のちほど教えてもらったのですが、schnellはファインチューニングには向きません。
ただ、この作業で得たいものは、「ダウンロードしてきたFluxモデルで、画像が生成できた」というステップです。
"./flux-schnell", # ローカルモデルのパス。
としました。
何度かコードを修正し、繰り返すと、ようやく画像を出すことができました。
ああああああああああああああああああああああああああああああああああああああああああああああああ!!!!!!!!!!!!!!!!!!!!!!!
ああああああああああああああ……。
うっ……あが……。
得た……成果を……。
ファインチューニング(Flux Gym)
こんどはsh train.pyが通りません。
どうしようかと強い人に泣きついたところ、「難しすぎるからコッチにしなよ」とFlux Gymを紹介してもらいました。
うわあああああああああああああああああああああああああああ
ああああああああああああああああああああああああああああああああああああああああああああああああああああ。
一週間悩んでいたことが一時間で、できた。
(そして、FluxGymのほうだと、なんか普通にFlux.1[dev]が動いた。)
教訓:目的を見失ってはいけない
(やりたいのは、あくまでFluxのファインチューニングであって、SimpleTunerをどうこうすることではない。)
ところが、これで得たものをいざ使うとなるとどうなるのか、やっていかなくてはならなくなりました。つまり、さっきまでの取り組みは無駄ではありませんでした。
さきほどの、テスト用プロンプトを使用できました。
SimpleTunerを薄眼で見て、toolkitがあるらしいこと、なんとなくの手順がなんとなく察せられます。
また、私がナントカ.safetensorsがほぼほぼ本体で、Clipとか、vaeとか、なんとなくそんなフォルダがありそうなことを知っているのはちょっと前にComfyUIを触っていたからです。
「うおおおおっ、全部動かすぞ!!!」というのも、論文を読むのも、概念を理解するのも、ほんとうにほんとうに大切なことですが、ちょっとずつ砕いて動かしてかないと何もわからないし頭に入らない人間はビバークしつつ進んでいくしかない。あと強い人には感謝しよう。