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]
genau das, was ich suchte. Vielen Dank! – viggie
Wie würden Sie dies auf eine Charge anwenden? –
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). –