web-dev-qa-db-fra.com

Tensorflow: comment afficher des images personnalisées dans Tensorboard (par exemple, Matplotlib Plots)

La section Image Dashboard du Tensorboard ReadMe indique:

Étant donné que le tableau de bord d'image prend en charge des pngs arbitraires, vous pouvez l'utiliser pour intégrer des visualisations personnalisées (par exemple, des nuages ​​de points matplotlib) dans TensorBoard.

Je vois comment une image pyplot pourrait être écrite dans un fichier, relue en tant que tenseur, puis utilisée avec tf.image_summary () pour l'écrire sur TensorBoard, mais cette déclaration du fichier Lisez-moi suggère qu'il existe un moyen plus direct. Y a-t-il? Dans l'affirmative, existe-t-il d'autres documents et/ou exemples sur la manière de procéder efficacement?

27
RobR

C'est assez facile à faire si vous avez l'image dans une mémoire tampon. Ci-dessous, je montre un exemple, où un pyplot est enregistré dans un tampon puis converti en une représentation d'image TF qui est ensuite envoyée à un résumé d'image.

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

Cela donne la visualisation TensorBoard suivante:

enter image description here

40
Andrzej Pronobis

Un peu tard avec ma réponse. Avec tf-matplotlib un simple nuage de points se résume à:

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)

Une fois exécuté, cela donne le tracé suivant dans Tensorboard 

Notez que tf-matplotlib prend soin d'évaluer toutes les entrées de tenseur, évite pyplot les problèmes de thread et prend en charge le blitting pour le traçage critique à l'exécution.

8
cheind

Le script suivant n'utilise pas l'encodage RVB/PNG intermédiaire. Il résout également le problème avec la construction d'opérations supplémentaires lors de l'exécution, un seul résumé est réutilisé.

La taille de la figure devrait rester la même pendant l'exécution

Solution qui fonctionne:

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)
7
y.selivonchyk

Cela vise à compléter la réponse d'Andrzej Pronobis. En suivant de près son article de Nice, j'ai mis en place cet exemple de travail minimal :

    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)

Où écrivain est une instance de tf.summary.FileWriter . Cela m'a donné l'erreur suivante: AttributeError: l'objet 'Tensor' n'a pas d'attribut 'value' Pour lequel ce post github avait la solution: le résumé doit être évalué (converti en chaîne) avant d'être ajouté à l'auteur . Ainsi, le code de travail pour moi est resté comme suit (ajoutez simplement l'appel .eval () à la dernière ligne):

    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)

Cela pourrait être assez court pour être un commentaire sur sa réponse, mais ceux-ci peuvent être facilement ignorés (et je fais peut-être autre chose aussi), alors voilà, j'espère que cela aide!

À votre santé,
Andres

1
fr_andres