Как отображать пользовательские изображения в TensorBoard с помощью Keras?
Я работаю над проблемой сегментации в Keras, и я хочу отображать результаты сегментации в конце каждой учебной эпохи.
Я хочу что-то похожее на Tensorflow: как отображать пользовательские изображения в Tensorboard (например, графики Matplotlib), но с использованием Keras. Я знаю, что TensorBoard
имеет TensorBoard
вызов TensorBoard
но для этой цели он кажется ограниченным.
Я знаю, что это нарушит абстракцию бэкэнда Keras, но я все равно заинтересован в использовании TensorFlow.
Можно ли добиться этого с помощью Keras + TensorFlow?
Ответы
Ответ 1
Итак, следующее решение хорошо работает для меня:
import tensorflow as tf
def make_image(tensor):
"""
Convert an numpy representation image to Image protobuf.
Copied from https://github.com/lanpa/tensorboard-pytorch/
"""
from PIL import Image
height, width, channel = tensor.shape
image = Image.fromarray(tensor)
import io
output = io.BytesIO()
image.save(output, format='PNG')
image_string = output.getvalue()
output.close()
return tf.Summary.Image(height=height,
width=width,
colorspace=channel,
encoded_image_string=image_string)
class TensorBoardImage(keras.callbacks.Callback):
def __init__(self, tag):
super().__init__()
self.tag = tag
def on_epoch_end(self, epoch, logs={}):
# Load image
img = data.astronaut()
# Do something to the image
img = (255 * skimage.util.random_noise(img)).astype('uint8')
image = make_image(img)
summary = tf.Summary(value=[tf.Summary.Value(tag=self.tag, image=image)])
writer = tf.summary.FileWriter('./logs')
writer.add_summary(summary, epoch)
writer.close()
return
tbi_callback = TensorBoardImage('Image Example')
Просто передайте обратный вызов, чтобы fit
или fit_generator
.
Обратите внимание, что вы также можете запустить некоторые операции, используя model
внутри обратного вызова. Например, вы можете запустить модель на некоторых изображениях, чтобы проверить ее производительность.
Ответ 2
Основываясь на приведенных выше ответах и своем собственном поиске, я предоставляю следующий код, чтобы завершить следующие вещи, используя TensorBoard в Keras:
- постановка задачи: предсказать карту диспаратности в бинокулярном стереофоническом согласовании;
- для подачи модели с входным левым изображением
x
и картой несоответствия истинности грунта gt
; - отображать входные данные
x
и истинность земли 'gt' в некоторый момент итерации; - чтобы отобразить вывод
y
вашей модели, в какой-то момент итерации.
-
Прежде всего, вы должны сделать свой класс обратного вызова с помощью Callback
. Note
что обратный вызов имеет доступ к связанной модели через свойство класса self.model
. Также Note
: вы должны передать входные данные для модели с помощью feed_dict, если вы хотите получить и отобразить выходные данные вашей модели.
from keras.callbacks import Callback
import numpy as np
from keras import backend as K
import tensorflow as tf
import cv2
# make the 1 channel input image or disparity map look good within this color map. This function is not necessary for this Tensorboard problem shown as above. Just a function used in my own research project.
def colormap_jet(img):
return cv2.cvtColor(cv2.applyColorMap(np.uint8(img), 2), cv2.COLOR_BGR2RGB)
class customModelCheckpoint(Callback):
def __init__(self, log_dir='./logs/tmp/', feed_inputs_display=None):
super(customModelCheckpoint, self).__init__()
self.seen = 0
self.feed_inputs_display = feed_inputs_display
self.writer = tf.summary.FileWriter(log_dir)
# this function will return the feeding data for TensorBoard visualization;
# arguments:
# * feed_input_display : [(input_yourModelNeed, left_image, disparity_gt ), ..., (input_yourModelNeed, left_image, disparity_gt), ...], i.e., the list of tuples of Numpy Arrays what your model needs as input and what you want to display using TensorBoard. Note: you have to feed the input to the model with feed_dict, if you want to get and display the output of your model.
def custom_set_feed_input_to_display(self, feed_inputs_display):
self.feed_inputs_display = feed_inputs_display
# copied from the above answers;
def make_image(self, numpy_img):
from PIL import Image
height, width, channel = numpy_img.shape
image = Image.fromarray(numpy_img)
import io
output = io.BytesIO()
image.save(output, format='PNG')
image_string = output.getvalue()
output.close()
return tf.Summary.Image(height=height, width=width, colorspace= channel, encoded_image_string=image_string)
# A callback has access to its associated model through the class property self.model.
def on_batch_end(self, batch, logs = None):
logs = logs or {}
self.seen += 1
if self.seen % 200 == 0: # every 200 iterations or batches, plot the costumed images using TensorBorad;
summary_str = []
for i in range(len(self.feed_inputs_display)):
feature, disp_gt, imgl = self.feed_inputs_display[i]
disp_pred = np.squeeze(K.get_session().run(self.model.output, feed_dict = {self.model.input : feature}), axis = 0)
#disp_pred = np.squeeze(self.model.predict_on_batch(feature), axis = 0)
summary_str.append(tf.Summary.Value(tag= 'plot/img0/{}'.format(i), image= self.make_image( colormap_jet(imgl)))) # function colormap_jet(), defined above;
summary_str.append(tf.Summary.Value(tag= 'plot/disp_gt/{}'.format(i), image= self.make_image( colormap_jet(disp_gt))))
summary_str.append(tf.Summary.Value(tag= 'plot/disp/{}'.format(i), image= self.make_image( colormap_jet(disp_pred))))
self.writer.add_summary(tf.Summary(value = summary_str), global_step =self.seen)
-
Затем передайте этот объект обратного вызова в fit_generator()
для вашей модели, например:
feed_inputs_4_display = some_function_you_wrote()
callback_mc = customModelCheckpoint( log_dir = log_save_path, feed_inputd_display = feed_inputs_4_display)
# or
callback_mc.custom_set_feed_input_to_display(feed_inputs_4_display)
yourModel.fit_generator(... callbacks = callback_mc)
...
-
Теперь вы можете запустить код и перейти на хост TensorBoard, чтобы увидеть отображение костюмированного изображения. Например, вот что я получил, используя вышеупомянутый код:
Готово! Наслаждайтесь!
Ответ 3
Аналогично, вы можете попробовать tf-matplotlib. Здесь график рассеяния
import tensorflow as tf
import numpy as np
import tfmpl
@tfmpl.figure_tensor
def draw_scatter(scaled, colors):
'''Draw scatter plots. One for each color.'''
figs = tfmpl.create_figures(len(colors), figsize=(4,4))
for idx, f in enumerate(figs):
ax = f.add_subplot(111)
ax.axis('off')
ax.scatter(scaled[:, 0], scaled[:, 1], c=colors[idx])
f.tight_layout()
return figs
with tf.Session(graph=tf.Graph()) as sess:
# A point cloud that can be scaled by the user
points = tf.constant(
np.random.normal(loc=0.0, scale=1.0, size=(100, 2)).astype(np.float32)
)
scale = tf.placeholder(tf.float32)
scaled = points*scale
# Note, 'scaled' above is a tensor. Its being passed 'draw_scatter' below.
# However, when 'draw_scatter' is invoked, the tensor will be evaluated and a
# numpy array representing its content is provided.
image_tensor = draw_scatter(scaled, ['r', 'g'])
image_summary = tf.summary.image('scatter', image_tensor)
all_summaries = tf.summary.merge_all()
writer = tf.summary.FileWriter('log', sess.graph)
summary = sess.run(all_summaries, feed_dict={scale: 2.})
writer.add_summary(summary, global_step=0)
При выполнении это приводит к следующему графику внутри Tensorboard
Обратите внимание, что tf-matplotlib заботится об оценке любых тензорных входов, избегает pyplot
резьбой на pyplot
и поддерживает блиты для критического построения времени выполнения.
Ответ 4
Я считаю, что нашел лучший способ записать такие пользовательские изображения на тензорную доску, используя tf-matplotlib. Вот как...
class TensorBoardDTW(tf.keras.callbacks.TensorBoard):
def __init__(self, **kwargs):
super(TensorBoardDTW, self).__init__(**kwargs)
self.dtw_image_summary = None
def _make_histogram_ops(self, model):
super(TensorBoardDTW, self)._make_histogram_ops(model)
tf.summary.image('dtw-cost', create_dtw_image(model.output))
Нужно просто переписать метод _make_histogram_ops из класса обратного вызова TensorBoard, чтобы добавить пользовательскую сводку. В моем случае create_dtw_image
- это функция, которая создает изображение с помощью tf-matplotlib.
С уважением,.
Ответ 5
Вот пример того, как нарисовать ориентиры на изображении:
class CustomCallback(keras.callbacks.Callback):
def __init__(self, model, generator):
self.generator = generator
self.model = model
def tf_summary_image(self, tensor):
import io
from PIL import Image
tensor = tensor.astype(np.uint8)
height, width, channel = tensor.shape
image = Image.fromarray(tensor)
output = io.BytesIO()
image.save(output, format='PNG')
image_string = output.getvalue()
output.close()
return tf.Summary.Image(height=height,
width=width,
colorspace=channel,
encoded_image_string=image_string)
def on_epoch_end(self, epoch, logs={}):
frames_arr, landmarks = next(self.generator)
# Take just 1st sample from batch
frames_arr = frames_arr[0:1,...]
y_pred = self.model.predict(frames_arr)
# Get last frame for which we have done predictions
img = frames_arr[0,-1,:,:]
img = img * 255
img = img[:, :, ::-1]
img = np.copy(img)
landmarks_gt = landmarks[-1].reshape(-1,2)
landmarks_pred = y_pred.reshape(-1,2)
img = draw_landmarks(img, landmarks_gt, (0,255,0))
img = draw_landmarks(img, landmarks_pred, (0,0,255))
image = self.tf_summary_image(img)
summary = tf.Summary(value=[tf.Summary.Value(image=image)])
writer = tf.summary.FileWriter('./logs')
writer.add_summary(summary, epoch)
writer.close()
return
Ответ 6
Я пытаюсь отобразить графики matplotlib на тензорной доске (полезные случаи построения статистики, тепловых карт и т.д.). Может использоваться и для общего случая.
class AttentionLogger(keras.callbacks.Callback):
def __init__(self, val_data, logsdir):
super(AttentionLogger, self).__init__()
self.logsdir = logsdir # where the event files will be written
self.validation_data = val_data # validation data generator
self.writer = tf.summary.FileWriter(self.logsdir) # creating the summary writer
@tfmpl.figure_tensor
def attention_matplotlib(self, gen_images):
'''
Creates a matplotlib figure and writes it to tensorboard using tf-matplotlib
gen_images: The image tensor of shape (batchsize,width,height,channels) you want to write to tensorboard
'''
r, c = 5,5 # want to write 25 images as a 5x5 matplotlib subplot in TBD (tensorboard)
figs = tfmpl.create_figures(1, figsize=(15,15))
cnt = 0
for idx, f in enumerate(figs):
for i in range(r):
for j in range(c):
ax = f.add_subplot(r,c,cnt+1)
ax.set_yticklabels([])
ax.set_xticklabels([])
ax.imshow(gen_images[cnt]) # writes the image at index cnt to the 5x5 grid
cnt+=1
f.tight_layout()
return figs
def on_train_begin(self, logs=None): # when the training begins (run only once)
image_summary = [] # creating a list of summaries needed (can be scalar, images, histograms etc)
for index in range(len(self.model.output)): # self.model is accessible within callback
img_sum = tf.summary.image('img{}'.format(index), self.attention_matplotlib(self.model.output[index]))
image_summary.append(img_sum)
self.total_summary = tf.summary.merge(image_summary)
def on_epoch_end(self, epoch, logs = None): # at the end of each epoch run this
logs = logs or {}
x,y = next(self.validation_data) # get data from the generator
# get the backend session and sun the merged summary with appropriate feed_dict
sess_run_summary = K.get_session().run(self.total_summary, feed_dict = {self.model.input: x['encoder_input']})
self.writer.add_summary(sess_run_summary, global_step =epoch) #finally write the summary!
Тогда вам нужно будет fit/fit_generator
его в качестве аргумента для fit/fit_generator
#val_generator is the validation data generator
callback_image = AttentionLogger(logsdir='./tensorboard', val_data=val_generator)
... # define the model and generators
# autoencoder is the model, note how callback is suppiled to fit_generator
autoencoder.fit_generator(generator=train_generator,
validation_data=val_generator,
callbacks=callback_image)
В моем случае, когда я отображаю карты внимания (в виде тепловых карт) на тензорной доске, это вывод.