Tensorflow: как отображать пользовательские изображения в Tensorboard (например, графики Matplotlib)
на Панель Изображения из Tensorboard ридми написано:
поскольку панель мониторинга изображений поддерживает произвольные png, вы можете использовать ее для встраивания пользовательских визуализаций (например, диаграмм рассеяния matplotlib) в TensorBoard.
Я вижу, как изображение pyplot может быть записано в файл, прочитано как тензор, а затем использовано с tf.image_summary (), чтобы записать его в TensorBoard, но это утверждение из readme предполагает, что есть больше прямой путь. Есть? Если да, то есть ли какая-либо дополнительная документация и/или примеры того, как это сделать эффективно?
4 ответов
Это довольно легко сделать, если у вас есть изображения в буферной памяти. Ниже я показываю пример, где pyplot сохраняется в буфер, а затем преобразуется в представление изображения TF, которое затем отправляется в сводку изображений.
import io
import matplotlib.pyplot as plt
import tensorflow as tf
def gen_plot():
"""Create a pyplot plot and save to buffer."""
plt.figure()
plt.plot([1, 2])
plt.title("test")
buf = io.BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)
return buf
# Prepare the plot
plot_buf = gen_plot()
# Convert PNG buffer to TF image
image = tf.image.decode_png(plot_buf.getvalue(), channels=4)
# Add the batch dimension
image = tf.expand_dims(image, 0)
# Add image summary
summary_op = tf.summary.image("plot", image)
# Session
with tf.Session() as sess:
# Run
summary = sess.run(summary_op)
# Write summary
writer = tf.train.SummaryWriter('./logs')
writer.add_summary(summary)
writer.close()
Это дает следующие визуализации TensorBoard:
следующий скрипт не использует промежуточную кодировку RGB/PNG. Он также устраняет проблему с дополнительной конструкцией операции во время выполнения, повторно используется Единая сводка.
ожидается, что размер фигуры останется неизменным во время выполнения
решение, которое работает:
import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np
def get_figure():
fig = plt.figure(num=0, figsize=(6, 4), dpi=300)
fig.clf()
return fig
def fig2rgb_array(fig, expand=True):
fig.canvas.draw()
buf = fig.canvas.tostring_rgb()
ncols, nrows = fig.canvas.get_width_height()
shape = (nrows, ncols, 3) if not expand else (1, nrows, ncols, 3)
return np.fromstring(buf, dtype=np.uint8).reshape(shape)
def figure_to_summary(fig):
image = fig2rgb_array(fig)
summary_writer.add_summary(
vis_summary.eval(feed_dict={vis_placeholder: image}))
if __name__ == '__main__':
# construct graph
x = tf.Variable(initial_value=tf.random_uniform((2, 10)))
inc = x.assign(x + 1)
# construct summary
fig = get_figure()
vis_placeholder = tf.placeholder(tf.uint8, fig2rgb_array(fig).shape)
vis_summary = tf.summary.image('custom', vis_placeholder)
with tf.Session() as sess:
tf.global_variables_initializer().run()
summary_writer = tf.summary.FileWriter('./tmp', sess.graph)
for i in range(100):
# execute step
_, values = sess.run([inc, x])
# draw on the plot
fig = get_figure()
plt.subplot('111').scatter(values[0], values[1])
# save the summary
figure_to_summary(fig)
немного поздно с моим ответом. С 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
проблемы с потоками и поддержка blitting для критического построения во время выполнения.
Это намеревается завершить ответ Анджея Пронобиса. Следуя внимательно его хороший пост, я установил это минимальный рабочий пример:
plt.figure()
plt.plot([1, 2])
plt.title("test")
buf = io.BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)
image = tf.image.decode_png(buf.getvalue(), channels=4)
image = tf.expand_dims(image, 0)
summary = tf.summary.image("test", image, max_outputs=1)
writer.add_summary(summary, step)
где writer является экземпляром tf.резюме.FileWriter. Это дало мне следующую ошибку: AttributeError: объект 'Tensor' не имеет атрибута 'value' За что это сообщение github имел решение: сводка должна быть оценена (преобразована в строку) перед тем, как добавил писатель. Поэтому рабочий код для меня остался следующим (просто добавьте .eval () вызов в последней строке):
plt.figure()
plt.plot([1, 2])
plt.title("test")
buf = io.BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)
image = tf.image.decode_png(buf.getvalue(), channels=4)
image = tf.expand_dims(image, 0)
summary = tf.summary.image("test", image, max_outputs=1)
writer.add_summary(summary.eval(), step)
Это может быть достаточно коротким, чтобы быть комментарием к его ответу, но их можно легко пропустить (и я могу делать что-то еще другое), так что вот, надеюсь, это поможет!
спасибо,
Андрес!--5-->