0

Wenn ich schaffen train_op wie folgt aus:Modell scheint mit Optimizer.minimize() werden Überanpassung aber nicht tf.contrib.layers.optimize_loss()

train_op = tf.contrib.layers.optimize_loss(
    loss=loss, 
    global_step=tf.contrib.framework.get_global_step(), 
    learning_rate=params['learning_rate'], 
    optimizer='Adam' 
) 

ich ein funktionierendes Netzwerk erhalten, die gut auf die Validierung durchführt und Testsätze.

Wenn ich nur minimize() Methode wie folgt verwenden:

optimizer = tf.train.AdamOptimizer(learning_rate=params['learning_rate']) 
train_op = optimizer.minimize(
    loss=loss, 
    global_step=tf.train.get_global_step() 
) 

ich viel schlechtere Ergebnisse (Präzision, Rückruf, Verlust) sogar auf der ersten Validierung nach 1000 Schritte, und nach einer Weile scheint es, wie es vollständig übersteuert (Verlust bei der Validierung ist mehr oder weniger konstant und ist 100x Zugverlust, aber Präzision und Rückruf crash)

Ich habe eine Funktion erstellt, die von contrib eine aufgereinigte Version ist, die sich von gerade Optimizer.minimize() unterscheidet zwei markierte Orte:

def make_train_op(loss, optimizer, global_step): 
    with tf.variable_scope(None, "OptimizeLoss", [loss, global_step]): 

     # ========================================== 
     # this part is extra comparing to minimize() 
     update_ops = set(tf.get_collection(tf.GraphKeys.UPDATE_OPS)) 
     if update_ops: 
      with tf.control_dependencies([update_ops]): 
       loss = tf.identity(loss) 
     # ========================================== 

     gradients = optimizer.calculate_gradients(
      loss, 
      tf.trainable_variables() 
     ) 

     grad_updates = optimizer.apply_gradients(
      gradients, 
      global_step=global_step, 
      name="train") 

     # ========================================== 
     # so is this one 
     with tf.control_dependencies([grad_updates]): 
      train_op = tf.identity(loss) 
     # ========================================== 
     return train_op 

Und Validierung funktioniert wieder gut. Das Training sieht in allen Fällen mehr oder weniger gleich (und gesund) aus. Netzwerk ist relativ einfach CNN/Batchnorm/Dropout/Maxpool Mix mit Cross-Entropie-Verlust.

Die Weise, die ich verstehe, ist, dass es einige Operationen gibt, die Teil eines Graphen sind, die nicht als Abhängigkeiten für Verlust erscheinen, aber die zum Berechnen von Gradienten benötigt werden. Wie ist das überhaupt möglich? Wenn das eine normale Situation ist, warum sind diese beiden Snippets nicht Teil eines Kerns? Hätte ich beim Erstellen eines Modells etwas anderes machen sollen, um diese Abhängigkeitszwang zu vermeiden?

Antwort

1

Das Problem ist mit batchnorm Update-Operationen, und es ist eigentlich documented:

Hinweis: beim Training, die moving_mean und moving_variance müssen aktualisiert werden. Standardmäßig werden die Update-Ops in tf.GraphKeys.UPDATE_OPS platziert, daher müssen sie als Abhängigkeit zum train_op hinzugefügt werden. Zum Beispiel:

update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) 
with tf.control_dependencies(update_ops): 
    train_op = optimizer.minimize(loss) 
Verwandte Themen