電通総研 テックブログ

電通総研が運営する技術ブログ

Stable Diffusion入門-長い呪文は切り捨てられる

電通国際情報サービス、オープンイノベーションラボの比嘉康雄です。 Stable Diffusionシリーズ、今回は、長い呪文は切り捨てられる編です。

からあげさんのStable Diffusionの内容を理解するための情報・書籍の記事の中に出てくる最初の75個分以降の文章は、バッサリ捨てられてしまう記事をみて、自分でも検証してみたのが今回の記事です。

これまで、意味のある区切りとして、カンマ(,)を使っていたのですが、カンマ(,)は75個のトークンの一つとして重複して数えられ、カンマ(,)を削っても出力結果はほとんど変わらないことを知って愕然としました。

Stable Diffusionのおすすめコンテンツはこちら。

tokenizer

呪文をトークンに分解するには、tokenizerを作成します。必要なライブラリは次のようにインストールします。今回は、Notebookの例です。

!pip install transformers ftfy regex

tokenizerの作成は次のように行います。

from transformers import CLIPTokenizer

tokenizer = CLIPTokenizer.from_pretrained("openai/clip-vit-large-patch14") 

呪文をトークンに分解するには、次のように行います。

prompt = "anime of beautiful girl, detailed beautiful face, detailed hair, detailed perfect pupil of eyes, detailed cute mouth, detailed shoulders, detailed bust"
tokens = tokenizer.tokenize(prompt)
print(len(tokens), tokens[0:tokenizer.model_max_length-2])

トークン出力結果(改行版)

37
['japanese</w>',
'anime</w>',
'of</w>',
'beautiful</w>',
'girl</w>',
',</w>',
'detailed</w>',
'beautiful</w>',
'face</w>',
',</w>',
'detailed</w>',
'hair</w>',
',</w>',
'detailed</w>',
'perfect</w>',
'pupil</w>',
'of</w>',
'eyes</w>',
',</w>',
'detailed</w>',
'cute</w>',
'mouth</w>',
',</w>',
'detailed</w>',
'shoulders</w>',
',</w>',
'detailed</w>',
'bust</w>']

37のトークンに分解されたことがわかります。',</w>'に注目してください。これは、カンマ(,)です。カンマ(,)もトークンの一つにカウントされていることがわかります。

僕が実験した限り、カンマ(,)ありなしで、出力される結果に違いはありません。75個を超えるトークンは切り捨てられることを考えると、カンマ(,)は呪文に含めないのが良いでしょう。

75個を超えるトークンは切り捨てられるのか

それでは、本当に「75個を超えるトークンは切り捨てられるのか」実験してみましょう。

下記のようなちょうど75個のトークンの呪文を用意します。

prompt = "illustration of a beautiful girl, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,"
tokens = tokenizer.tokenize(prompt)
print(len(tokens), tokens[0:tokenizer.model_max_length-2])
image = pipe(prompt)["sample"][0]
image

トークン出力結果(改行版)

75 
['illustration</w>',
'of</w>',
'a</w>',
'beautiful</w>',
'girl</w>',
',</w>',
省略
',</w>']

確かに呪文は、75個のトークンで構成されていますね。この呪文の最後に以下の呪文を追加しましょう。75個を超えるトークンが切り捨てられるなら、結果に影響はないはずです。

追加する呪文(改行版)

deviantart,
concept art,
digital painting,
award-winning,
cinematic postprocessing,
cinematic scene,
cinematic composition,
cinematic lighting,
overexpose,
ray tracing,
8k

トークン出力結果(改行版)

109
['illustration</w>',
'of</w>',
'a</w>',
'beautiful</w>',
'girl</w>',
',</w>',
省略
',</w>']

結果に影響はなかったですね。75個を超えるトークンが切り捨てられることが確認できました。

呪文のカンマを削っても出力結果に影響はないのか

今度は、呪文のカンマを削っても出力結果に影響がないのかを検証してみましょう。

今回の呪文は、 美少女を高確率で出す呪文編で使った呪文の改良版です。

今回の呪文(横長、コピー&ペースト用)

illustration of a beautiful girl, detailed beautiful face, detailed hair, detailed perfect pupil of eyes, detailed mouth, detailed shoulders, detailed bust, looking far away, shot diagonally, artstation, deviantart, concept art, digital painting, award-winning, cinematic postprocessing, cinematic scene, cinematic composition, cinematic lighting, overexpose, ray tracing, 8k

閲覧用呪文(改行版)

illustration of a beautiful girl,
detailed beautiful face,
detailed hair,
detailed perfect pupil of eyes,
detailed mouth,
detailed shoulders,
detailed bust,
looking far away,
shot diagonally,
artstation,
deviantart,
concept art,
digital painting,
award-winning,
cinematic postprocessing,
cinematic scene,
cinematic composition,
cinematic lighting,
overexpose,
ray tracing,
8k

改良したのは、detailed perfect pupil of eyesとdetailed shouldersの二箇所です。 イラストなら、前回の呪文でも大丈夫なのですが、写真で試すと目や腕が変になることがあったので改良しました。

目は、detailed beautiful eyesをdetailed perfect pupil of eyesに変えました。

腕は、detailed armsをdetailed shouldersに変えました。腕は変になりやすいので、指定しないほうが無難なようです。肩を指定することで腕が出力される回数が減りました。

トークン出力結果(改行版)

74 
['illustration</w>','of</w>','a</w>','beautiful</w>','girl</w>',
',</w>',
'detailed</w>','beautiful</w>','face</w>',
',</w>',
'detailed</w>','hair</w>',
',</w>',
'detailed</w>','perfect</w>','pupil</w>','of</w>','eyes</w>',
',</w>',
'detailed</w>','mouth</w>',
',</w>',
'detailed</w>','shoulders</w>',
',</w>',
'detailed</w>','bust</w>',
',</w>',
'looking</w>','far</w>','away</w>',
',</w>',
'shot</w>','diag', 'on', 'ally</w>',
',</w>',
'art','station</w>',
',</w>',
'deviantart</w>',
',</w>',
'concept</w>','art</w>',
',</w>',
'digital</w>','painting</w>',
',</w>',
'award</w>','-</w>','winning</w>',
',</w>',
'cinematic</w>','post','processing</w>',
',</w>',
'cinematic</w>','scene</w>',
',</w>',
'cinematic</w>','composition</w>',
',</w>',
'cinematic</w>','lighting</w>',
',</w>',
'ove', 'rex', 'pose</w>',
',</w>',
'ray</w>','tracing</w>',
',</w>',
'8</w>','k</w>']

画像出力結果

既にトークンの数は74(Max 75)。これ以上、詳細な指定ができなくなるのは問題です。出力結果を見ながら呪文を改良していきましょう。

',</w>'は削れますね。

a beautiful girlのaも削れます。girlを見れば単数であることがわかるからです。僕の試した限りはtheも削ることができます。

diagonallyが、'diag', 'on', 'ally</w>'と3つに分かれて認識されています。これは、Stable Diffusionがdiagonallyという単語を認識できていないことを示しています。

この結果を見てdiagonallyが無効だと判断するのは早計です。Stable Diffusionは、ワードでない(</w>がついていない)連続したトークンを有効だと認識していることもあるからです。例えば、pixivは、'pi', 'xiv</w>'と別れていますが、pixivあり/なしで、出力結果は変わってきます。つまり、pixivの呪文は有効だということです。

ワードでない(</w>がついていない)連続したトークンは、あり/なしで何度も試しましょう。効果があると確信できるときだけ、呪文として採用しましょう。shot diagonally(斜めに撮影する)は、何度も試した結果効果が確信できなかったので、不採用にしました。

同様にワードでない(</w>がついていない)連続したトークンの'ove', 'rex', 'pose</w>'も不採用にしました。

award-winningは、'award</w>', '-</w>', 'winning</w>'に分解されていたので、真ん中の '-</w>'は不要と判断し、award winningにすることにしました。

改良版の呪文(横長、コピー&ペースト用)はこちらになります。

illustration of beautiful girl detailed beautiful face detailed hair detailed perfect pupil of eyes detailed mouth detailed shoulders detailed bust looking far away artstation deviantart concept art digital painting award winning cinematic postprocessing cinematic scene cinematic composition cinematic lighting ray tracing 8k

改良版の閲覧用呪文(改行版)

illustration of beautiful girl
detailed beautiful face
detailed hair
detailed perfect pupil of eyes
detailed mouth 
detailed shoulders 
detailed bust 
looking far away 
artstation 
deviantart 
concept art 
digital painting 
award winning 
cinematic postprocessing 
cinematic scene 
cinematic composition 
cinematic lighting 
ray tracing 
8k

トークン出力結果(改行版)

45 
['illustration</w>', 'of</w>', 'beautiful</w>', 'girl</w>', 
'detailed</w>', 'beautiful</w>', 'face</w>', 
'detailed</w>', 'hair</w>', 
'detailed</w>', 'perfect</w>', 'pupil</w>', 'of</w>', 'eyes</w>', 
'detailed</w>', 'mouth</w>', 
'detailed</w>', 'shoulders</w>', 
'detailed</w>', 'bust</w>', 
'looking</w>', 'far</w>', 'away</w>', 
'art', 'station</w>', 
'deviantart</w>', 
'concept</w>', 'art</w>', 
'digital</w>', 'painting</w>', 
'award</w>', 'winning</w>', 
'cinematic</w>', 'post', 'processing</w>', 
'cinematic</w>', 'scene</w>', 
'cinematic</w>', 'composition</w>', 
'cinematic</w>', 'lighting</w>', 
'ray</w>', 'tracing</w>', 
'8</w>', 'k</w>']

画像出力結果

トークンの個数が74から45に圧縮されました。画像のクオリティは変わっていないことが確認できると思います。

まとめ

今回は、75個を超えるトークンは、切り捨てられることを確認しました。

さらに、呪文を圧縮するテクニックとして、カンマ(、)を削る、ワードでない(</w>がついていない)連続したトークンが有効かどうかをチェックすることを学びました。

次回は、蒸気機関が高度に発達したレトロなアニメ(スチームパンク)の世界観編です。

仲間募集

私たちは同じグループで共に働いていただける仲間を募集しています。
現在、以下のような職種を募集しています。

Stable Diffusionの過去コンテンツ

執筆:@higaShodoで執筆されました