40 votes

Comment faire la moyenne des résumés sur plusieurs lots ?

En supposant que j'ai un tas de résumés définis comme :

loss = ...
tf.scalar_summary("loss", loss)
# ...
summaries = tf.merge_all_summaries()

Je peux évaluer le summaries à quelques reprises sur les données d'apprentissage et transmet le résultat à une fonction SummaryWriter . Le résultat sera des résumés bruités, car ils ne sont calculés que sur un seul lot.

Cependant, je voudrais calculer les résumés sur l'ensemble des données de validation. Bien sûr, je ne peux pas passer l'ensemble de données de validation comme un lot unique, car il serait trop grand. Donc, j'obtiendrai des sorties de résumé pour chaque lot de validation.

Existe-t-il un moyen de faire la moyenne de ces résumés de façon à ce qu'il apparaisse comme si les résumés avaient été calculés sur l'ensemble de la validation ?

49voto

Tom Points 813

Faites la moyenne de votre mesure en Python et créez un nouvel objet Summary pour chaque moyenne. Voici ce que je fais :

accuracies = []

# Calculate your measure over as many batches as you need
for batch in validation_set:
  accuracies.append(sess.run([training_op]))

# Take the mean of you measure
accuracy = np.mean(accuracies)

# Create a new Summary object with your measure
summary = tf.Summary()
summary.value.add(tag="%sAccuracy" % prefix, simple_value=accuracy)

# Add it to the Tensorboard summary writer
# Make sure to specify a step parameter to get nice graphs over time
summary_writer.add_summary(summary, global_step)

1 votes

Super, je ne savais pas qu'il y avait une API pour construire l'objet résumé directement dans le code python. C'est logique, puisque c'est juste un tampon de protocole.

0 votes

Que signifie le préfixe ici ?

10voto

MZHm Points 1094

Je voudrais éviter calcul de la moyenne à l'extérieur de le graphique.

Vous pouvez utiliser tf.train.ExponentielMouvementMoyen :

ema = tf.train.ExponentialMovingAverage(decay=my_decay_value, zero_debias=True)
maintain_ema_op = ema.apply(your_losses_list)

# Create an op that will update the moving averages after each training step.
with tf.control_dependencies([your_original_train_op]):
    train_op = tf.group(maintain_ema_op)

Alors, utilisez :

sess.run(train_op)

Cela appellera maintain_ema_op car elle est définie comme une dépendance de contrôle.

Afin d'obtenir vos moyennes mobiles exponentielles, utilisez :

moving_average = ema.average(an_item_from_your_losses_list_above)

Et récupérez sa valeur en utilisant :

value = sess.run(moving_average)

Cela calcule la moyenne mobile dans votre graphique de calcul .

2 votes

@MZHn pourquoi est-il préférable de laisser TF faire les calculs en interne ? Est-ce beaucoup plus rapide ? (il semble que Python puisse très bien gérer une opération de calcul de moyenne).

1 votes

@DankMasterDan Lorsque tout est géré par Tensorflow, chaque opération sera exécutée sur le GPU (en supposant que vous utilisez Tensorflow GPU dans ce cas). Par conséquent, le changement de point d'exécution du GPU au CPU (où le code Python s'exécute) prendra quelques horloges pour se terminer. Ce temps peut devenir un goulot d'étranglement pour le GPU qui doit attendre que le gestionnaire poursuive son traitement sur de grands tableaux de données. Cependant, en traitant cette tâche simple avec Tensorflow, elle peut être parallélisée comme d'autres nœuds dans le graphe de calcul, sans avoir besoin de faire des allers-retours entre le CPU et le GPU.

0 votes

@MZHm Qu'est-ce que an_item_from_your_losses_list_above censé être ? Pouvez-vous s'il vous plaît montrer la création de : your_losses_list ? J'ai essayé de créer un np.array() vide et d'y ajouter des tenseurs dans le cadre de la dépendance du contrôle. Lorsque j'appelle ema.average(list_of_loss_tensors) J'ai compris : TypeError: unhashable type: 'numpy.ndarray' . Qu'est-ce qui devrait être utilisé à la place d'une liste ou de numpy.ndarray, comme conteneur pour les pertes ? Un tf.placeholder de taille num_losses ?

8voto

Maikefer Points 316

Je pense que c'est toujours mieux de laisser tensorflow faire les calculs.

Jetez un coup d'œil aux mesures du streaming. Ils ont une fonction de mise à jour pour fournir les informations de votre lot actuel et une fonction pour obtenir le résumé moyen. Cela va ressembler à ceci :

accuracy = ... 
streaming_accuracy, streaming_accuracy_update = tf.contrib.metrics.streaming_mean(accuracy)
streaming_accuracy_scalar = tf.summary.scalar('streaming_accuracy', streaming_accuracy)

# set up your session etc. 

for i in iterations:
      for b in batches:
               sess.run([streaming_accuracy_update], feed_dict={...})

     streaming_summ = sess.run(streaming_accuracy_scalar)
     writer.add_summary(streaming_summary, i)

Consultez également la documentation de tensorflow : https://www.tensorflow.org/versions/master/api_guides/python/contrib.metrics

et cette question : Comment accumuler des statistiques sommaires dans tensorflow ?

0 votes

Il faut aussi que ` sess.run(tf.local_variables_initializer())` avant l'accumulation.

0 votes

Si seulement tf.metrics fonctionnait avec une exécution rapide, mais ça ne semble pas être le cas. Existe-t-il une approche analogue à celle-ci pour eager exec ? Sinon, il semble que nous devions faire le calcul nous-mêmes dans certains cas si nous voulons être flexibles entre compilé et eager...

3voto

sygi Points 3260

Vous pouvez enregistrer la moyenne de la somme actuelle et recalculer la moyenne après chaque lot, comme suit :

loss_sum = tf.Variable(0.)
inc_op = tf.assign_add(loss_sum, loss)
clear_op = tf.assign(loss_sum, 0.)
average = loss_sum / batches
tf.scalar_summary("average_loss", average)

sess.run(clear_op)
for i in range(batches):
    sess.run([loss, inc_op])

sess.run(average)

0 votes

Cela n'ajouterait-il pas un nouveau résumé scalaire au graphique à chaque fois que le code est exécuté ?

0 votes

Oui, je pensais que vous alliez l'exécuter une seule fois (bien que maintenant je vois que cela n'a pas de sens). Je modifie maintenant...

0 votes

Cela semble plausible. Cependant, j'aimerais qu'il y ait une solution plus élégante... Je n'en ai pas trouvé (voir ma solution de fortune).

1voto

jdehesa Points 22254

Pour référence future, l'API de métrique TensorFlow prend désormais en charge cette fonction par défaut. Par exemple, regardez tf.mean_squared_error :

Pour l'estimation de la métrique sur un flux de données, la fonction crée un fichier update_op qui met à jour ces variables et renvoie l'opération mean_squared_error . En interne, un squared_error calcule le carré par éléments de la différence entre predictions y labels . Ensuite, update_op incréments total avec la somme réduite du produit de weights y squared_error et il incrémente count avec la somme réduite de weights .

Ces total y count sont ajoutées à l'ensemble des variables métriques, donc en pratique, ce que vous feriez est quelque chose comme :

x_batch = tf.placeholder(...)
y_batch = tf.placeholder(...)
model_output = ...
mse, mse_update = tf.metrics.mean_squared_error(y_batch, model_output)
# This operation resets the metric internal variables to zero
metrics_init = tf.variables_initializer(
    tf.get_default_graph().get_collection(tf.GraphKeys.METRIC_VARIABLES))
with tf.Session() as sess:
    # Train...
    # On evaluation step
    sess.run(metrics_init)
    for x_eval_batch, y_eval_batch in ...:
        mse = sess.run(mse_update, feed_dict={x_batch: x_eval_batch, y_batch: y_eval_batch})
    print('Evaluation MSE:', mse)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X