Python Tensorflow:如何在 Tensorboard 中显示自定义图像(例如 Matplotlib 图)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38543850/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 21:06:54  来源:igfitidea点击:

Tensorflow: How to Display Custom Images in Tensorboard (e.g. Matplotlib Plots)

pythonmatplotlibtensorflowtensorboard

提问by RobR

The Image Dashboardsection of the Tensorboard ReadMe says:

Tensorboard 自述文件的图像仪表板部分说:

Since the image dashboard supports arbitrary pngs, you can use this to embed custom visualizations (e.g. matplotlib scatterplots) into TensorBoard.

由于图像仪表板支持任意 png,您可以使用它来将自定义可视化(例如 matplotlib 散点图)嵌入到 TensorBoard 中。

I see how a pyplot image could be written to file, read back in as a tensor, and then used with tf.image_summary() to write it to TensorBoard, but this statement from the readme suggests there is a more direct way. Is there? If so, is there any further documentation and/or examples of how to do this efficiently?

我看到如何将 pyplot 图像写入文件,作为张量读回,然后与 tf.image_summary() 一起使用以将其写入 TensorBoard,但自述文件中的此语句表明有一种更直接的方法。在那儿?如果是这样,是否有任何进一步的文档和/或示例说明如何有效地做到这一点?

回答by Andrzej Pronobis

It is quite easy to do if you have the image in a memory buffer. Below, I show an example, where a pyplot is saved to a buffer and then converted to a TF image representation which is then sent to an image summary.

如果您将图像放在内存缓冲区中,这很容易做到。下面,我展示了一个示例,其中将 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()

This gives the following TensorBoard visualization:

这给出了以下 TensorBoard 可视化:

enter image description here

在此处输入图片说明

回答by y.selivonchyk

Next script does not use intermediate RGB/PNG encoding. It also fixes the issue with additional operation construction during execution, single summary is reused.

Next 脚本不使用中间 RGB/PNG 编码。它还解决了在执行期间附加操作构造的问题,重复使用单个摘要。

Size of the figure is expected to remain the same during execution

预计在执行期间图形的大小将保持不变

Solution that works:

有效的解决方案:

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)

回答by cheind

A bit late with my answer. With tf-matplotliba simple scatter plot boils down to:

我的回答有点晚了。使用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)

When executed, this results in the following plot inside Tensorboard

执行时,这会在 Tensorboard 中生成以下图

Note that tf-matplotlibtakes care about evaluating any tensor inputs, avoids pyplotthreading issues and supports blitting for runtime critical plotting.

请注意,tf-matplotlib负责评估任何张量输入,避免pyplot线程问题并支持用于运行时关键绘图的 blitting。

回答by subjord

Finally there is some official documentationabout "Logging arbitrary image data" with an example of matplotlib created images.

最后有一些关于“记录任意图像数据”的官方文档,其中包含一个 matplotlib 创建的图像示例。

回答by fr_andres

This intends to complete Andrzej Pronobis' answer. Following closely his nice post, I set up this minimal working example:

这打算完成 Andrzej Pronobis 的回答。密切关注他的好帖子,我设置了这个最小的工作示例

    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)

Where writer is an instance of tf.summary.FileWriter. This gave me the following error: AttributeError: 'Tensor' object has no attribute 'value'For which this github posthad the solution: the summary has to be evaluated (converted into a string) before being added to the writer. So the working code for me remained as follows (simply add the .eval() call in the last line):

其中 writer 是tf.summary.FileWriter 的一个实例。这给了我以下错误: AttributeError: 'Tensor' object has no attribute 'value'对于这个 github post有解决方案:在将摘要添加到 writer 之前,必须对其进行评估(转换为字符串)。所以我的工作代码如下(只需在最后一行添加 .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)

This could be short enough to be a comment on his answer, but these can be easily overlooked (and I may be doing something else different too), so here it is, hope it helps!

这可能足够短,可以作为对他的回答的评论,但这些很容易被忽视(我也可能在做其他不同的事情),所以就在这里,希望它有所帮助!

Cheers,
Andres

干杯,
安德烈斯