ホントにノイズからノイズを除去していくとキレイな画像が生成されるのか。これを今回は自分の目で確認してみましょう。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
前回はStable Diffusionとは何かと、Webページでその動作を確認しました。おおざっぱにいえば、Stable Diffusionとは「画像を生成するための訓練済みモデル」で、その動作原理は「純粋なノイズから、徐々にノイズを除去していき、最終的なきれいな画像を得る」というものでした。
というわけで、今回はこれがホントかどうかを目に見える形で確認することにしましょう。最初に答えを見せてしまうと、以下のような画像を得るのが目的です。その過程でDiffusersからStable Diffusionを使って、画像を生成する基本的なやり方を紹介していきます。
WindowsにStable Diffusion環境を構築するか、Google Colabを使用するかは悩みましたが、Google Colabのノートブックを公開しておけば、多くの方が実際にコードを動かして試してみることができるだろうということで、今回はGoogle Colabを使用しています。なお、無償版のGoogle Colabでは「ノートブックにはハイメモリが必要です」のようなメッセージが表示されたり、実際にメモリ不足で実行できなかったりするかもしれません。その場合は当たりの環境が割り当てられるまでがんばってみてください(かわさき)。
ノートブック内でPythonというプログラミング言語が使われていますが、単に実行するだけなので誰にでもできそうですね。コードの意味は以下の本文で分かりやすく説明されているのでPythonが初めてでも理解できると思います。自分でコードを書けるようになるための記事ではなく単に動かして挙動を確認するための記事なので、難しいと感じたら分からない部分はスキップして概要だけつかんでみるようにしてください。私の場合、手元でコードからStable Diffusionを実行できるだけでも感動しました(一色)。
DiffusersとはStable Diffusionをはじめとする「拡散モデル」による画像生成を数行のコードで行えるようにするフレームワークです。例えば、DiffusersにはStable Diffusionを簡単に使えるようにするためのStableDiffusionPipelineクラスが含まれていて、これを利用することで確かにほんの数行で画像を生成できるようになります。
とはいえ、その前にStable Diffusionのモデルを利用するためにHugging Faceと呼ばれるAIコミュニティーサイトに登録をして、Stable Diffusionのモデルにアクセスするための「トークン」と呼ばれる文字列を取得する必要があります。上記のURLにアクセスすると、以下のような画面が表示されるので、メールアドレスとパスワードを入力しましょう。
すると、次にユーザー名やフルネームなどのプロフィールを入力する画面が表示されます。
利用規約と行動規範をよく読んで[I have read and agree with the Terms of Service and the Code of Conduct]にチェックをして、[Create Account]ボタンをクリックすると、入力したメールアドレスに確認メールが届くのでリンクをクリックすれば登録は完了です。
この画面の上にある検索ボックスに「stable diffusion」などと入力すると、その下に「CompVis/stable-diffusion-v1-4」という選択肢が表示されるので、これをクリックします。すると、Stable Diffusionについて説明をしたページが表示されます。画面の上部には「このモデルにアクセスするにはコンタクト情報を共有する必要があります」というメッセージが表示されています。この欄を読み進めて、[I have read the License and agree with its terms]にチェックを入れて、[Access Repository]ボタンをクリックします。
次に自身の設定ページに移動して、[New Token]ボタンをクリックしてください。すると、以下のような画面が表示されるので、[Name]欄に「stable diffusion」などと入力して、[Generate a token]ボタンをクリックします。
これにより以下のように生成されたトークンが表示されます。
●文字で表示されたトークンの右端にある([Show]の右隣にある)[Copy token to clipboard]ボタンを押せば、トークンをコピーできます。これを使って、後でStable Diffusionのモデルにアクセスするようにコードを記述します。
ここまでくれば、Colabのノートブックにコードを記述する準備が完了です。といっても、今回は既に記述済みのノートブックのコードを見ていくことにしましょう。
Diffusersを使うには、通常「pip install diffusers」コマンドを実行するだけです(Google Colab環境でOSコマンドを実行する際には基本的に先頭に「!」が必要です)。そうなのですが、今回の処理ではPyPI経由でpipからインストールされるDiffusers 0.3.0ではうまくいきません。ちょっとしたバグがあり、GitHubではそれが既に修正されているので、そちらを利用することにしました。他にもtransformers、scipy、ftfyの各パッケージもインストールしています。
ライブラリのインストールができたら、さっそくコードを書いてみます。といっても、以降の内容は「Stable Diffusion with Diffusers」のままです。やることはほんのわずか。
以上です。これをコードにしたものが以下です。
import torch
from diffusers import StableDiffusionPipeline
YOUR_TOKEN = 'hf_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
pipe = StableDiffusionPipeline.from_pretrained('CompVis/stable-diffusion-v1-4',
use_auth_token=YOUR_TOKEN)
pipe.to('cuda')
prompt = 'a photograph of an astronaut riding a horse'
with torch.autocast('cuda'):
image = pipe(prompt).images[0]
image
最初の2行がtorchパッケージとStableDiffusionPipelineクラスのインポートです(実際には後の「with torch.autocast('cuda'):」がなければtorchパッケージのインポートは必要ないかもしれませんね。このwithブロックは計算で使用する浮動小数点数値の精度が異なっている場合に、精度を自動的にそろえてくれるものです)。
変数YOUR_TOKENには上で取得したトークンを代入しておきます。
その次の「pipe = StableDiffusionPipeline.from_pretrained('CompVis/stable-diffusion-v1-4', use_auth_token=YOUR_TOKEN)」行でパイプラインと呼ばれる仕組みを作っています。この第1引数に指定しているのが、Stable Diffusionのモデル本体です。そして、第2引数にはその上で設定しているトークンを指定します。その後の「pipe.to('cuda')」行は、作成したパイプラインをGPUに移すためのものです。
ここまでが画像生成の準備です。
そして、プロンプトとしてよく見られる「a photograph of an astronaut riding a horse」(馬に乗っている宇宙飛行士の写真)を設定しています。最後に「image = pipe(prompt).images[0]」行で画像を生成しています。この行のうち「pipe(prompt)」という作成したパイプラインを関数のように呼び出している部分で画像が生成されます。その次にある「.images[0]」は「pipe(prompt)」呼び出しの戻り値のうち、images属性にある先頭要素を取り出すものです。つまり、これがStabled Diffusionにより生成された画像となります(with文は既に述べた通り、浮動小数点数値の精度をそろえるための機構です)。
コード自体は確かにかなり少ない量ですが、ホントにこんな簡単に画像が生成できるのでしょうか。というわけで、以下に実行結果を示します。
それらしい画像が確かに生成されました。すばらしいですね。ちなみに上のコードは毎回別々の画像を生成しますが、設定を変えながら、同じ画像を生成するのであれば、前回と同様に乱数の初期値を固定します。コードでこれを行う場合には、torch.Generatorクラスのmanual_seedメソッドを使用します。
以下はその例です。
generator = torch.Generator('cuda').manual_seed(2)
image = pipe(prompt, guidance_scale=7.5, num_inference_steps=50,
generator=generator).images[0]
image
乱数のシードはgeneratorキーワード引数に指定します。promptは上と同様、生成される画像の指示で、guidance_scaleキーワード引数には前回にも出てきたプロンプトに対する忠実度で(大きいほどプロンプトに忠実になり、小さいほど生成される画像の多様性が大きくなる)、num_inference_stepsキーワード引数にはノイズ除去を行う回数を指定します。この他にも画像のサイズも指定できますが、それらについては次回に取り上げることにしましょう。
以下はこのコードの実行結果です。
ここまでDiffusersを使うことで、数行のコードで画像生成が行えることを見てきました。StableDiffusionPipelineクラスの__call__メソッドには、画像生成を行うための処理がまとめられていて、このクラスのインスタンスを関数のように呼び出すことで、このメソッドのコードが実行されるようになっています。興味のある方はソースコードを見てみると、結構な量のコードが書かれていることが分かるはずです。
こうしたコードを事前に定義することで、定型的で煩雑なコードを記述する必要をなくすのがDiffusersのよいところですね。
次に、純粋なノイズからノイズ除去を繰り返していくことで、上の画像がホントに生成されるのかを確認してみましょう。
Copyright© Digital Advantage Corp. All Rights Reserved.