colab stable diffusion

準備

NVIDIA準備

!nvidia-smi

このコマンドを実行すると、NVIDIA GPU の使用状況、メモリ使用量、プロセスの情報などを表示することができます。

!nvidia-smi は、NVIDIA GPU ドライバーと NVIDIA CUDA ツールキットをインストールしたコンピューター上で実行することができるコマンドです。

具体的には、GPU モデル、CUDA バージョン、プロセスの ID、GPU の使用率、メモリ使用量、電力消費量などが表示されます。このコマンドを使用することで、ディープラーニングや機械学習のモデルを実行する際に、GPU のリソース使用状況を確認することができます。

diffusersインストール

!pip install diffusers==0.11.1
!pip install transformers scipy ftfy accelerate

これらのコマンドは、Python パッケージをインストールするためのコマンドです。

!pip install diffusers==0.11.1

Diffusers というパッケージのバージョン 0.11.1 をインストールするコマンドです。Diffusers は、機械学習モデルをより安定させるためのノイズ注入技術を提供するパッケージです。

!pip install transformers scipy ftfy accelerate
Transformers は、自然言語処理のための深層学習モデルを提供するパッケージです。
Scipy は、科学技術計算のためのパッケージで、高度な数学的な演算や統計処理が可能です。
ftfy は、テキストデータのクリーニングや正規化を行うためのパッケージです。
Accelerate は、GPU を使用した高速化のためのパッケージです。

この4つのパッケージを一緒にインストールするコマンドです。

これらのパッケージは、機械学習や自然言語処理の開発において一般的に使用されるものであり、インストールすることで開発環境を整えることができます。

PyTorchインストール

import torch
from diffusers import StableDiffusionPipeline
pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4", torch_dtype=torch.float16)

このコードは、PyTorch と Diffusers パッケージを使用して、安定したディフュージョンプロセスを実行するためのパイプラインを定義するものです。

具体的には、CompVis/stable-diffusion-v1-4 というモデルを事前学習済みモデルとして使用しています。

このモデルを torch.float16 のデータ型で読み込んで、StableDiffusionPipeline クラスのインスタンスを生成し、変数 pipe に代入しています。

これにより、画像やテキストなどのデータに対して、安定したノイズ注入プロセスを実行することができるようになります。

CUDA準備

pipe = pipe.to("cuda")

このコードは、PyTorch のテンソルを GPU 上で処理するために、pipe パイプラインを CUDA デバイスに転送するためのものです。

to メソッドを使用して、引数に “cuda” を指定することで、パイプライン内のすべてのテンソルを CUDA デバイスに移動することができます。

pipe パイプラインを CUDA デバイスに転送することで、処理の高速化が期待できます。

出力

出力その1

# image here is in [PIL format]
# (https://pillow.readthedocs.io/en/stable/)
# Now to display an image you can either save it such as:
image.save(f”astronaut_rides_horse.png”)
# or if you’re in a google colab you can directly display it with

prompt = "a photograph of an astronaut riding a horse"
image = pipe(prompt).images[0]
image.save(f"astronaut_rides_horse.png")
image

このコードは、先程定義した pipe パイプラインに、”a photograph of an astronaut riding a horse” という文字列を入力して、その画像を生成するためのものです。

具体的には、pipe パイプラインの images 属性を使用して、生成された画像のリストの最初の要素を取得し、変数 image に代入しています。その後、この画像を PNG 形式で保存するか、Google Colab 上で直接表示することができます。

このコードは、Generative Adversarial Network (GAN) のような生成モデルを使用して、与えられた文章に対してそれに相応しい画像を生成するためのものです。Diffusion Model を使用することで、より安定した生成が可能となっています。

このような技術は、画像生成や画像処理の分野で広く利用されており、例えば商品の画像を生成する自動化されたシステムなどに応用されています。

出力その2シード値 1024

import torch
generator = torch.Generator("cuda").manual_seed(1024)
image = pipe(prompt, generator=generator).images[0]
image

このコードは、先程定義した pipe パイプラインに、”a photograph of an astronaut riding a horse” という文字列を入力して、その画像を生成するためのものです。また、生成に使用するランダムシードを、cuda 上の torch.Generator オブジェクトを使用して指定しています。

具体的には、シード値 1024 を引数にして、torch.Generator オブジェクトを作成しています。これにより、画像の生成に使用されるランダムシードが固定され、再現性を担保することができます。

ランダムシードは、ディープラーニングにおいて生成モデルやデータのシャッフル、学習時のノイズ注入などに使用されるため、重要な役割を果たします。

このように、生成に使用するランダムシードを固定することで、同じシード値を使用した場合には、生成される画像が再現可能となり、実験の再現性を高めることができます。

出力その3ステップ小さい

import torch
generator = torch.Generator("cuda").manual_seed(1024)
image = pipe(prompt, num_inference_steps=15, generator=generator).images[0]
image

3行目が少し違いますが、上記のコードとくらべて、どのような違いがありますか?

2つ目のコードと1つ目のコードの違いは、num_inference_steps 引数の値が異なることです。

2つ目のコードでは、num_inference_steps=15 として、Diffusion Model による推論ステップ数を 15 に設定しています。一方、1つ目のコードでは num_inference_steps 引数が指定されていませんので、デフォルト値である 1000 が使用されています。

Diffusion Model による画像生成において、推論ステップ数は生成される画像の品質に影響を与えます。

ステップ数が多い場合には、より高品質な画像が生成される可能性がありますが、一方で計算コストが高くなります。

ステップ数が少ない場合には、生成される画像の品質が低下する可能性がありますが、計算コストは低くなります。

出力その4グリッドの定義

from PIL import Image

def image_grid(imgs, rows, cols):
    assert len(imgs) == rows*cols

    w, h = imgs[0].size
    grid = Image.new('RGB', size=(cols*w, rows*h))
    grid_w, grid_h = grid.size
    
    for i, img in enumerate(imgs):
        grid.paste(img, box=(i%cols*w, i//cols*h))
    return grid

このコードは、生成された画像のリストを受け取り、それらをグリッド状に配置して、1枚の画像として結合するための関数 image_grid を定義しています。

具体的には、生成された画像のリスト imgs、グリッド状に配置する行数 rows、列数 cols を引数に取ります。この関数は、画像のサイズやグリッドのサイズを計算して、それらを結合した新しい画像 grid を作成します。

それぞれの画像を grid 上に配置するために、PIL.Image モジュールの paste メソッドを使用します。

この関数を使うことで、生成された画像を簡単にグリッド状に配置して可視化することができます。

出力その5

num_images = 1
prompt = ["a photograph of an astronaut riding a horse"] * num_images
images = pipe(prompt).images
grid = image_grid(images, rows=1, cols=1)
grid

これは1個しか出力していませんが。前述のコードにならって書いているものですか?

はい、このコードは前述のコードにならって書かれています。ただし、異なる点は、生成する画像の枚数を num_images で指定している点と、prompt に異なるテキストを指定している点です。ここでは num_images=1 として、1枚の画像を生成しています。

出力その6縦横合体画像

num_cols = 3
num_rows = 4

prompt = ["a photograph of an astronaut riding a horse"] * num_cols

all_images = []
for i in range(num_rows):
  images = pipe(prompt).images
  all_images.extend(images)

grid = image_grid(all_images, rows=num_rows, cols=num_cols)
grid

このコードは、指定された num_cols 列と num_rows 行のグリッド状に、同じテキスト「a photograph of an astronaut riding a horse」を指定して、画像を生成しています。

for ループで、各行ごとに num_cols 枚の画像を生成しています。生成されたすべての画像は all_images リストに格納され、最後に image_grid 関数を使用してグリッド状に並べられ、1枚の画像として結合されます。

生成された画像は、全て「a photograph of an astronaut riding a horse」の説明に基づいて生成された画像であり、グリッド状に並んでいます。

出力その7サイズ違い

prompt = "a photograph of an astronaut riding a horse"
image = pipe(prompt, height=512, width=768).images[0]
image

これは、画像の大きさを変えただけのコードですか?
はい、正確には、このコードは prompt で指定されたテキストに基づいて画像を生成し、 height と width パラメータを使用して、生成された画像のサイズを指定しています。

特に、height=512 と width=768 を指定しているため、生成された画像は、高さ512ピクセル、幅768ピクセルのサイズになります。