2017-02-08 2 views
3

ich eine grobe Methode umzusetzen versuche bezogen auf das Gemisch-of-Experts Papier in tensorflow-https://arxiv.org/abs/1701.06538Mischung aus Experten - Train beste Modell nur bei jeder Iteration

Es würde n Modelle definiert sein:

model_1: 
     var_11 
     var_12 
     loss_1 
     optimizer_1 

    model_2: 
     var_21 
     var_22 
     loss_2 
     optimizer_2 

    model_3: 
     var_31 
     var_32 
     loss_3 
     optimizer_3 

Bei jeder Iteration möchte ich das Modell mit dem geringsten Verlust trainieren, während die anderen Variablen konstant bleiben. Ist es möglich, einen Schalter zu platzieren, um nur einen der Optimizer auszuführen?

S.: Diese Basis dieses Problems ist ähnlich einer, die ich zuvor gefragt hatte. http://stackoverflow.com/questions/42073239/tf-get-collection-to-extract-variables-of-one-scope/42074009?noredirect=1#comment71359330_42074009

Da der Vorschlag dort nicht funktioniert habe, versuche ich, das Problem anders anzugehen.

Vielen Dank im Voraus!

Antwort

4

Dies scheint mit tf.cond machbar zu sein:

import tensorflow as tf 

def make_conditional_train_op(
    should_update, optimizers, variable_lists, losses): 
    """Conditionally trains variables. 

    Each argument is a Python list of Tensors, and each list must have the same 
    length. Variables are updated based on their optimizer only if the 
    corresponding `should_update` boolean Tensor is True at a given step. 

    Returns a single train op which performs the conditional updates. 
    """ 
    assert len(optimizers) == len(variable_lists) 
    assert len(variable_lists) == len(losses) 
    assert len(should_update) == len(variable_lists) 
    conditional_updates = [] 
    for model_number, (update_boolean, optimizer, variables, loss) in enumerate(
     zip(should_update, optimizers, variable_lists, losses)): 
    conditional_updates.append(
     tf.cond(update_boolean, 
       lambda: tf.group(
        optimizer.minimize(loss, var_list=variables), 
        tf.Print(0, ["Model {} updating".format(model_number), loss])), 
       lambda: tf.no_op())) 
    return tf.group(*conditional_updates) 

Die grundlegende Strategie des variablen Updates im lambda eines der cond Zweige definieren des Optimierers sicher zu machen, in welchem ​​Fall es wahr bedingte op Ausführung, dh die Zuordnung zu Variablen (und Optimizer-Akkumulatoren) erfolgt nur, wenn dieser Zweig der cond ausgelöst wird.

Als Beispiel können wir einige Modelle konstruieren:

def make_model_and_optimizer(): 
    scalar_variable = tf.get_variable("scalar", shape=[]) 
    vector_variable = tf.get_variable("vector", shape=[3]) 
    loss = tf.reduce_sum(scalar_variable * vector_variable) 
    optimizer = tf.train.AdamOptimizer(0.1) 
    return optimizer, [scalar_variable, vector_variable], loss 

# Construct each model 
optimizers = [] 
variable_lists = [] 
losses = [] 
for i in range(10): 
    with tf.variable_scope("model_{}".format(i)): 
    optimizer, variables, loss = make_model_and_optimizer() 
    optimizers.append(optimizer) 
    variable_lists.append(variables) 
    losses.append(loss) 

Dann eine bedingte Aktualisierungsstrategie bestimmen, nur in diesem Fall mit dem maximalen Verlust Trainieren des Modells (nur weil das in mehr Schalt führt, der Ausgang wenn nur ein Modell überhaupt ist eher langweilig aktualisiert):

# Determine which model should be updated (in this case, the one with the 
# maximum loss) 
integer_one_hot = tf.one_hot(
    tf.argmax(tf.stack(losses), 
       axis=0), 
    depth=len(losses)) 
is_max = tf.equal(
    integer_one_hot, 
    tf.ones_like(integer_one_hot)) 

Schließlich können wir die make_conditional_train_op Funktion aufrufen, den Zug op zu schaffen, dann einige Trainings Iterationen tun:

train_op = make_conditional_train_op(
    tf.unstack(is_max), optimizers, variable_lists, losses) 

# Repeatedly call the conditional train op 
with tf.Session(): 
    tf.global_variables_initializer().run() 
    for i in range(20): 
    print("Iteration {}".format(i)) 
    train_op.run() 

Dies wird den Druck des Index, und der Verlust bei jeder Iteration aktualisiert wird, die bedingte Ausführung bestätigt:

Iteration 0 
I tensorflow/core/kernels/logging_ops.cc:79] [Model 6 updating][2.7271919] 
Iteration 1 
I tensorflow/core/kernels/logging_ops.cc:79] [Model 6 updating][2.1755948] 
Iteration 2 
I tensorflow/core/kernels/logging_ops.cc:79] [Model 2 updating][1.9858969] 
Iteration 3 
I tensorflow/core/kernels/logging_ops.cc:79] [Model 6 updating][1.6859927] 
+0

genau das, was ich suchte. Vielen Dank! – viggie

+0

Wie würden Sie dies auf eine Charge anwenden? –

+0

Das ist einfach genug für so etwas wie einen reinen Gradienten-Sinkoptimierer (finde den min, dann 'tf.gather' nur diesen Teil des Stapels, wenn der Verlust berechnet wird, der optimiert wird). Das Problem ist für Optimierer wie Adam, die Momentum-Updates haben; da kenne ich keinen allgemeinen Weg, ohne in die Implementierung des Optimierers einzutauchen. Vielleicht möchten Sie eine neue Frage mit weiteren Details zu dem, was Sie tun möchten, starten (und zögern Sie nicht, mich darüber zu informieren, wenn Sie keine Antwort erhalten). –

Verwandte Themen