Stable Diffusion を使うときに Seed という言葉が出てくると思います。この Seed は出力ごとに異なり、予め Seed を指定しておくことで (同じ条件であれば) 出力を固定することができます。
逆に Seed を指定しなければ、同じ条件でも、いつもランダムな出力になります。
今回は、この「ランダム出力」でも とりあえず Seed を設定しておこう というマイブームな記事です。
- Seed(シード) とは?
- Stable Diffusion における Seed とは?
- どうせランダム出力するなら設定しなくていいじゃん?
- diffusers で Seed を設定するには?
- マイブームな実行コード
- まとめ
Seed(シード) とは?
一般的?に Seed 値 とは、乱数生成器における初期値として扱われます。
例えば、マイクラでもワールド生成時に同じ Seed 値を指定することで毎回同じワールドを生成することが可能です。
Stable Diffusion における Seed とは?
Stable Diffusion でも Seed というものが存在しており、同じ Seed 値を使用すれば、同じ出力を得ることができます。
但し、 同じ条件であれば です。
Stable Diffusion には Prompt 以外にも色々なプロパティがありますので、それらが全く同じであれば、同じ出力を得ることができます。条件が多少変わっても ある程度同じ系列 の出力を得ることができるようです。
以下の記事は、自分が Stable Diffuson を触り始めて3日目の記事になりますが、
初めて Seed 値の設定にチャレンジして、ほんの少し Prompt を変えただけで、全然違う見た目になってしまいました。
どうせランダム出力するなら設定しなくていいじゃん?
出力するだけなら設定は不要です。でも後からこう思ったことはないでしょうか?
そこで、例えランダムだとしても Seed を設定しておけば、 あとから Seed 値を調べることができる というわけです。
diffusers で Seed を設定するには?
今では、当たり前のように使っていますが、diffusers で利用する上では torch.Generator を使用します。
pipe( # ~省略~ generator=torch.Generator().manual_seed(123) )
この 123
の部分をランダムにしたいわけです。
torch.Generator でランダムな値を設定するには?
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")
これで保存時に実行時刻とシードがファイル名に入ってます。
実行結果
まとめ
初めて Stable Diffusion を diffusers 経由で触ってから3ヶ月くらい経ちましたが、
diffusers の扱いに慣れた気がします。
まだまだ動かせないことも多いので相変わらずではありますが。。。