ジャコ Lab

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

Easy Negative ってなに?diffusers(Google Colab) で使ってみる

興味を持ってググっていると新しいキーワードが次々と出てきますね。
今回は Easy Negative とやらを調べてみます。

どうやら、ネガティブプロンプトをいい感じに簡略化してくれるらしいです。

この情報も Web UI ばかりでてきます。
果たして diffusers ではどうやって使うのでしょうか?

Easy Negative とは?

ネガティブプロンプトをいい感じに簡略化してくれるものらしいです。
EasyNegative とネガティブプロンプトに入れるだけで効果があるらしいです。

diffusers でどうやって使うんだろう?

pipe.load_textual_inversion() ググっているとこの辺を使いそうではあります。
しかし、色々な使い方が引っかかりますね...

pipe.load_textual_inversion(
    "sayakpaul/EasyNegative-test", 
    weight_name="EasyNegative.safetensors", 
    token="EasyNegative"
)
!wget https://huggingface.co/datasets/gsdf/EasyNegative/resolve/main/EasyNegative.safetensors
pipe.load_textual_inversion(
    ".", 
    weight_name="EasyNegative.safetensors", 
    token="EasyNegative"
)
pipe.load_textual_inversion(
    "embed/negative", 
    weight_name="EasyNegativeV2.safetensors", 
    token="EasyNegative"
)

なんとなく、 インスタンス上にダウンロードするパターン
Hugging Face 上のモデル名を利用するパターン がありそうです。

このリファレンス を見ると、
第一引数は pretrained_model_name_or_path になっているので、
やはり「インスタンス上のパス」or「Hugging Face 上のモデル名」なのかな?と思います。

weight_name はファイル名かファイルパスでしょうか?
token はネガティブプロンプトに使う名前っぽいですね。

その他 Hugging Face 上には以下にもあるみたいです。
(むしろこちらが公式でしょうか?)

huggingface.co huggingface.co

sayakpaul/EasyNegative-test に関しては無くなっていそうです。

とりあえず使ってみよう

まずは Easy Negative 無し

zako-lab929.hatenablog.com

とりあえず上記の記事のプロンプトを使って、
ネガティブプロンプトは無しの画像を1個出力してみましょう。
シードは適当に固定してみます。

import os
from datetime import datetime
from zoneinfo import ZoneInfo

# ディレクトリを作成する (存在していてもエラーにはしない)
os.makedirs('outputs', exist_ok=True)

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

# プロンプト
prompt = "1girl, school uniform, ponytail, silver hair, wallpaper, landscape, depth of field, night, light particles, light rays, sidelighting, ****, open jacket, skirt"
negative_prompt = ""

# 画像を生成
generator = torch.Generator().manual_seed(123456789)
print(f"Seed: {generator.initial_seed()}")
image = pipe(
    prompt,
    negative_prompt=negative_prompt,
    generator=generator,
    width=768, height=512,
).images[0]
image

EasyNegative 無し

Easy Negative を使ってみる

  from diffusers import StableDiffusionPipeline
  import torch

  pipe = StableDiffusionPipeline.from_pretrained(
      "Meina/MeinaMix_V11",
      torch_dtype=torch.float16,
  ).to("cuda")

+ pipe.load_textual_inversion(
+     "embed/negative",
+     weight_name="EasyNegativeV2.safetensors", 
+     token="EasyNegative"
+ )
  import os
  from datetime import datetime
  from zoneinfo import ZoneInfo

  # ディレクトリを作成する (存在していてもエラーにはしない)
  os.makedirs('outputs', exist_ok=True)

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

  # プロンプト
  prompt = "1girl, school uniform, ponytail, silver hair, wallpaper, landscape, depth of field, night, light particles, light rays, sidelighting, ****, open jacket, skirt"
- negative_prompt = ""
+ negative_prompt = "EasyNegative"

  # 画像を生成
  generator = torch.Generator().manual_seed(123456789)
  print(f"Seed: {generator.initial_seed()}")
  image = pipe(
      prompt,
      negative_prompt=negative_prompt,
      generator=generator,
      width=768, height=512,
  ).images[0]
  image

EasyNegative 有り

元々高品質な画像が生成されるモデルということでしょうか?
構図が変わってしまったのでよくわからないですね!

でも、動きましたね!
パイプラインの準備が上手くできたということでしょうか!?

色々試してみる

gsdf/EasyNegative の EasyNegative.safetensors

huggingface.co

pipe.load_textual_inversion(
    "gsdf/EasyNegative",
    weight_name="EasyNegative.safetensors", 
    token="EasyNegative"
)

=> HTTPError: 401 Client Error: Unauthorized for url: https://huggingface.co/gsdf/EasyNegative/resolve/main/EasyNegative.safetensors
`embed/negative` との違いはよくわからないですが 401 エラーですね。
HF_TOKEN が必要なやつってことでしょうか?

gsdf/Counterfeit-V3.0 の EasyNegativeV2.safetensors

pipe.load_textual_inversion(
    "gsdf/Counterfeit-V3.0",
    weight_name="embedding/EasyNegativeV2.safetensors", 
    token="EasyNegative"
)

こちらは上手くいきましたね。
というか SHA256 が embed/negative と一緒なので、全く一緒の物なのでしょうね。

stabilityai/stable-diffusion-2-1 ではエラー

モデルを Meina/MeinaMix_V11 ではなく stabilityai/stable-diffusion-2-1 にしたら以下のエラーとなりました。

ValueError: Loaded embeddings are of incorrect shape. Expected each textual inversion embedding to be of shape {input_embeddings.shape[-1]}, but are {embeddings.shape[-1]}

runwayml/stable-diffusion-v1-5 では OK

runwayml/stable-diffusion-v1-5 では EasyNegative を用いたパイプラインの準備が出来たところを見ると
EasyNegativeV2 は Stable Diffusion 1.5 系統でしか使えない感じでしょうかね?

EasyNegative 無し (SD1.5) | EasyNegative 有り (SD1.5)

一番差がわかりやすいかも?

まとめ

diffusers で EasyNegative を使うときは load_textual_inversion() を使うみたいです!