# stable-diffusion-webui-dumpunet
**Repository Path**: dbscholar0/stable-diffusion-webui-dumpunet
## Basic Information
- **Project Name**: stable-diffusion-webui-dumpunet
- **Description**: 查看不同的图层,观察 U-Net 特征图。通过为每个 unet 块提供不同的提示生成图像:https://note.com/kohya_ss/n/n93b7c01b0547
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2023-04-08
- **Last Updated**: 2023-04-08
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
[English ver.](./README_en.md)
# Dump U-Net
## 目次
- [Dump U-Net](#dump-u-net)
- [目次](#目次)
- [これは何](#これは何)
- [できること](#できること)
- [特徴量の抽出](#特徴量の抽出)
- [U-Net の特徴量画像](#u-net-の特徴量画像)
- [画面説明](#画面説明)
- [Colorization](#colorization)
- [Dump Setting](#dump-setting)
- [抽出画像の例](#抽出画像の例)
- [アテンション層の特徴量抽出](#アテンション層の特徴量抽出)
- [画面説明](#画面説明-1)
- [例](#例)
- [ブロックごとのプロンプトの変更](#ブロックごとのプロンプトの変更)
- [概要](#概要)
- [画面説明](#画面説明-2)
- [記法](#記法)
- [例](#例-1)
- [Dynamic Prompts との併用](#dynamic-prompts-との併用)
- [TODO](#todo)
## これは何
U-Net の特徴量を可視化するための [stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui) の拡張です。
## できること
1. モデルの途中出力の可視化:U-Net の各ブロックおよびアテンション層の特徴量を可視化する。
2. 層別プロンプト:U-Net の各ブロックでプロンプトを変更しながら画像を生成する。
3. 2.でプロンプトを変更したときの U-Net の特徴量の差分を可視化する。
## 特徴量の抽出
例として以下の画像を使用する。

```
Model: waifu-diffusion-v1-3-float16 (84692140)
Prompt: a cute girl, pink hair
Sampling steps: 20
Sampling Method: DPM++ 2M Karras
Size: 512x512
CFG Scale: 7
Seed: 1719471015
```
### U-Net の特徴量画像
たとえば以下のような画像を生成する。
グレースケール出力 `OUT11, steps 20, Black/White, Sigmoid(1,0)`

カラー出力 `OUT11, steps 20, Custom, Sigmoid(1,0), H=(2+v)/3, S=1.0, V=0.5`

#### 画面説明

- Extract U-Net features
- チェックすると U-Net の特徴量抽出が有効になる。
- Layers
- 抽出対象のブロックを指定する。コンマ区切り、ハイフン区切りが使える。
IN11-M00-OUT00
は繋がっている。
- Image saving steps
- 抽出対象のステップを指定する。
- Colorization
- 出力画像の色を指定する。
- Dump Setting
- 特徴量のバイナリを出力する設定を行う。
- Selected Layer Info
Layers
で指定したブロックの詳細が出力される。
抽出するブロックの指定方法:
```
単体指定: IN00
IN00 から IN11、M00、OUT00 から OUT11 が使える。
複数指定: IN00, IN01, M00
コンマ `,` で区切って複数のブロックを指定できる。
範囲指定: IN00-OUT11
ハイフン `-` で区切って範囲を指定できる。
両端は範囲に含まれる。
IN11, M00, OUT00 は繋がっている。
範囲指定(ステップ付き): IN00-OUT11(+2)
範囲指定の後に `(+数字)` と書くとステップを表す。
+1 と書くと通常の範囲指定と同じ。
+2 と書くと一つ飛ばしで指定したことになる。
例えば上記の例は
IN00, IN02, IN04, IN06, IN08, IN10,
M00,
OUT01, OUT03, OUT05, OUT07, OUT09, OUT11
を指定したことになる。
```
#### Colorization

- Colorize method
- 色付けの方法を指定する。
White/Black
は特徴量を v
として、|v|
が大きいピクセルを白、小さいピクセルを黒で表示する。
Red/Blue
は v
が大きいピクセルを赤、小さいピクセルを青で表示する。
Custom
は v
の値から RGB もしくは HSL 色空間の値を自由に計算する。
- Value transform
- 特徴量の値は必ずしもそのまま色の指定に使える大きさではない。そのときにピクセル値へ変換するときの変換方法を指定する。
Auto [0,1]
は与えられた特徴量の最小値と最大値を使って値を [0,1]
に線型変換する。
Auto [-1,1]
は同じく [-1,1]
に線型変換する。
Linear
は Clamp min./max.
を指定して、その範囲を Colorize method
が White/Black
のとき [0,1]
に、それ以外のとき [-1,1]
に線型変換する。

Sigmoid
は gain
と offset
を指定して、v + offset
をシグモイド関数で変換する。出力は Colorize method
が White/Black
のとき [0,1]
に、それ以外のとき [-1,1]
になる。
- Color space
Value transform
で変換した値 v
をピクセル値に変換するコードを書く。v
の範囲は Colorize method
および Value transform
の指定により [0,1]
もしくは [-1,1]
で与えられる。計算結果は [0,1]
でクリップされる。
コードは numpy
をグローバル環境として実行される。たとえば、abs(v)
は numpy.abs(v)
の意味になる。

#### Dump Setting

- Dump feature tensors to files
- チェックすると U-Net の特徴量をファイルとして書き出す。
- Output path
- バイナリを出力するディレクトリを指定する。存在しなければ作成される。
#### 抽出画像の例
左から順に、`steps=1,5,10` の画像。
- IN00 (64x64, 320ch)

- IN05 (32x32, 640ch)

- M00 (8x8, 1280ch)

- OUT06 (32x32, 640ch)

- OUT11 (64x64, 320ch)

### アテンション層の特徴量抽出
#### 画面説明

ほぼ [U-Net の特徴量画像](#41-u-net-%E3%81%AE%E7%89%B9%E5%BE%B4%E9%87%8F%E7%94%BB%E5%83%8F) と同じ。
#### 例
横軸がトークン位置を表す。最初に開始トークン、最後に終了トークンが挿入されているので、間の75枚の画像が各トークンの影響を表す。
縦軸はアテンション層のヘッド。今のモデルでは h=8
なので画像が8つ並ぶことになる。
「`pink hair` はこの層に効いてるのかな?」みたいなことが分かる。
- IN01

- M00

- OUT10

## ブロックごとのプロンプトの変更
### 概要
内容は以下の記事を参照。
[Stable DiffusionのU-Netでブロックごとに異なるプロンプトを与えて画像生成する(ブロック別プロンプト)](https://note.com/kohya_ss/n/n93b7c01b0547)
```
Model: waifu-diffusion-v1-3-float16 (84692140)
Prompt: a (~: IN00-OUT11: cute; M00: excellent :~) girl
Sampling Method: Euler a
Size: 512x512
CFG Scale: 7
Seed: 3292581281
```
上の画像は順番に、
- `a cute girl` で生成した画像
- IN00 のみ cute を excellent に変更して生成した画像
- IN05 のみ cute を excellent に変更して生成した画像
- M00 のみ cute を excellent に変更して生成した画像
となっている。
### 画面説明

ほぼ [U-Net の特徴量画像](#41-u-net-%E3%81%AE%E7%89%B9%E5%BE%B4%E9%87%8F%E7%94%BB%E5%83%8F) と同じ。
- Output difference map of U-Net features between with and without Layer Prompt
- ブロックごとのプロンプトが有効の時と無効の時の U-Net の特徴量を比較して差分画像を出力する。
### 記法
プロンプト中で次に示す特殊な記法を用いることで、ブロックごとのプロンプトを指定できる。
```
a (~: IN00-OUT11: cute ; M00: excellent :~) girl
```
この場合、IN00~OUT11 まで(つまり全体)で
```
a cute girl
```
が使われるが、M00 のみ
```
a excellent girl
```
が使われることになる。
指定は `(~:` から `:~)` までの間で行う。書式は以下の通り。
```
(~:
ブロック指定:プロンプト;
ブロック指定:プロンプト;
...
ブロック指定:プロンプト;
:~)
```
`(~:` の後、`:~)` の前、`:` の前、`;` の後は空白を入れてもいい。ただし `:プロンプト;` の部分の空白はそのまま結果に反映されるので注意。一番最後のプロンプトの後のセミコロンは無くてもいい。
ブロック指定は以下のように行う。おおむね X/Y plot と同じ。なお、範囲が重なっている場合は後に指定したものが優先される。
```
単体指定: IN00
IN00 から IN11、M00、OUT00 から OUT11 が使える。
複数指定: IN00, IN01, M00
コンマ `,` で区切って複数のブロックを指定できる。
範囲指定: IN00-OUT11
ハイフン `-` で区切って範囲を指定できる。
両端は範囲に含まれる。
IN11, M00, OUT00 は繋がっている。
範囲指定(ステップ付き): IN00-OUT11(+2)
範囲指定の後に `(+数字)` と書くとステップを表す。
+1 と書くと通常の範囲指定と同じ。
+2 と書くと一つ飛ばしで指定したことになる。
例えば上記の例は
IN00, IN02, IN04, IN06, IN08, IN10,
M00,
OUT01, OUT03, OUT05, OUT07, OUT09, OUT11
を指定したことになる。
その他全て: _ (アンダーバー)
これは特殊な記号で、優先度は最も低い。
他のどのブロックにも当てはまらなかった場合、ここで指定したプロンプトが使われる。
```
### 例
いくつか例を挙げる。
```
1: (~: IN00: A ; IN01: B :~)
2: (~: IN00: A ; IN01: B ; IN02: C :~)
3: (~: IN00: A ; IN01: B ; IN02: C ; _ : D :~)
4: (~: IN00,IN01: A ; M00 : B :~)
5: (~: IN00-OUT11: A ; M00 : B :~)
```
1: IN00でAを、IN01でBを使う。他のブロックでは何も無し。
2: IN00でAを、IN01でBを、IN02でCを使う。他のブロックでは何も無し。
3: IN00でAを、IN01でBを、IN02でCを使う。他のブロックではDを使う。
4: IN00とIN01でAを、M00でBを使う。他のブロックでは何も無し。
5: IN00からOUT11まで(つまり全体)でAを使う。ただしM00ではBを使う。
### Dynamic Prompts との併用
検証には [Dynamic Prompts](https://github.com/adieyal/sd-dynamic-prompts) との併用が便利。
たとえば1ブロックでのみプロンプトを変更した際の影響を見たい場合、Dynamic Prompts の Jinja Template を有効にして
```
{% for layer in [ "IN00", "IN01", "IN02", "IN03", "IN04", "IN05", "IN06", "IN07", "IN08", "IN09", "IN10", "IN11", "M00", "OUT00", "OUT01", "OUT02", "OUT03", "OUT04", "OUT05", "OUT06", "OUT07", "OUT08", "OUT09", "OUT10", "OUT11" ] %}
{% prompt %}a cute school girl, pink hair, wide shot, (~:{{layer}}:bad anatomy:~){% endprompt %}
{% endfor %}
```
と指定すると、各ブロックでの「bad anatomy」の効果を調べる……といったことができる。
実際の例:[ブロック別プロンプトで特定の1ブロックにプロンプトを追加してみるテスト](https://gist.github.com/hnmr293/7f240aa5b74c0f5a27a9764fdd9672e2)
## TODO
- セルフアテンション層の可視化