🖼️

Stable Diffusionのインストール手順書(GCP版)

2022/09/06に公開

Stable Diffusionの関連ブログがあちこちに量産されていますね。実際のサービスにどう落とし込みマネタイズするか、色々なアイデアが浮かびそうです。
この記事では機械学習をやったことのないエンジニアを想定した、GCPのGCE(ディープラーニングVM)を使用した手順書になります。

Stable Diffusionとは、プロンプトと称するテキストから画像を生成するAIです。CompVis, Stability AI, LAIONの研究者、エンジニアによって開発されました。 Stability AIのEmadがTwitterで活発に情報発信しています。

サーバ環境

GCPでディープラーニングVMインスタンスを作成します。次のマシンスペックで動きます。

Debian GNU/Linux 10 (Debian以外を指定できない)
NVIDIA Tesla T4 x 1 (月額3万円ほど)
n1-standard-2 (これ以下のスペックだとメモリ不足で動きません)
CUDA11.3 (自動インストール)
Python 3.10.4 (あとでpyenvで入れる)

GCPの管理コンソール > GCE > インスタンスの作成 > マーケットプレース からインスタンスを作成します。deep learning vmで検索します。Deep Learning VMを選択します。

マシンタイプをGPUにし、Tesla T4を選択します。GPUのところにチェックを入れるとNVIDIAのドライバーもインストールしてくれます。右側に概算見積もりが出ます。くれぐれも桁を見間違えないように注意してください。また、ドル建てですので為替(円安ドル高)の影響を受けます。

数分でインスタンスの作成が完了します。以下、SSHでログインして作業しましょう。

Python環境

pyenvpipenvでやります。

SSLが無いとか色々怒られますので入れておきます。

sudo apt-get update
sudo apt install libedit-dev
sudo apt-get install make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

あとは通常のpyenvとpipenvのインストールになります。

git clone https://github.com/pyenv/pyenv.git ~/.pyenv
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc

再ログインしてパスを反映させます。

インストールします。結構遅いです。(2, 3分ほど)

pyenv install 3.10.4
pyenv global 3.10.4
pip install pipenv

ライブラリーのインストール

Pipfileになります。

Pipfile
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
torch = "*"
diffusers = "*"
transformers = "*"
scipy = "*"

[dev-packages]

[requires]
python_version = "3.10"

インストールします。

pipenv shell
pipenv install

Huggingfaceのサンプルコードを動かす

Huggingfaceのライブラリを使用してStable Diffusionを動かします。

ブログにカスタマイズ方法など説明してありますので読んでおくと良いでしょう。

https://huggingface.co/blog/stable_diffusion

ライブラリを使用するためにはHuggingfaceのサイトで以下の3つの手順を済ませておく必要があります。

  1. Huggingfaceサイトでアカウントの作成
  2. レポジトリの使用許諾契約に同意
  3. トークンの払い出し

以上を済ませたら、pipenvのバーチャル環境から作業を進めます。

huuggingfaceへのログインをします。

huggingface-cli login

プロンプトが返りますので、先ほど払い出したトークンをタイプします。

Token: (上の3番で払い出したトークンをタイプ。エコーバックしません。)
Login successful
Your token has been saved to /home/(xxx)/.huggingface/token

赤色のエラーメッセージっぽいのが表示されますが問題ないです。

Authenticated through git-credential store but this isn't the helper defined on your machine.

Huggingfaceからコピってきた次のコードを作成します。

sd.py
import torch
from torch import autocast
from diffusers import StableDiffusionPipeline

model_id = "CompVis/stable-diffusion-v1-4"  # 噂のSDの学習モデル
device = "cuda"

# メモリが10GB以上ある人は、torch_dtypeとrevisionを削ってください。
pipe = StableDiffusionPipeline.from_pretrained(model_id, use_auth_token=True, torch_dtype=torch.float16, revision="fp16")
pipe = pipe.to(device)

# この文字列が噂のプロンプトになります。お好みのフレーズに変えて遊んでください。
# 『馬に乗っている宇宙飛行士の写真』
prompt = "a photograph of an astronaut riding a horse"  

with autocast("cuda"):
    image = pipe(prompt, guidance_scale=7.5)["sample"][0]

image.save("astronaut_rides_horse.png")  # 完成した画像

いよいよ実行です!

初回は学習モデル等のダウンロードで少し時間がかかります。2回目以降は14秒ほどで画像を生成できます。

$ python sd.py 
Downloading: 100%|
...
51it [00:14,  3.57it/s]

このような出力がされればOKです。🎉

無事終了すると完成した画像がastronaut_rides_horse.pngという名前で出力されます。
プロンプトを変えたりして遊んでください。

補足

下記のエラーが出た場合はメモリー不足(10GB GPU RAM)なのでfloat16版を使用してください。

RuntimeError: [enforce fail at alloc_cpu.cpp:73] . DefaultCPUAllocator: can't allocate memory: you tried to allocate 117964800 bytes. Error code 12 (Cannot allocate memory)

プロンプトが同じでも実行するたびに違う画像が生成されます。固定したい場合は固定のシードを使用します。

generator = torch.Generator("cuda").manual_seed(1024)
image = pipe(prompt, guidance_scale=7.5, generator=generator)["sample"][0]

推論のステップ数を変えたい場合はnum_inference_stepsにセットします。デフォは50です。少なくすれば早く終わりますが精度は悪くなります。開発時はステップ数を減らして開発効率を上げます。

num_inference_steps
image = pipe(prompt, guidance_scale=7.5, num_inference_steps=15, generator=generator)["sample"][0]

また閲覧注意な画像NSFW(Not Safe For Work)と判定されると真っ黒な画像になります。

Potential NSFW content was detected in one or more images. A black image will be returned instead. Try again with a different prompt and/or seed.

複数の画像の生成

一度に複数の画像を生成したいときは、配列で渡します。

sd_multi.py
import torch
from torch import autocast
from diffusers import StableDiffusionPipeline
from PIL import Image

model_id = "CompVis/stable-diffusion-v1-4"
device = "cuda"

pipe = StableDiffusionPipeline.from_pretrained(model_id, use_auth_token=True, torch_dtype=torch.float16,
                                               revision="fp16")
pipe = pipe.to(device)

# 配列で複数のプロンプトを渡します。
prompts = [
    "Visual Novel, robots, battle, 4k",
    "Artstation, by Yoshitaka Amano, Visual Novel",
    "Visual Novel, high scool, girls, pool side"
]

# 複数の画像を1つのpngにグリッド表示する
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))

    for i, img in enumerate(imgs):
        grid.paste(img, box=(i % cols * w, i // cols * h))
    return grid


with autocast("cuda"):
    images = pipe(prompts, guidance_scale=7.5, num_inference_steps=50)["sample"]
    g = image_grid(images, rows=1, cols=3) # 1列3行で表示。数合わせしてください。

g.save("astronaut_rides_horse.png")

プロンプトについて

アニメっぽいのを出したい人は、Visual Novelという単語を使用すると出ます。4kを付けると、綺麗な画像になります。
こちらのサイトでプロンプトを探ることができます。

Discussion