ジャコ Lab

プログラミング関連のメモ帳的ブログです

Stable Diffusion の Seed はとりあえず設定しておくというマイブーム

Stable Diffusion を使うときに Seed という言葉が出てくると思います。この Seed は出力ごとに異なり、予め Seed を指定しておくことで (同じ条件であれば) 出力を固定することができます。

逆に Seed を指定しなければ、同じ条件でも、いつもランダムな出力になります。

今回は、この「ランダム出力」でも とりあえず Seed を設定しておこう というマイブームな記事です。

Seed(シード) とは?

一般的?に Seed 値 とは、乱数生成器における初期値として扱われます。

例えば、マイクラでもワールド生成時に同じ Seed 値を指定することで毎回同じワールドを生成することが可能です。

Stable Diffusion における Seed とは?

Stable Diffusion でも Seed というものが存在しており、同じ Seed 値を使用すれば、同じ出力を得ることができます。

但し、 同じ条件であれば です。

Stable Diffusion には Prompt 以外にも色々なプロパティがありますので、それらが全く同じであれば、同じ出力を得ることができます。条件が多少変わっても ある程度同じ系列 の出力を得ることができるようです。

以下の記事は、自分が Stable Diffuson を触り始めて3日目の記事になりますが、
初めて Seed 値の設定にチャレンジして、ほんの少し Prompt を変えただけで、全然違う見た目になってしまいました。

zako-lab929.hatenablog.com

どうせランダム出力するなら設定しなくていいじゃん?

出力するだけなら設定は不要です。でも後からこう思ったことはないでしょうか?

この絵いいな。。。でもシードがわからん。。。

そこで、例えランダムだとしても Seed を設定しておけば、 あとから Seed 値を調べることができる というわけです。

diffusers で Seed を設定するには?

今では、当たり前のように使っていますが、diffusers で利用する上では torch.Generator を使用します。

pipe(
    # ~省略~
    generator=torch.Generator().manual_seed(123)
)
こんな感じ

この 123 の部分をランダムにしたいわけです。

普通に乱数生成して設定しても良いけど

torch.Generator でランダムな値を設定するには?

pytorch.org

torch.Generator() で generator を生成できますが、これだけだとシード値が変わりません。

import torch

for idx in range(10):
    generator = torch.Generator()

    print(f"Seed: {generator.initial_seed()}")

# === 出力

Seed: 67280421310721
Seed: 67280421310721
Seed: 67280421310721
Seed: 67280421310721
Seed: 67280421310721
Seed: 67280421310721
Seed: 67280421310721
Seed: 67280421310721
Seed: 67280421310721
Seed: 67280421310721
しれっと使いましたがinitial_seed()で Generator が持つ Seed を得ることができるようです。

そこで以下のように1行追加します。

import torch

for idx in range(10):
    generator = torch.Generator()
    generator.seed() # この行を追加

    print(f"Seed: {generator.initial_seed()}")

# === 出力

Seed: 781032041376920943
Seed: 66879011613637603
Seed: 16742068809265919494
Seed: 7666320785904406628
Seed: 15713238966921772729
Seed: 2840743311707300618
Seed: 3446303502834378495
Seed: 1154777202747352886
Seed: 1743615981788055730
Seed: 376290463360427003
seed()で Generator が持つ Seed をランダムに変えることができます。

マイブームな実行コード

import torch

# シード設定
generator = torch.Generator()
generator.seed()

# プロンプト実行
image = pipe(
    # ~この記事では重要ではないので省略~
    generator=generator
).images[0]

(省略した部分はこちら)

# プロンプト実行
prompt = "1girl, japanese armor, white hair, purple eyes, sword, ((holding sword)), blue flames, glowing weapon, light particles, wallpaper, chromatic aberration"
negative_prompt = "(worst quality, low quality:1.4), (zombie, sketch, interlocked fingers, comic)"
image = pipe(
    prompt=prompt,
    negative_prompt=negative_prompt,
    num_inference_steps=28,
    guidance_scale=7,
    generator=generator
).images[0]

from datetime import datetime
from zoneinfo import ZoneInfo

# Asia/Tokyo タイムゾーンの現在時刻を YYYYMMDDhhmmss 形式で得る
formattedNow = datetime.now(tz=ZoneInfo("Asia/Tokyo")).strftime("%Y%m%d%H%M%S")

# 実行結果
image.save(f"{formattedNow}_{generator.initial_seed()}.png")

これで保存時に実行時刻とシードがファイル名に入ってます。

実行結果

シード値:12580151220004778540 の出力
シード値: 12580151220004778540

まとめ

初めて Stable Diffusion を diffusers 経由で触ってから3ヶ月くらい経ちましたが、
diffusers の扱いに慣れた気がします。

まだまだ動かせないことも多いので相変わらずではありますが。。。