【Stable Diffusion】seed固定による同じ画像の作成

【Stable Diffusion】seed固定による同じ画像の作成 機械学習

「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固定による画像作成の検証を説明しました。

タイトルとURLをコピーしました