2017-09-24 3 views
8

Ich mache ein paar Experimente mit TensorFlow und habe einen Haken gefunden. Ich versuche, TF zu verwenden, um eine Änderung in einem Modell zu bewerten, dann das Modell basierend auf der resultierenden Änderung der Verlustfunktion beizubehalten oder zurückzusetzen. Ich habe den harten Teil (bedingte Kontrolle) herausgefunden, aber ich stecke auf etwas fest, das ziemlich einfach sein sollte: Ich kann nicht scheinen, tf.trainable_variables für eine Iteration zu speichern, dann stelle es bei Bedarf wieder her.Wie kann ich Tensors auf einen früheren Wert zurücksetzen, ohne den Wert auf der Festplatte zu speichern?

Sagen wir, ein Build einen Op:

... 
store_trainable_vars = [] 

for v in tf.trainable_variables(): 

    store_trainable_vars.append(v) 
... 

Dann später, ich will tf.trainable_variables auf den Wert wiederherzustellen es hatte, als diese Op letzten Lauf war. Ich würde wollen, wie etwas tun:

def reject_move(): 

    revert_state = [] 

    for (v, s) in zip(tf.trainable_variables(), store_trainable_vars): 

     revert_state.append(tf.assign(v, s, name="revert_state")) 

    return(revert_state) 

Offensichtlich wird dies neu bewerten store_trainable_vars, die wiederum Links auf den aktuellen Wert von tf.trainable_variables(), so dass keine revert_state Op. Ich brauche eine Möglichkeit, den Wert von Tensors zu speichern und abzurufen, ohne auf den aktuellen Wert dieser Tensoren zurückzugreifen. So etwas wie

... 
store_trainable_vars = [] 

for v in tf.trainable_variables(): 

    store_trainable_vars.append(v.value_right_now()) 
... 

wo v.value_right_now() eine Konstante zurückgibt, die bis überschrieben wird sich nicht ändern.

Ich weiß, ich könnte Saver verwenden, aber diese Lösung schreibt auf die Festplatte, die für diese Anwendung nicht akzeptabel ist, da es in einer Trainingsschleife ausgeführt wird.

Ich vermisse wahrscheinlich etwas offensichtlich - jede Anleitung wäre willkommen.

Antwort

1

Es war nicht meine ursprüngliche Absicht, diese Frage selbst zu beantworten, aber ich habe eine Methode entwickelt, die ziemlich gut funktioniert. Also dachte ich, ich würde es teilen. Der Schlüssel Einblick kam aus this sehr clevere Antwort. Der Ansatz besteht darin, die für die initiale Variablenzuweisung erstellten Zuweisungsknoten wiederzuverwenden. Eine vollständige Klasse, die diesen Ansatz implementiert, wird nachstehend angegeben.

import tensorflow as tf 


class TensorFlowState(object): 

    def __init__(self): 

     # Get the graph. 
     graph = tf.get_default_graph() 

     # Extract the global varibles from the graph. 
     self.gvars = graph.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) 

     # Exract the Assign operations for later use. 
     self.assign_ops = [graph.get_operation_by_name(v.op.name + "/Assign") 
          for v in self.gvars] 

     # Extract the initial value ops from each Assign op for later use. 
     self.init_values = [op.inputs[1] for op in self.assign_ops] 

    def start(self, sess): 

     self.sess = sess 

    def store(self): 

     # Record the current state of the TF global varaibles 
     self.state = self.sess.run(self.gvars) 

    def restore(self): 
    # Create a dictionary of the iniailizers and stored state of globals. 
    feed_dict = {init_value: val 
       for init_value, val in zip(self.init_values, self.state)} 

    # Use the initializer ops for each variable to load the stored values. 
    return(self.sess.run(self.assign_ops, feed_dict=feed_dict)) 

zu nutzen, einfach die Klasse instanziiert, die start Methode aufrufen, eine tf.Session, passieren und die store und restore Methoden aufrufen, wie in Ihrem Imperativ Trainingsschleife benötigt. Ich habe diese Implementierung verwendet, um einen Optimierer zu erstellen, der ungefähr so ​​schnell läuft wie die Gradientenoptimierer, die in TensorFlow enthalten sind.

5

Zur Wiederherstellung eines Graphen Zustand manuell müssen Sie tf.tuple oder tf.group Betrieb verwenden, die den Fluss für eine Massenänderung ändern wird:

Dieses ein Tupel von Tensoren mit den gleichen Werten wie die Tensoren schafft Argument , außer dass der Wert jedes Tensors erst zurückgegeben wird, nachdem die Werte aller Tensoren berechnet wurden.

[Update] Hier ist, wie ich es tun würde:

import numpy as np 
import tensorflow as tf 

x = tf.placeholder(shape=[None, 5], dtype=tf.float32, name='x') 
W = tf.Variable(np.zeros([5, 5]), dtype=tf.float32, name='W') 
b = tf.Variable(np.zeros([5]), dtype=tf.float32, name='b') 
y = tf.add(tf.matmul(x, W), b) 

with tf.Session() as session: 
    batch = np.ones([2, 5]) 
    session.run(tf.global_variables_initializer()) 
    print session.run(y, feed_dict={x: batch})  # prints [2, 5] zeros 

    # store the current value 
    store = {v.name: v.eval(session) for v in tf.trainable_variables()} 
    print store          # prints [5, 5] and [5] zeros 

    # update 
    new = {'W:0': np.ones([5, 5]), 'b:0': np.ones([5])} 
    session.run(tf.tuple([tf.assign(var, new[var.name]) for var in tf.trainable_variables()])) 
    print session.run(y, feed_dict={x: batch})  # prints [2, 5] sixes 

    # restore 
    session.run(tf.tuple([tf.assign(var, store[var.name]) for var in tf.trainable_variables()])) 
    print session.run(y, feed_dict={x: batch})  # prints [2, 5] zeros again 

Aber ich glaube wirklich, Sie Ihre Entscheidung über Saver überdenken sollte, weil es entworfen wurde, als auch in einer Trainingsschleife verwendet werden soll . Intern erledigt Saver die ganze knifflige Arbeit für Sie (insbesondere, es ist Wiederherstellen Op Aufrufe tf.group und , falls erforderlich), die sonst die Quelle von ziemlich böse Bugs werden könnte. Außerdem ist die Platte (fast) immer größer als Ihre GPU und der Hauptspeicher. Wenn Sie es sich also leisten können, das Modell im Speicher zu speichern, sollten Sie es auch auf der Festplatte speichern können.

Hier sind some parameters, die die Proliferation von Checkpoint-Dateien auf der Festplatte steuern helfen:

  • max_to_keep gibt die maximale Anzahl der letzten Checkpoint-Dateien halten. Wenn neue Dateien erstellt werden, werden ältere Dateien gelöscht. Wenn Keine oder 0, werden alle Prüfpunktdateien beibehalten. Der Standardwert ist 5 (das heißt, die 5 letzten Checkpoint-Dateien werden beibehalten).
  • keep_checkpoint_every_n_hours: Zusätzlich zu den neuesten max_to_keep Checkpoint-Dateien, möchten Sie möglicherweise eine Prüfpunktdatei für jede N Stunden des Trainings halten. Dies kann nützlich sein, wenn Sie später analysieren möchten, wie sich ein Modell während einer langen Trainingseinheit entwickelt hat. Für Beispiel, Übergeben stellt sicher, dass Sie eine Prüfpunktdatei für alle 2 Stunden des Trainings halten. Der Standardwert von 10.000 Stunden deaktiviert die Funktion effektiv.

[Update] Wie in den Kommentaren zu klären, ist das Hauptanliegen Datenträgerlatenz, die die Ausbildung verlangsamen kann, wenn zu oft abgerufen. Wenn Sie Linux verwenden, verwendet es häufig caches Festplattenseiten, Windows does it. Wenn Sie jedoch absolut sicher sein möchten, sollten Sie in Betracht ziehen, tmpfs zu verwenden.

+0

Ich sollte klarstellen: Als ich sagte, ich wollte nicht auf die Festplatte schreiben, war es nicht, weil ich über Raum besorgt war. Diese Speicherung und Wiederherstellung findet im schlimmsten Fall bei jeder Iteration statt. Es ist die Laufzeitstrafe für das Zurückgreifen auf die Festplatte, die ich vermeiden möchte. Können Sie Ihre Antwort bearbeiten, um stattdessen eine triviale Verwendung von 'tf.group' für die Wiederherstellung von Graphen zu demonstrieren? (oder verlinke einfach auf ein solches Beispiel) –

Verwandte Themen