MNIST
db用に次の単純なMLPネットワークを作成しました。
from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras import callbacks
batch_size = 100
num_classes = 10
epochs = 20
tb = callbacks.TensorBoard(log_dir='/Users/shlomi.shwartz/tensorflow/notebooks/logs/minist', histogram_freq=10, batch_size=32,
write_graph=True, write_grads=True, write_images=True,
embeddings_freq=10, embeddings_layer_names=None,
embeddings_metadata=None)
early_stop = callbacks.EarlyStopping(monitor='val_loss', min_delta=0,
patience=3, verbose=1, mode='auto')
# the data, shuffled and split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()
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')
x_train /= 255
x_test /= 255
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
model = Sequential()
model.add(Dense(200, activation='relu', input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(100, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(60, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(30, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(10, activation='softmax'))
model.summary()
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
history = model.fit(x_train, y_train,
callbacks=[tb,early_stop],
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
モデルは正常に実行され、TensorBoardでスカラー情報を確認できました。ただし、embeddings_freq = 10を変更して画像を視覚化しようとすると( ここに表示 )、次のエラーが発生しました:
Traceback (most recent call last):
File "/Users/shlomi.shwartz/IdeaProjects/TF/src/minist.py", line 65, in <module>
validation_data=(x_test, y_test))
File "/Users/shlomi.shwartz/tensorflow/lib/python3.6/site-packages/keras/models.py", line 870, in fit
initial_Epoch=initial_Epoch)
File "/Users/shlomi.shwartz/tensorflow/lib/python3.6/site-packages/keras/engine/training.py", line 1507, in fit
initial_Epoch=initial_Epoch)
File "/Users/shlomi.shwartz/tensorflow/lib/python3.6/site-packages/keras/engine/training.py", line 1117, in _fit_loop
callbacks.set_model(callback_model)
File "/Users/shlomi.shwartz/tensorflow/lib/python3.6/site-packages/keras/callbacks.py", line 52, in set_model
callback.set_model(model)
File "/Users/shlomi.shwartz/tensorflow/lib/python3.6/site-packages/keras/callbacks.py", line 719, in set_model
self.saver = tf.train.Saver(list(embeddings.values()))
File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/tensorflow/python/training/saver.py", line 1139, in __init__
self.build()
File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/tensorflow/python/training/saver.py", line 1161, in build
raise ValueError("No variables to save")
ValueError: No variables to save
Q:何が足りないのですか?それはKerasでそれを行う正しい方法ですか?
更新:埋め込みプロジェクションを使用するためのいくつかの前提条件があることを理解していますが、Kerasでそれを行うための良いチュートリアルが見つかりませんでした。いただければ幸いです。
ここでcallbacks.TensorBoard
に「埋め込み」と呼ばれるものは、広い意味で、任意のレイヤーの重みです。 Kerasドキュメント によると:
embeddings_layer_names:監視するレイヤーの名前のリスト。なしまたは空のリストの場合、すべての埋め込みレイヤーが監視されます。
したがって、デフォルトでは、Embedding
レイヤーを監視しますが、実際にはEmbedding
レイヤーは必要ありません。この視覚化ツールを使用するには。
提供されているMLPの例では、欠落しているのはembeddings_layer_names
引数です。視覚化するレイヤーを把握する必要があります。すべてのkernel
レイヤーの重み(または、KerasではDense
)を視覚化したい場合、次のようにembeddings_layer_names
を指定できます。
model = Sequential()
model.add(Dense(200, activation='relu', input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(100, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(60, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(30, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(10, activation='softmax'))
embedding_layer_names = set(layer.name
for layer in model.layers
if layer.name.startswith('dense_'))
tb = callbacks.TensorBoard(log_dir='temp', histogram_freq=10, batch_size=32,
write_graph=True, write_grads=True, write_images=True,
embeddings_freq=10, embeddings_metadata=None,
embeddings_layer_names=embedding_layer_names)
model.compile(...)
model.fit(...)
次に、TensorBoardで次のようなものを見ることができます:
embeddings_layer_names
に関して何が起こっているのかを知りたい場合は、 Kerasソースの関連行 を参照してください。
だからここにレイヤー出力を視覚化するための汚い解決策があります。元のTensorBoard
コールバックはこれをサポートしていないため、新しいコールバックの実装は避けられないようです。
ここでTensorBoard
コールバック全体を書き直すには多くのページスペースが必要になるため、元のTensorBoard
を拡張して、異なる部分を書き出します(すでにかなり長い)。ただし、計算の重複やモデルの保存を避けるために、TensorBoard
コールバックを書き直す方がより適切でクリーンな方法になります。
import tensorflow as tf
from tensorflow.contrib.tensorboard.plugins import projector
from keras import backend as K
from keras.models import Model
from keras.callbacks import TensorBoard
class TensorResponseBoard(TensorBoard):
def __init__(self, val_size, img_path, img_size, **kwargs):
super(TensorResponseBoard, self).__init__(**kwargs)
self.val_size = val_size
self.img_path = img_path
self.img_size = img_size
def set_model(self, model):
super(TensorResponseBoard, self).set_model(model)
if self.embeddings_freq and self.embeddings_layer_names:
embeddings = {}
for layer_name in self.embeddings_layer_names:
# initialize tensors which will later be used in `on_Epoch_end()` to
# store the response values by feeding the val data through the model
layer = self.model.get_layer(layer_name)
output_dim = layer.output.shape[-1]
response_tensor = tf.Variable(tf.zeros([self.val_size, output_dim]),
name=layer_name + '_response')
embeddings[layer_name] = response_tensor
self.embeddings = embeddings
self.saver = tf.train.Saver(list(self.embeddings.values()))
response_outputs = [self.model.get_layer(layer_name).output
for layer_name in self.embeddings_layer_names]
self.response_model = Model(self.model.inputs, response_outputs)
config = projector.ProjectorConfig()
embeddings_metadata = {layer_name: self.embeddings_metadata
for layer_name in embeddings.keys()}
for layer_name, response_tensor in self.embeddings.items():
embedding = config.embeddings.add()
embedding.tensor_name = response_tensor.name
# for coloring points by labels
embedding.metadata_path = embeddings_metadata[layer_name]
# for attaching images to the points
embedding.Sprite.image_path = self.img_path
embedding.Sprite.single_image_dim.extend(self.img_size)
projector.visualize_embeddings(self.writer, config)
def on_Epoch_end(self, Epoch, logs=None):
super(TensorResponseBoard, self).on_Epoch_end(Epoch, logs)
if self.embeddings_freq and self.embeddings_ckpt_path:
if Epoch % self.embeddings_freq == 0:
# feeding the validation data through the model
val_data = self.validation_data[0]
response_values = self.response_model.predict(val_data)
if len(self.embeddings_layer_names) == 1:
response_values = [response_values]
# record the response at each layers we're monitoring
response_tensors = []
for layer_name in self.embeddings_layer_names:
response_tensors.append(self.embeddings[layer_name])
K.batch_set_value(list(Zip(response_tensors, response_values)))
# finally, save all tensors holding the layer responses
self.saver.save(self.sess, self.embeddings_ckpt_path, Epoch)
それを使用するには:
tb = TensorResponseBoard(log_dir=log_dir, histogram_freq=10, batch_size=10,
write_graph=True, write_grads=True, write_images=True,
embeddings_freq=10,
embeddings_layer_names=['dense_1'],
embeddings_metadata='metadata.tsv',
val_size=len(x_test), img_path='images.jpg', img_size=[28, 28])
TensorBoardを起動する前に、視覚化のためにラベルと画像をlog_dir
に保存する必要があります。
from PIL import Image
img_array = x_test.reshape(100, 100, 28, 28)
img_array_flat = np.concatenate([np.concatenate([x for x in row], axis=1) for row in img_array])
img = Image.fromarray(np.uint8(255 * (1. - img_array_flat)))
img.save(os.path.join(log_dir, 'images.jpg'))
np.savetxt(os.path.join(log_dir, 'metadata.tsv'), np.where(y_test)[1], fmt='%d')
結果は次のとおりです。
Kerasには少なくとも1つの埋め込みレイヤーが必要です。統計については、それらについての良い説明でした。これはKeras向けではありませんが、概念はほぼ同じです。 ニューラルネットワークの埋め込み層とは
したがって、実際に必要なのは(投稿からは完全には明確ではありません)、モデルの予測を次のように視覚化することであると結論付けます。 このTensorboardデモ 。
そもそも、このようなものを再現することは簡単ではありません Tensorflowでも 、Kerasは言うまでもありません。上記のデモでは、非常に簡潔で、そのような視覚化を取得するために必要な メタデータとスプライト画像 のようなものへの参照を渡します。
結論:自明ではありませんが、Kerasでそれを行うことは確かに可能です。 Kerasコールバックは必要ありません。必要なのは、モデルの予測、必要なメタデータとスプライトイメージ、およびいくつかの純粋なTensorFlowコードだけです。そう、
ステップ1-テストセットのモデル予測を取得します。
emb = model.predict(x_test) # 'emb' for embedding
ステップ2a-テストセットの実際のラベルを使用してメタデータファイルを作成します。
import numpy as np
LOG_DIR = '/home/herc/SO/tmp' # FULL PATH HERE!!!
metadata_file = os.path.join(LOG_DIR, 'metadata.tsv')
with open(metadata_file, 'w') as f:
for i in range(len(y_test)):
c = np.nonzero(y_test[i])[0][0]
f.write('{}\n'.format(c))
ステップ2b-TensorFlowの担当者から提供されたスプライト画像mnist_10k_Sprite.png
を取得します ここLOG_DIR
ステップ3-Tensorflowコードを記述します:
import tensorflow as tf
from tensorflow.contrib.tensorboard.plugins import projector
embedding_var = tf.Variable(emb, name='final_layer_embedding')
sess = tf.Session()
sess.run(embedding_var.initializer)
summary_writer = tf.summary.FileWriter(LOG_DIR)
config = projector.ProjectorConfig()
embedding = config.embeddings.add()
embedding.tensor_name = embedding_var.name
# Specify the metadata file:
embedding.metadata_path = os.path.join(LOG_DIR, 'metadata.tsv')
# Specify the Sprite image:
embedding.Sprite.image_path = os.path.join(LOG_DIR, 'mnist_10k_Sprite.png')
embedding.Sprite.single_image_dim.extend([28, 28]) # image size = 28x28
projector.visualize_embeddings(summary_writer, config)
saver = tf.train.Saver([embedding_var])
saver.save(sess, os.path.join(LOG_DIR, 'model2.ckpt'), 1)
次に、LOG_DIR
でTensorboardを実行し、ラベルで色を選択すると、次のようになります。
他のレイヤーの予測を取得するためにこれを変更するのは簡単ですが、この場合はKeras FunctionalAPIの方が適している場合があります。