HuggingFace Diffusers 0.12 : API : パイプライン – 意味的ガイダンス (Colab 版) (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 03/23/2023 (v0.14.0)
* 本ページは、HuggingFace Diffusers の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- 人工知能研究開発支援
- 人工知能研修サービス(経営者層向けオンサイト研修)
- テクニカルコンサルティングサービス
- 実証実験(プロトタイプ構築)
- アプリケーションへの実装
- 人工知能研修サービス
- PoC(概念実証)を失敗させないための支援
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
- 株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
- sales-info@classcat.com ; Web: www.classcat.com ; ClassCatJP
HuggingFace Diffusers 0.12 : API : パイプライン – 意味的ガイダンス (Colab 版)
これは拡散モデルへの意味的ガイダンス (Sega) アプローチの実演です。Sega はテキスト-to-画像生成モデルにより保持されるコンセプトと相互作用することを可能にします。arXiv の論文と GitHub の公式実装をご覧ください。
最初に依存関係のインストール
# @title First install depencendies
!pip install git+https://github.com/ml-research/semantic-image-editing &> /dev/null
!pip install ftfy &> /dev/null
その後、インポートが有効になるようにノートブックを必ず再起動してください。
パイプラインのセットアップ
そして SemanticEditPipeline をロードします、これは [diffusers] DiffusionPipeline を継承しています。このパイプラインは任意の Stable Diffusion チェック・ポイントと互換です。
from semdiffusers import SemanticEditPipeline
import torch
device='cuda'
pipe = SemanticEditPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
safety_checker=None,
).to(device)
gen = torch.Generator(device=device)
インポートとユティリティ
後で必要なライブラリをインポートして、幾つかのユティリティ関数を定義します。
from PIL import Image
def image_grid(imgs, rows, cols, spacing = 20):
assert len(imgs) == rows * cols
w, h = imgs[0].size
grid = Image.new('RGBA', size=(cols * w + (cols-1)*spacing, rows * h + (rows-1)*spacing ), color=(255,255,255,0))
grid_w, grid_h = grid.size
for i, img in enumerate(imgs):
grid.paste(img, box=( i // rows * (w+spacing), i % rows * (h+spacing)))
#print(( i // rows * w, i % rows * h))
return grid
一般的なサンプル
続いて、論文で示されているサンプルを探求します。
以下は Fig. 1 で示されているすべてのサンプルです。これらは広範囲の SEGA のタスクと機能をカバーしています。
target = {'editing_prompt': 'crowd, crowded, people', 'reverse_editing_direction':True, 'edit_warmup_steps':10
, 'edit_guidance_scale':8.3, 'edit_threshold':0.9, 'edit_momentum_scale':0.5, 'edit_mom_beta': 0.6}
seed = 9
prompt = 'an image of a crowded boulevard, realistic, 4k'
gen.manual_seed(seed)
org = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7)
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7,
**target)
image_grid((org.images[0], out.images[0]), rows=1, cols=2)
target = {'editing_prompt': ['sunglasses'], 'reverse_editing_direction':[False],
'edit_warmup_steps':10, 'edit_guidance_scale':6, 'edit_threshold':0.95, 'edit_momentum_scale':0.5, 'edit_mom_beta': 0.6}
seed = 3
prompt = 'a photo of a cat'
gen.manual_seed(seed)
org = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7)
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7,
**target)
image_grid((org.images[0], out.images[0]), rows=1, cols=2)
target = {'editing_prompt': ['boat on a river, boat','monet, impression, sunrise'], 'reverse_editing_direction':False,
'edit_warmup_steps':[15,18], 'edit_guidance_scale':6, 'edit_threshold':[0.9, 0.8], 'edit_momentum_scale':0.5, 'edit_mom_beta': 0.6}
seed = 48
prompt = 'a castle next to a river'
gen.manual_seed(seed)
org = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7)
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7,
**target)
image_grid((org.images[0], out.images[0]), rows=1, cols=2)
target = {'editing_prompt': ['smiling, smile', 'makeup, heavy makeup, red lips, eye shadow', 'wearing hat, hat', 'female person', 'male person'],
'reverse_editing_direction':[True, False, False, False, True], 'edit_warmup_steps':8
, 'edit_guidance_scale':[0,4,6,3,7], 'edit_threshold':[0.95, 0.95, 0.95, 0.95, 0.95], 'edit_momentum_scale':0.5, 'edit_mom_beta': 0.6}
seed = 145
prompt = 'a photo of the face of a random person'
gen.manual_seed(seed)
org = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7)
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7,
**target)
image_grid((org.images[0], out.images[0]), rows=1, cols=2)
単調性
意味的コンセプトの大きさは意味的ガイダンス・ベクトルの強度に単調にスケールします。以下で意味的ガイダンス $s_e$ の強度を増やす効果を観察できます。ポジティブとネガティブ・ガイダンスの両方について、スケールの変化は笑顔や顰 (しか) め面の強さに相関しています。その結果、生成されが画像への任意の変更は意味的ガイダンス・スケール $e_$ とウォームアップ期間 $\delta$ だけを使用して直感的に誘導することができます。生成過程へのこのレベルの制御はまた、コンセプト毎の編集の望まれる強度の任意の組み合わせにより複数のコンセプトに対して適用可能です。
prompt = 'a photo of the face of a random person'
root = './data/face_attributes/'
seed = 7
images = []
for x in [10,6,3,1.5]:
target = {'editing_prompt': ['smile, smiling'], 'reverse_editing_direction':[True], 'edit_warmup_steps':10, 'edit_guidance_scale':x, 'edit_threshold':0.975, 'edit_momentum_scale':0.5, 'edit_mom_beta': 0.6}
gen.manual_seed(seed)
out = pipe(prompt, generator=gen, guidance_scale=7, num_images_per_prompt=1, **target)
images.extend(out.images)
gen.manual_seed(seed)
out = pipe(prompt, generator=gen, guidance_scale=7, num_images_per_prompt=1)
tmp = out.images[0]
images.extend(out.images)
for x in [1.5,3,6,10]:
target = {'editing_prompt': ['smile, smiling'], 'reverse_editing_direction':[False], 'edit_warmup_steps':10, 'edit_guidance_scale':x, 'edit_threshold':0.975, 'edit_momentum_scale':0.5, 'edit_mom_beta': 0.6}
gen.manual_seed(seed)
out = pipe(prompt, generator=gen, guidance_scale=7, num_images_per_prompt=1, **target)
images.extend(out.images)
image_grid(images, 1, len(images))
ベクトル算術
Fig 2 で示される Sega ベクトルを使用して king – male + female = Queen を実演します。
target = {'editing_prompt': ['male', 'female'],
'reverse_editing_direction':[True, False, False, False, True], 'edit_warmup_steps':5
, 'edit_guidance_scale':5, 'edit_threshold':0.9, 'edit_momentum_scale':0.5, 'edit_mom_beta': 0.6}
seed = 33
prompt = 'a portrait of a king, full body shot, 8k'
gen.manual_seed(seed)
org = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7)
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7,
**target)
image_grid((org.images[0], out.images[0]), rows=1, cols=2)
ガイダンス・ベクトルの堅牢性
描かれている例は SEGA がどのように (意味的に基礎となる) オリジナル画像への対象コンセプトのベストエフォートな統合を抽出するかを示しています。これは SEGA の使用を容易にし、初期画像生成と同じ探索的な (exploratory) 性質を提供します。
images = []
target = {'editing_prompt': ['glasses'], 'reverse_editing_direction':[False], 'edit_warmup_steps':15, 'edit_guidance_scale':5, 'edit_threshold':0.99, 'edit_momentum_scale':0.35, 'edit_mom_beta': 0.6}
seed = 5
prompt = 'a photo of the face of a gorgeous woman'
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7)
images.extend(out.images)
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7,
**target)
images.extend(out.images)
target = {'editing_prompt': ['glasses'], 'reverse_editing_direction':[False], 'edit_warmup_steps':12, 'edit_guidance_scale':7, 'edit_threshold':0.98, 'edit_momentum_scale':0.35, 'edit_mom_beta': 0.6}
seed = 2
prompt = 'a photo of a corgi'
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7)
images.extend(out.images)
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7,
**target)
images.extend(out.images)
target = {'editing_prompt': ['glasses'], 'reverse_editing_direction':[False], 'edit_warmup_steps':12, 'edit_guidance_scale':5, 'edit_threshold':0.975, 'edit_momentum_scale':0.35, 'edit_mom_beta': 0.6}
seed = 2
prompt = 'a photo of a flowerpot'
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7)
images.extend(out.images)
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7,
**target)
images.extend(out.images)
target = {'editing_prompt': ['glasses'], 'reverse_editing_direction':[False], 'edit_warmup_steps':10, 'edit_guidance_scale':8.5, 'edit_threshold':0.85, 'edit_momentum_scale':0.5, 'edit_mom_beta': 0.6}
seed = 11
prompt = 'a photo of a frog'
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7)
images.extend(out.images)
gen.manual_seed(seed)
out = pipe(prompt=prompt, generator=gen, num_images_per_prompt=1, guidance_scale=7,
**target)
images.extend(out.images)
image_grid(images, rows=2, cols=int(len(images)/2))
ガイダンス・ベクトルの一意性
一つのコンセプトのガイダンス・ベクトル $\gamma$ は一意で、従って一度計算すれば続けて他の画像にも適用できます。以下で生成された画像は、左端の画像上で ‘glasses’ の意味的ガイダンスを計算してそのベクトルを他のプロンプトの拡散過程で追加した例を示しています。すべての顔は、それぞれ必要な $\epsilon$-推定なしで、眼鏡をかけて生成されます。フォトレアリズムから線画 (drawings) への切り替えで見られるように、これは大幅なドメインシフトさえカバーします。
prompt = 'a photo of the face of a random person'
root = './images/uniqueness/glasses/'
other_prompts = [
'a photo of the face of a girl',
'a photo of the face of an actor',
'A photo of a person, in the style of a cartoon, drawing',
'a photo of the face of a boy',
'a photo of the face of Emma Watson',
'a photo of the face of the president',
]
target = {'editing_prompt': ['glasses'], 'reverse_editing_direction':[False], 'edit_warmup_steps':12, 'edit_guidance_scale':7, 'edit_threshold':0.95, 'edit_momentum_scale':0.35, 'edit_mom_beta': 0.6}
i = 2
images = []
gen.manual_seed(i)
out = pipe(prompt, generator=gen, guidance_scale=7, num_images_per_prompt=1)
images.extend(out.images)
gen.manual_seed(i)
out = pipe(prompt, generator=gen, guidance_scale=7, num_images_per_prompt=1, **target)
images.extend(out.images)
sem_guidance = pipe.sem_guidance
for prompt in other_prompts:
#images = []
if 'Emma' in prompt or 'Jonny' in prompt:
scale = 3
else:
scale = 7
gen.manual_seed(i)
out = pipe(prompt, generator=gen, guidance_scale=scale, num_images_per_prompt=1)
images.extend(out.images)
gen.manual_seed(i)
out = pipe(prompt, generator=gen, guidance_scale=scale, num_images_per_prompt=1, sem_guidance=sem_guidance)
images.extend(out.images)
image_grid(images, 2, int(len(images)/2))
ガイダンス・ベクトルのアイソレーション
異なるコンセプトは大きく離れています、何故ならば各コンセプト・ベクトルはトータルのノイズ推定の断片だけを必要とするからです。つまり、異なるベクトルは互いに干渉しません。そのため、以下で示されるように、複数のコンセプトは同じ画像に同時に適用できます。例えば、最初に加えられた眼鏡が、続く追加の編集で変化のないままであることが分かります。We can utilize this behavior to perform more complex changes, best expressed using multiple concepts.
seed = 21
prompt = 'a photo of the face of a woman'
images = []
gen.manual_seed(seed)
out = pipe(prompt, generator=gen, guidance_scale=7, num_images_per_prompt=1, )
images.extend(out.images)
target = {'editing_prompt': ['smiling, smile', 'glasses, wearing glasses', 'curls, wavy hair, curly hair', 'beard, full beard, mustache'], 'reverse_editing_direction':False, 'edit_warmup_steps':10
, 'edit_guidance_scale':[0,5,0,0], 'edit_threshold':[0.99, 0.975, 0.925, 0.96], 'edit_momentum_scale':0.3, 'edit_mom_beta': 0.6}
gen.manual_seed(seed)
out = pipe(prompt, generator=gen, guidance_scale=7, num_images_per_prompt=1, **target)
images.extend(out.images)
target = {'editing_prompt': ['smiling, smile', 'glasses, wearing glasses', 'curls, wavy hair, curly hair', 'beard, full beard, mustache'], 'reverse_editing_direction':False, 'edit_warmup_steps':10
, 'edit_guidance_scale':[6,5,0,0], 'edit_threshold':[0.99, 0.975, 0.925, 0.96], 'edit_momentum_scale':0.3, 'edit_mom_beta': 0.6}
gen.manual_seed(seed)
out = pipe(prompt, generator=gen, guidance_scale=7, num_images_per_prompt=1, **target)
images.extend(out.images)
target = {'editing_prompt': ['smiling, smile', 'glasses, wearing glasses', 'curls, wavy hair, curly hair', 'beard, full beard, mustache'], 'reverse_editing_direction':False, 'edit_warmup_steps':10
, 'edit_guidance_scale':[6,5,5,0], 'edit_threshold':[0.99, 0.975, 0.925, 0.96], 'edit_momentum_scale':0.3, 'edit_mom_beta': 0.6}
gen.manual_seed(seed)
out = pipe(prompt, generator=gen, guidance_scale=7, num_images_per_prompt=1, **target)
images.extend(out.images)
target = {'editing_prompt': ['smiling, smile', 'glasses, wearing glasses', 'curls, wavy hair, curly hair', 'beard, full beard, mustache'], 'reverse_editing_direction':False, 'edit_warmup_steps':10
, 'edit_guidance_scale':[4,5,5,5.4], 'edit_threshold':[0.99, 0.975, 0.925, 0.96], 'edit_momentum_scale':0.3, 'edit_mom_beta': 0.6}
gen.manual_seed(seed)
out = pipe(prompt, generator=gen, guidance_scale=7, num_images_per_prompt=1, **target)
images.extend(out.images)
image_grid(images, 1, len(images))
以上