Home Creators Posts Import Register Favorites Logout

Content

 コラム? コラムです。


 一部で話題になっているStable Diffusionを試してみたので、スーパー走り書きですが、コラムという名の手順を残しておきます。(もっと充実した手順がいっぱい出てくると思うけど)

 ※Stable Diffusionについての詳細は割愛するよ! 検索してね!


 ITよわよわな人向けに書いたので、スクショ多めにしました。

 (若干冗長なので、詳しい人は詳しい人向けの記事を読んだ方がいいかも)

 手順にNSFWフィルターの除去(ぽろり)も含まれてますが、諸々自己責任で。


 理解の浅い状態で書いた記事が広い範囲に公開されるのがちょっと嫌だったので、一旦コラムとして公開してますが、もし精査するやる気が出たら、他のブログとかに転記するかも。


 なお、手順は2022/08/24時点のもので、ソースコードのバージョンが変わると使えなくなる可能性が高い。特にNSFWフィルターの除去は、ソースコードを直接書き換えているので整合が取れなくなる可能性が高いので注意。


*


 ちなみに、Stable Diffusionがどんな感じなのか軽く試したい場合は、デモやDreamstudioを使うとよし。


デモ版

https://huggingface.co/spaces/stabilityai/stable-diffusion

DreamStudio

https://beta.dreamstudio.ai


 興味が出たら、Colabに構築するともう少し長く試せるよっていう話。

 ただ、お金に余裕がある人は、Dreamstudioのクレジットを購入するのが一番楽で良いと思う。ただし、NSFWっぽい画像が出力されると問答無用で除外されてしまうのだけは、自前で環境構築しない限り、避けられない。


*


 Stable Diffusionは分かるけどColabってなんぞやという人のために知らない人に簡単に説明を書くと、Google ColabはPaaSの一種。

 つまり、クラウド上で動く、用途が限定された仮想マシンのようなもの。

 制約はあるものの無料で、Pythonの実行やGPUの利用ができる。

 (ちなみに僕も、Colabは今回初めて使った)


 つまり、自前でStable Diffusionを動かしてみたいけど、おうちに要件を満たすGPU(グラフィックボード)を持ってない人が、気軽にインストールして色々と試せる環境ってわけ。

 ブラウザがあれば動くから、どこからでも動かせるっていうのも強い。

 ちなみに、つよつよなGPUを持ってる人は、ローカルに構築した方がもっと実用的に使えると思う。


 注意点として無料版のColabでは、90分操作しない状態が続いたり、12時間経過したりすると、自動的にランタイム(仮想マシン)の状態がリセットされる。そうなると環境が初期化されてしまうので、そのたびに2. 構築編/インストールの手順を実行する必要がある。

 (使ったコマンドやソースコードは、セルと呼ばれるテキストボックス(?)に残って再実行できるので、2回目からは実行ボタンをぽちぽちするだけで再構築できる。慣れると10分もかからないで終わる)


1. 準備編

 (1) Hugging Faceでトークンを取得する

  ・アカウントの作成

  ・トークンの発行

  ・モデルへのアクセス権の取得

2. 構築編

 (1) ノートブックの作成

  ・ノートブックの新規作成

  ・ランタイムの設定

 (2) インストール

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

  ・NSFWフィルターの無効化

  ・モデルの適用

 (3) 動作確認

  ・プロンプトの実行


【前提】

※Googleアカウントは取得済みの状態を想定しています

(サブアカウントを持ってる人は、なんとなくサブを使った方がいいかも)

※手順の作成環境は、iPad proです。

(ブラウザが対応してれば動くよ)

【準備編】

Hugging Faceでトークンを取得する


 Hugging Faceというのは、自然言語処理を対象にしたオープンソースコミュニティのこと。多分、自然言語処理版Githubみたいなものだと思う。ここにStable Diffusionのモデルが公開されている。アクセストークンを取得するとAPI越しにデータを取得できるようになる。

アカウントの作成

(1) サインアップのページを開く

IFrame URL


(2) メールアドレスとパスワードを入力


(3) ユーザ名とフルネームの登録


(4) メールアドレスの認証

 登録したメールアドレスにメールが届くので、メール本文のリンクからメールアドレスを認証する。




アクセストークンの発行

(1) Settingsのページを開く


(2) Access Tokenのページを開く


(3) New Tokenからトークンを発行する

 Nameには分かりやすい名称をつける。(この手順ではGoogle Colabとつけた)

 Roleは、(今回の手順では)READトークンで良い。

(4) トークンをコピーする


モデルへのアクセス権の取得

(1) Stable Diffusion V1.4のページを開く

https://huggingface.co/CompVis/stable-diffusion-v1-4



(2) ライセンスに同意する

 ※よく読んでね!


【構築編】

ノートブックの作成

ノートブックの新規作成

(1) Colabを開く

IFrame URL


(2) ノートブックを新規作成


(3) ノートブックの名称を変更

本手順では分かりやすいようにStableDiffusionとした。


ランタイムの設定

(1) 『ランタイムのタイプの変更』を開く


(2) ハードウェアアクセラレータの変更

 GPUを選択。


インストール

パッケージのインストール

(1) ランタイムへ接続


(2) コマンドを実行

!pip install --upgrade diffusers transformers scipy


 左端に緑色のチェックマークが出たら、実行完了。


NSFWフィルターの無効化

 diffusersパッケージのソースコードを直接書き換えるので注意。

 失敗した場合は、ノートブックを作り直すなどすること。

 ※ちなみに、NSFWを無効化せずに先の手順に進めることも可能。ただし、後からNSFWを無効化したくなった場合に、この手順だけを実行してもうまく動かないので注意。(手順の順番通りに実行する必要がある)


(1) セル(行)を追加

 左上の +<> を押下する。


(2) コードを実行


# ここから↓

# Disable NSFW check

with open('/usr/local/lib/python3.7/dist-packages/diffusers/pipelines/stable_diffusion/safety_checker.py','w') as file:

file.write('''import numpy as np

import torch

import torch.nn as nn


from transformers import CLIPConfig, CLIPVisionModel, PreTrainedModel


from ...utils import logging



logger = logging.get_logger(__name__)



def cosine_distance(image_embeds, text_embeds):

normalized_image_embeds = nn.functional.normalize(image_embeds)

normalized_text_embeds = nn.functional.normalize(text_embeds)

return torch.mm(normalized_image_embeds, normalized_text_embeds.T)



class StableDiffusionSafetyChecker(PreTrainedModel):

config_class = CLIPConfig


def __init__(self, config: CLIPConfig):

super().__init__(config)


self.vision_model = CLIPVisionModel(config.vision_config)

self.visual_projection = nn.Linear(config.vision_config.hidden_size, config.projection_dim, bias=False)


self.concept_embeds = nn.Parameter(torch.ones(17, config.projection_dim), requires_grad=False)

self.special_care_embeds = nn.Parameter(torch.ones(3, config.projection_dim), requires_grad=False)


self.register_buffer("concept_embeds_weights", torch.ones(17))

self.register_buffer("special_care_embeds_weights", torch.ones(3))


@torch.no_grad()

def forward(self, clip_input, images):

pooled_output = self.vision_model(clip_input)[1] # pooled_output

image_embeds = self.visual_projection(pooled_output)


special_cos_dist = cosine_distance(image_embeds, self.special_care_embeds).cpu().numpy()

cos_dist = cosine_distance(image_embeds, self.concept_embeds).cpu().numpy()


result = []

batch_size = image_embeds.shape[0]

for i in range(batch_size):

result_img = {"special_scores": {}, "special_care": [], "concept_scores": {}, "bad_concepts": []}


# increase this value to create a stronger `nfsw` filter

# at the cost of increasing the possibility of filtering benign images

adjustment = 0.0


for concet_idx in range(len(special_cos_dist[0])):

concept_cos = special_cos_dist[i][concet_idx]

concept_threshold = self.special_care_embeds_weights[concet_idx].item()

result_img["special_scores"][concet_idx] = round(concept_cos - concept_threshold + adjustment, 3)

if result_img["special_scores"][concet_idx] > 0:

result_img["special_care"].append({concet_idx, result_img["special_scores"][concet_idx]})

adjustment = 0.01


for concet_idx in range(len(cos_dist[0])):

concept_cos = cos_dist[i][concet_idx]

concept_threshold = self.concept_embeds_weights[concet_idx].item()

result_img["concept_scores"][concet_idx] = round(concept_cos - concept_threshold + adjustment, 3)

if result_img["concept_scores"][concet_idx] > 0:

result_img["bad_concepts"].append(concet_idx)


result.append(result_img)


has_nsfw_concepts = [len(res["bad_concepts"]) > 0 for res in result]


#for idx, has_nsfw_concept in enumerate(has_nsfw_concepts):

# if has_nsfw_concept:

# images[idx] = np.zeros(images[idx].shape) # black image


if any(has_nsfw_concepts):

logger.warning(

"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."

)


return images, has_nsfw_concepts''')

# ここまで↑


 左端に緑色のチェックマークが出たら、実行完了。


モデルの適用

(1) セル(行)を追加

 左上の +<> を押下する。


(2) コードを貼り付けて、アクセストークン部分を書き換える

 (準備編でコピーしたアクセストークンを使います)


# ここから↓

from diffusers import StableDiffusionPipeline


YOUR_TOKEN = "ここにアクセストークンを入れる"

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

pipe = StableDiffusionPipeline.from_pretrained(model_id, use_auth_token=YOUR_TOKEN)

pipe.to("cuda")

# ここまで↑


(3) コードを実行


動作確認

プロンプトの実行

(1) セル(行)を追加

 左上の +<> を押下する。


(2) コードの実行

import datetime

prompt = "Hyperrealistic manly rugby player, art nouveau"

image = pipe(prompt, height=512, width=512, guidance_scale=10, num_inference_steps=70)["sample"][0]

image.save(f""+datetime.datetime.now().strftime('%Y%m%d_%H%M%S')+".png")

image

(3) 確認


 画像が表示されればOK。

 一応、画像は一時的にストレージにも保存される。

 (ファイルブラウザで閲覧可能)



その他、備考

 ・無操作時間90分、または12時間経過でランタイムはリセットされる。

 ・画像サイズを増やすと容赦なくメモリ不足になるので注意。

  (メモリ不足になるとランタイムのリセットが必要になってしまうので注意)

 ・画像サイズの指定には制約がある。

  詳しく仕様を読んでないけど、64の倍数なら動くみたい。

 (512x960くらいがメモリ的に限界だった)

 ・急にエラーが出るようになったらとにかくランタイムを再起動/リセットする。

 ・ランタイムがリセットされた場合は、構築編/インストールの手順を再実行する。

 ・使用量が上限に達するとGPUが利用できなくなる。

  (一日程度経過すると再利用できるようになる)








Files

Comments

No comments found for this post.