tensowboardで特徴量を可視化する(tf.keras) - 全結合

#tensorboardで特徴量を可視化してみた

以前に投稿した[mnistを全結合層で教師あり学習し、最終段をクラスタリングして評価する](https://qiita.com/notfolder/items/c7665a67bd18679e7b6e)のコードに下記を追記して、tensorboardで可視化した。

こんな感じ。3Dでぐるぐる回せるので楽しい。
![スクリーンショット 2020-12-12 22.50.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490869/78189972-10e6-6d7b-42be-4cb577d7b8f5.png)

**metadata.tsvをGUIで読み込まないとラベルが反映されない問題が出たが、tensorboardを起動するときに、./tflogではなく、./tflog/YYYY-MM-DDnnnnnnを指定することでmetadata.tsvが読み込まれるので注意**
・・・できれば./tflogで読んで欲しいが、その場合はチェックポイントファイル自体も./tflogに書き出す必要がある模様。

**projectorに指定する変数名はtensorboadに表示される変数名を指定すること**

### ラベルを可視化するためのメタデータを作成

```python
# メタデータ作成・保存
import datetime
import os
import numpy as np
LOG_DIR = f"./tflog/{datetime.datetime.now().strftime('%Y-%m-%d-%H%M%S')}"
META = os.path.join(LOG_DIR, 'metadata.tsv')
with open(META, 'w') as f:
    f.write("Index\tLabel\n")
    for index,label in enumerate(np.where(y_test)[1]):
        f.write("%d\t%d\n" % (index,label))
```

### コールバックを作成し、学習中のデータを記録するようにする

```python
# コールバックを作成
tb_cb = tensorflow.keras.callbacks.TensorBoard(log_dir= LOG_DIR,
    histogram_freq=1)
cbks = [tb_cb]

history = model.fit(x_train, y_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    validation_data=(x_test, y_test), callbacks=cbks)
```

### チェックポイントを作成し、Projectorに出力する

```python
result = model.predict(x_test)

emb = result

# embeddingsの作成
embedding_var = tensorflow.Variable(emb,  name='mnist_embedding')

CHECKPOINT_FILE = LOG_DIR + '/model.ckpt'
ckpt = tensorflow.train.Checkpoint(embeddings=embedding_var)
ckpt.save(CHECKPOINT_FILE)

from tensorboard.plugins import projector
# Projector設定
config = projector.ProjectorConfig()
embedding = config.embeddings.add()
embedding.tensor_name = "embeddings/.ATTRIBUTES/VARIABLE_VALUE"
# メタデータ(CSV)パス
embedding.metadata_path= 'metadata.tsv'

# Projectorに出力
projector.visualize_embeddings(LOG_DIR, config)
```

全体コードは下記。

```python
import tensorflow
# one-hot encodingを施すためのメソッド
from tensorflow.keras.utils import to_categorical

# 必要なライブラリのインポート
from tensorflow.keras.datasets import mnist
import numpy as np
#import pandas as pd
#import sklearn

from tensorflow.keras.layers import Lambda, Input, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.losses import mse
from tensorflow.keras import backend as K

#Kerasの関数でデータの読み込み。データをシャッフルして学習データと訓練データに分割
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# 2次元データを数値に変換
x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
# 型変換
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
# 255で割ったものを新たに変数とする
x_train /= 255
x_test /= 255

# one-hot encodingを施すためのメソッド
from tensorflow.keras.utils import to_categorical

# クラス数は10
num_classes = 10
y_train = y_train.astype('int32')
y_test = y_test.astype('int32')
labels = y_test
# one-hot encoding
y_train = to_categorical(y_train, num_classes)
y_test =  to_categorical(y_test, num_classes)

# 必要なライブラリのインポート、最適化手法はAdamを使う
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout
from tensorflow.keras.optimizers import Adam

feature_dim = 10

# モデル作成
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(feature_dim, activation='relu'))  # 特徴量として取り出すための層を追加
model.add(Dense(10, activation='softmax'))

model.summary()

# バッチサイズ、エポック数
batch_size = 128
epochs = 20

model.compile(loss='categorical_crossentropy',
            optimizer=Adam(),
            metrics=['accuracy'])

# メタデータ作成・保存
import datetime
import os
import numpy as np
LOG_DIR = f"./tflog/{datetime.datetime.now().strftime('%Y-%m-%d-%H%M%S')}"
META = os.path.join(LOG_DIR, 'metadata.tsv')
os.makedirs(os.path.join(LOG_DIR), exist_ok=True)
with open(META, 'w') as f:
    f.write("Index\tLabel\n")
    for index,label in enumerate(np.where(y_test)[1]):
        f.write("%d\t%d\n" % (index,label))

# コールバックを作成
tb_cb = tensorflow.keras.callbacks.TensorBoard(log_dir= LOG_DIR,
    histogram_freq=1)
cbks = [tb_cb]

history = model.fit(x_train, y_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    validation_data=(x_test, y_test),
                    callbacks=cbks)

model.pop() # 最終段のsoftmax層を取り除いて、特徴量の層を最終段とする
model.summary()
result = model.predict(x_test)

emb = result

# embeddingsの作成
embedding_var = tensorflow.Variable(emb,  name='mnist_embedding')

CHECKPOINT_FILE = os.path.join(LOG_DIR, 'model.ckpt')
ckpt = tensorflow.train.Checkpoint(embeddings=embedding_var)
ckpt.save(CHECKPOINT_FILE)

from tensorboard.plugins import projector
# Projector設定
config = projector.ProjectorConfig()
embedding = config.embeddings.add()
embedding.tensor_name = "embeddings/.ATTRIBUTES/VARIABLE_VALUE"
# メタデータ(CSV)パス
embedding.metadata_path= 'metadata.tsv'

# Projectorに出力
projector.visualize_embeddings(LOG_DIR, config)
```