Как использовать TensorBoard с Keras в Python для визуализации вложений

Я читаю книгу Deep Learning with Python, в которой используется Keras. В главе 7 показано, как использовать TensorBoard для мониторинга прогресса фазы обучения, на примере:

import keras
from keras import layers
from keras.datasets import imdb
from keras.preprocessing import sequence

max_features = 2000
max_len = 500
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
x_train = sequence.pad_sequences(x_train, maxlen=max_len)
x_test = sequence.pad_sequences(x_test, maxlen=max_len)

model = keras.models.Sequential()
model.add(layers.Embedding(max_features, 128, input_length=max_len, name='embed'))
model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.MaxPooling1D(5))
model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.GlobalMaxPooling1D())
model.add(layers.Dense(1))
model.summary()

model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])

callbacks = [
    keras.callbacks.TensorBoard(
        log_dir='my_log_dir',
        histogram_freq=1,
        embeddings_freq=1,
    )
]
history = model.fit(x_train, y_train, epochs=20, batch_size=128, validation_split=0.2, callbacks=callbacks)

По-видимому, библиотека Keras претерпела некоторые изменения, поскольку этот код вызывает некоторое исключение:

ValueError: To visualize embeddings, embeddings_data must be provided.

Это происходит после первой эпохи и при первом запуске обратных вызовов (при первом запуске TensorBoard). Я знаю, что отсутствует параметр TensorBoard embeddings_data. Но я не знаю, что мне назначить на это.

У кого-нибудь есть рабочий пример для этого?

Вот версии, которые я использую:

Python: 3.6.5
Keras: 2.2.0
Tensorflow: 1.9.0

[ОБНОВИТЬ]

Чтобы проверить любое возможное решение, я проверил это:

import numpy as np

callbacks = [
    keras.callbacks.TensorBoard(
        log_dir='my_log_dir',
        histogram_freq = 1,
        embeddings_freq = 1,
        embeddings_data = np.arange(0, max_len).reshape((1, max_len)),
    )
]
history = model.fit(x_train, y_train, epochs=20, batch_size=128, validation_split=0.2, callbacks=callbacks)

Это единственный способ заполнить embeddings_data который не приведет к ошибке. Но хотя это тоже не помогает. Тем не менее вкладка PROJECTOR TensorBoard пуста:

enter image description here

Любая помощь приветствуется.

Ответы

Ответ 1

Да, это правильно, вам нужно предоставить, что вставлять для визуализации, используя аргумент embeddings_data:

callbacks = [
    keras.callbacks.TensorBoard(
        log_dir='my_log_dir',
        histogram_freq=1,
        embeddings_freq=1,
        embeddings_data=np.array([3,4,2,5,2,...]),
    )
]

embeddings_data: данные, которые должны быть внедрены в слои, указанные в именах embeddings_layer_names. Массив Numpy (если модель имеет один вход) или список массивов Numpy (если модель имеет несколько входов).

Посмотрите документацию на обновленную информацию о том, что такое эти аргументы.

Ответ 2

Я просто задал себе тот же вопрос. Из документации было не совсем понятно, что такое "embeddings_data". Но имеет смысл, что это список слов для вставки, а точнее их индексов.

Но я немного запутался в этом формате. Из моего токенизатора с kken tokenizer у меня есть слово "word_index" с номером для всех слов в моем словаре, из которых используются самые частые записи maxwords. Токенизатор дает мне списки целых чисел от 0 до maxwords или мешок с одним горячим кодированием слов. Затем я помещаю эти последовательности в maxlen.

max_words = 1000

tokenizer = Tokenizer(num_words=max_words)
tokenizer.fit_on_texts(X_train)

X_train_sequences = tokenizer.texts_to_sequences(X_train)
X_train_one_hot_results = tokenizer.texts_to_matrix(X_train, mode='binary')

X_test_sequences = tokenizer.texts_to_sequences(X_test)
X_test_one_hot_results = tokenizer.texts_to_matrix(X_test, mode='binary')

#####

maxlen = 100
X_train_pad = pad_sequences(X_train_sequences, maxlen=maxlen)
X_test_pad = pad_sequences(X_test_sequences, maxlen=maxlen)

Затем я создаю модель, которая начинается с слоя внедрения как такового:

embedding_dim = 300

model = Sequential()
model.add(Embedding(max_words,embedding_dim,input_length=maxlen, name='embed'))
model.add(Flatten())
...

Таким образом max_words - это мой размер словаря, размер одного горячего кодированного слова/текста, embedding_dim - это размер выходного сигнала слоя, а maxlen - длина последовательности, то есть количество слов в предложении, которое поддерживается постоянным путем заполнения. Являются ли номера из word_index теми, что "embeddings_data" должны получить как-то?

Когда я ввожу "только" массив numpy, в котором указано произвольное количество индексов слов

...
tensorboard = TensorBoard(log_dir='log_dir', histogram_freq=1, embeddings_freq=1, embeddings_data=np.array([1,2,3]))
...

Я получаю эту ошибку:

ValueError: невозможно передать значение формы (3, 1) для Tensor 'embed_input_2: 0', который имеет форму '(?, 100)'

В моем примере 100 - длина последовательности. Это сбивает с толку. Потому что я хочу визуализировать отдельные слова, а не предложения или тексты, не так ли? Очевидно, обратный вызов хочет передать слой одной или нескольким последовательностям.

Итак, как я должен кодировать мои жетоны "Королева", "Король", "Женщина", "Человек", чтобы я мог видеть семантические отношения (надеюсь)? Или в более общем плане: как получить обзор всех элементов словарного запаса, чтобы выявить общие тенденции в индивидуально обученных вложениях?

Ответ 3

Я также читаю книгу "Глубокое обучение на Python", в которой используется Keras. Вот мое решение этого вопроса. Сначала я попробую этот код:

callbacks = [keras.callbacks.TensorBoard(
    log_dir = 'my_log_dir',
    histogram_freq = 1,
    embeddings_freq = 1,
    embeddings_data = x_train,
)]
history = model.fit(x_train, y_train, epochs=2, batch_size=128, validation_split=0.2, callbacks=callbacks)

Но есть ошибка: ResourceExhaustedError.

Поскольку в "x_train" содержится 25000 сэмплов, сложно встроить их в мой старый ноутбук. Итак, затем я пытаюсь встроить первые 100 сэмплов "x_train", и это имеет смысл.

Код и результат показаны здесь.

callbacks = [keras.callbacks.TensorBoard(
    log_dir = 'my_log_dir',
    histogram_freq = 1,
    embeddings_freq = 1,
    embeddings_data = x_train[:100],
)]
history = model.fit(x_train, y_train, epochs=2, batch_size=128, validation_split=0.2, callbacks=callbacks)

Проектор 100 образцов

Обратите внимание, что в проекторе "Точки: 100" означает, что имеется 100 выборок, а "Размер: 64000" означает, что длина вектора внедрения для одной выборки составляет 64000. В одной выборке содержится 500 слов, как "max_len = 500", и для каждого слова существует вектор 128_dim, поэтому 500 * 128 = 64000.

Ответ 4

Вот пример использования вложений для базового MNIST сверточного классификатора NN. В этом сценарии embedding_data данные являются входными данными, и я полагаю, что обычно это будут те данные, которые передаются через сеть.

Здесь связан скрипт с некоторыми комментариями. Во-первых, они начинаются с базовой настройки MNIST.

'''Trains a simple convnet on the MNIST dataset and embeds test data.
The test data is embedded using the weights of the final dense layer, just
before the classification head. This embedding can then be visualized using
TensorBoard Embedding Projector.
'''

from __future__ import print_function

from os import makedirs
from os.path import exists, join

import keras
from keras.callbacks import TensorBoard
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K

import numpy as np

batch_size = 128
num_classes = 10
epochs = 12
log_dir = './logs'

if not exists(log_dir):
    makedirs(log_dir)

# input image dimensions
img_rows, img_cols = 28, 28

# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

Теперь метаданные созданы для тензорной доски. Для этой задачи классификации embedding_data является тестовым набором. Затем метаданные должны включать соответствующие цифровые метки.

# save class labels to disk to color data points in TensorBoard accordingly
with open(join(log_dir, 'metadata.tsv'), 'w') as f:
    np.savetxt(f, y_test)

# 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)

Теперь определите обратный вызов тензорной доски. Обратите внимание, что "функции" будут относиться к встраиванию интересующего слоя, который называется при построении модели. embedding_data - это просто набор тестов.

tensorboard = TensorBoard(batch_size=batch_size,
                          embeddings_freq=1,
                          embeddings_layer_names=['features'],
                          embeddings_metadata='metadata.tsv',
                          embeddings_data=x_test)

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())

Следующий слой называется "функции".

model.add(Dense(128, activation='relu', name='features'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

model.fit(x_train, y_train,
          batch_size=batch_size,
          callbacks=[tensorboard],
          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])

# You can now launch tensorboard with 'tensorboard --logdir=./logs' on your
# command line and then go to http://localhost:6006/#projector to view the
# embeddings