「Stable Diffusionで作成される画像が毎回変わるのは困る・・・」
「Stable Diffusionのtxt2imgでseedを固定したい」
このような場合には、この記事の内容が参考になります。
この記事では、seedを固定して同じ画像を作成する方法を解説しています。
本記事の内容
- seedとは?
- seed固定で画像作成を行う方法
- seed固定による画像作成の検証
それでは、上記に沿って解説していきます。
seedとは?
Stable Diffusionは、機械学習をベースにした画像生成技術です。
機械学習において、seedは再現性を考えた場合に重要な値と言えます。
seedは、次のように表現される場合があります。
- 乱数シード
- 疑似乱数
このseedが、Stable Diffusionにおいても重要な値となっています。
Stable Diffusionで画像を作成した場合、作成される画像が毎回異なりませんか?
実は、これもseedが関係しています。
seedが毎回異なるため、作成される画像もその都度変わることになります。
基本的に、機械学習ではseedは毎回変わるのが普通です。
そして、Stable Diffusionもその考え方がデフォルトになっています。
しかし、これでは都合が悪い場合も出てきます。
Stable Diffusionで言えば、prompt(呪文)の検証を行う場合です。
呪文の精度を上げようと頑張っている場合に、コロコロと絵の内容が変わるのは邪魔でしかないです。
ちょっとした形容詞や単語の追加が、どう影響を及ぼすのかわかりません。
つまり、根本から絵の内容が変わると調整した内容の影響度を測れないのです。
したがって、再現性を求める場合にはseedは固定することになります。
seedを固定すれば、Stable Diffusionでも同じ絵を作成することが可能になります。
そして、呪文の精度を上げるための作業ができるようになります。
さらには、guidance_scaleやnum_inference_stepsの調整も可能となります。
以上、seedについて説明しました。
次は、seed固定で画像作成を行う方法を説明します。
seed固定で画像作成を行う方法
seed固定で画像作成を行う方法を解説していきます。
前提として、次の記事の内容は済みとします。
すでにStable Diffusionを実行できる環境があるということです。
そして、「Diffusersを用いた方法」でStable Diffusionが動くことも条件になります。
別の言い方をすると、「txt2img.py」スクリプトをコマンドで実行する方法ではないということです。
「txt2img.py」スクリプトを使う方法だと、seedを固定することが簡単にできます。
「txt2img.py」のヘルプでも、次のようにオプションが説明されています。
--seed SEED the seed (for reproducible sampling)
ここまでの内容が理解できれば、次へ進みましょう。
早速ですが、以下はseedを固定した場合のコードになります。
import torch from diffusers import StableDiffusionPipeline from torch import autocast import datetime MODEL_ID = "CompVis/stable-diffusion-v1-4" DEVICE = "cuda" YOUR_TOKEN = "コピーしたアクセストークン" PROMPT = "a dog painted by Katsuhika Hokusai" SEED = 1000 pipe = StableDiffusionPipeline.from_pretrained(MODEL_ID, revision="fp16", torch_dtype=torch.float16, use_auth_token=YOUR_TOKEN) pipe.to(DEVICE) # seed固定 generator = torch.Generator(device=DEVICE).manual_seed(SEED) with autocast(DEVICE): image = pipe(PROMPT, guidance_scale=7.5, generator=generator)["sample"][0] # 現在時間 dt_now = datetime.datetime.now() now = dt_now.strftime("%Y%m%d%H%M%S") # ファイル名 file_path = str(SEED) + "_" + str(now) + ".png" # ファイル保存 image.save(file_path)
参考の記事におけるコードを改良しています。
ポイントは、以下の部分です。
SEED = 1000 ~省略~ # seed固定 generator = torch.Generator(device=DEVICE).manual_seed(SEED) ~省略~ image = pipe(PROMPT, guidance_scale=7.5, generator=generator)["sample"][0]
上記コードにより、seed固定を実現しています。
コードの内容がわからない場合は、上記記事をご覧ください。
以上、seed固定で画像作成を行う方法を説明しました。
次は、seed固定による画像作成の検証を説明します。
seed固定による画像作成の検証
まず、上記コードをそのまま2回連続で実行します。
※もちろん、アクセストークンは各自で取得した値を設定する
実行すると、同じディレクトリ上に次のような名前のファイルがありませんか?
1000_20220904064711.png 1000_20220904064814.png
1000_以降は、異なる数字(処理日時)になっているはずです。
そして、その画像の絵は次のようなモノではありませんか?
seed=1000
もしかしたら、実行マシンによって絵の内容が異なる可能性はあるかもしれません。
ただ、1000_で始まる画像は2つとも同じ絵のはずです。
これは確実に同じだと言えます。
では、次にseedを変更してみましょう。
コード上で次のように変更するだけです。
SEED = 1001
そして、2回実行します。
今回は、1001_で始まる画像が2つ作成されます。
1001_20220904064957.png 1001_20220904065142.png
絵の内容は、先ほどの画像とは異なります。
これは、seedを変更した結果です。
seed=1001
そして、1001_で始まる画像は2つとも同じ絵になります。
ここまでの検証により、seedの役割について実感できたと思います。
以上、seed固定による画像作成の検証を説明しました。