web-dev-qa-db-fra.com

Comment afficher des images personnalisées dans TensorBoard à l'aide de Keras?

Je travaille sur un problème de segmentation à Keras et je souhaite afficher les résultats de la segmentation à la fin de chaque époque d'entraînement.

Je souhaite quelque chose de similaire à Tensorflow: comment afficher des images personnalisées dans Tensorboard (tracés Matplotlib, par exemple) , à l’aide de Keras. Je sais que Keras a le TensorBoard callback, mais il semble limité à cette fin.

Je sais que cela briserait l'abstraction du backend de Keras, mais je suis intéressé par l'utilisation du backend de TensorFlow.

Est-il possible d'y parvenir avec Keras + TensorFlow?

13
Fábio Perez

Donc, la solution suivante fonctionne bien pour moi:

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

Passez simplement le rappel à fit ou fit_generator.

Notez que vous pouvez également exécuter certaines opérations en utilisant la variable model dans le rappel. Par exemple, vous pouvez exécuter le modèle sur certaines images pour vérifier ses performances.

 screen

19
Fábio Perez

De même, vous voudrez peut-être essayer tf-matplotlib . Voici un diagramme de dispersion

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)

Lorsqu'il est exécuté, le résultat est le tracé suivant dans Tensorboard

Notez que tf-matplotlib prend le soin d'évaluer toutes les entrées de tenseur, évite les problèmes de threads pyplot et prend en charge le blitting pour les tracés critiques à l'exécution.

2
cheind

Sur la base des réponses ci-dessus et de ma propre recherche, je fournis le code suivant pour terminer les opérations suivantes en utilisant TensorBoard dans Keras:


  • configuration du problème: pour prédire la carte de disparité dans l'appariement stéréo binoculaire;
  • pour alimenter le modèle avec l'entrée image gauche x et la carte de disparité de vérité au sol gt;
  • pour afficher l'entrée x et la vérité au sol 'gt', à un moment donné de l'itération;
  • pour afficher la sortie y de votre modèle, à un moment donné.

  1. Tout d'abord, vous devez créer votre classe de rappel costumé avec Callback. Note qu'un rappel a accès à son modèle associé via la propriété de classe self.model. De même, Note: vous devez alimenter le modèle avec feed_dict si vous souhaitez obtenir et afficher la sortie de votre modèle. 

    from keras.callbacks import Callback
    import numpy as np
    from keras import backend as K
    import tensorflow as tf
    
    # 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_inputd_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)
    
  2. Ensuite, passez cet objet de rappel à fit_generator() pour votre modèle, par exemple:

       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)
       ...
    
  3. Maintenant, vous pouvez exécuter le code et aller sur l'hôte TensorBoard pour voir l'affichage de l'image costumée. Par exemple, voici ce que j’ai obtenu en utilisant le code susmentionné:  enter image description here


    Terminé! Prendre plaisir!

1
ccj5351

Voici un exemple comment dessiner des points de repère sur une image:

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
0
mrgloom

Je pense avoir trouvé un meilleur moyen de consigner ces images personnalisées sur tensorboard en utilisant le tf-matplotlib. Voici comment...

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

Il suffit d’écraser la méthode _make_histogram_ops de la classe de rappel TensorBoard pour ajouter le résumé personnalisé. Dans mon cas, le create_dtw_image est une fonction qui crée une image à l'aide de tf-matplotlib.

Cordialement,.

0