2016-01-22 12 views
29

Ich frage mich, ob es einen Weg gibt, dass ich verschiedene Lernrate für verschiedene Schichten wie in Caffe verwenden kann. Ich versuche, ein vortrainiertes Modell zu modifizieren und es für andere Aufgaben zu verwenden. Ich möchte das Training für neue hinzugefügte Schichten beschleunigen und die trainierten Schichten mit niedriger Lernrate halten, um zu verhindern, dass sie verzerrt werden. Ich habe zum Beispiel ein vortrainiertes Modell mit 5 Conv-Layern. Jetzt füge ich eine neue Conv-Ebene hinzu und verfeinere sie. Die ersten 5 Schichten hätten eine Lernrate von 0,00001 und die letzte hätte 0,001. Irgendeine Idee, wie man das erreicht?Wie wird die schichtweise Lernrate in Tensorflow eingestellt?

Antwort

53

kann es ganz leicht mit 2 Optimizern erreicht werden:

var_list1 = [variables from first 5 layers] 
var_list2 = [the rest of variables] 
train_op1 = GradientDescentOptimizer(0.00001).minimize(loss, var_list=var_list1) 
train_op2 = GradientDescentOptimizer(0.0001).minimize(loss, var_list=var_list2) 
train_op = tf.group(train_op1, train_op2) 

Ein Nachteil dieser Implementierung ist, dass es tf.gradients berechnet zweimal innerhalb der Optimierer und somit kann es nicht im Sinne der optimalen sein (.) Ausführungsgeschwindigkeit. Dies kann durch explizites Aufrufen von tf.gradients (.) Gemildert werden, indem die Liste in 2 aufgeteilt wird und entsprechende Gradienten an beide Optimierer übergeben werden.

Verwandte Frage: Holding variables constant during optimizer

EDIT: Hinzugefügt effiziente, sondern mehr Implementierung:

var_list1 = [variables from first 5 layers] 
var_list2 = [the rest of variables] 
opt1 = tf.train.GradientDescentOptimizer(0.00001) 
opt2 = tf.train.GradientDescentOptimizer(0.0001) 
grads = tf.gradients(loss, var_list1 + var_list2) 
grads1 = grads[:len(var_list1)] 
grads2 = grads[len(var_list1):] 
tran_op1 = opt1.apply_gradients(zip(grads1, var_list1)) 
train_op2 = opt2.apply_gradients(zip(grads2, var_list2)) 
train_op = tf.group(train_op1, train_op2) 

können Sie tf.trainable_variables() verwenden, um alle Trainingsvariablen zu erhalten und entscheiden, um von ihnen zu wählen. Der Unterschied ist, dass in der ersten Implementierung tf.gradients(.) zweimal innerhalb der Optimierer aufgerufen wird. Dies kann dazu führen, dass einige redundante Operationen ausgeführt werden (z. B. können Gradienten auf der ersten Schicht einige Berechnungen für die Gradienten der folgenden Schichten wiederverwenden).

+0

Danke für Ihre Antwort Rafal. Ich wundere mich immer noch ein wenig, wenn Sie den Nachteil in Bezug auf Geschwindigkeit gesagt haben, wie sehr es die Leistung beeinflussen würde. Wenn ich ein großes Netzwerk trainiere, wäre dies keine gute Option. Könnten Sie außerdem genauer auf Ihre zweite Methode eingehen? Wie kann man tf.gradients() explizit aufrufen? Tut mir leid, ich bin immer noch ein Neuling. –

+0

Bearbeitete die Antwort. –

+0

thx man, ist die vorletzte Zeile "train_op2 = opt2.apply_gradients (.)"? wenn ich das richtig verstehe. –

6

-Update 22. Januar: Rezept unten ist nur eine gute Idee für GradientDescentOptimizer, andere Optimierer, die einen laufenden Durchschnitt halten gelten Rate vor dem Parameter Update erfahren, so Rezept unten nicht, dass ein Teil der Gleichung beeinflussen

Zusätzlich zu Rafals Ansatz könnten Sie compute_gradients, apply_gradients Schnittstelle von Optimizer verwenden. Zum Beispiel, hier ist ein Spielzeug Netzwerk, in dem ich 2x die Lernrate verwenden für die zweite Parameter

x = tf.Variable(tf.ones([])) 
y = tf.Variable(tf.zeros([])) 
loss = tf.square(x-y) 
global_step = tf.Variable(0, name="global_step", trainable=False) 

opt = tf.GradientDescentOptimizer(learning_rate=0.1) 
grads_and_vars = opt.compute_gradients(loss, [x, y]) 
ygrad, _ = grads_and_vars[1] 
train_op = opt.apply_gradients([grads_and_vars[0], (ygrad*2, y)], global_step=global_step) 

init_op = tf.initialize_all_variables() 
sess = tf.Session() 
sess.run(init_op) 
for i in range(5): 
    sess.run([train_op, loss, global_step]) 
    print sess.run([x, y]) 

Sie sehen sollten

[0.80000001, 0.40000001] 
[0.72000003, 0.56] 
[0.68800002, 0.62400001] 
[0.67520005, 0.64960003] 
[0.67008007, 0.65984005] 
+1

Das ist gut bei der Verwendung von SGD, aber nicht sicher, ob es optimal für schicke Optimierer ist, die Statistiken über vergangene Gradientenwerte berechnen ... Es macht wahrscheinlich keinen Unterschied, solange Sie diese Lernrate während des Trainings nicht ändern wollen. –

+0

guter Punkt, aktualisierte Antwort –

+0

Danke Mann, das scheint brilliant. –

3

Collect Lernrate Multiplikatoren für jede Variable wie:

self.lr_multipliers[var.op.name] = lr_mult 

und dann wenden Sie sie während der Anwendung der Gradienten wie:

def _train_op(self): 
    tf.scalar_summary('learning_rate', self._lr_placeholder) 
    opt = tf.train.GradientDescentOptimizer(self._lr_placeholder) 
    grads_and_vars = opt.compute_gradients(self._loss) 
    grads_and_vars_mult = [] 
    for grad, var in grads_and_vars: 
    grad *= self._network.lr_multipliers[var.op.name] 
    grads_and_vars_mult.append((grad, var)) 
    tf.histogram_summary('variables/' + var.op.name, var) 
    tf.histogram_summary('gradients/' + var.op.name, grad) 
    return opt.apply_gradients(grads_and_vars_mult) 

Sie können das ganze Beispiel here finden.

0

Die ersten 5 Schichten hätten eine Lernrate von 0,00001 und die letzte hätte 0,001. Irgendeine Idee, wie man das erreicht?

Es gibt eine einfache Möglichkeit, dies mit tf.stop_gradient zu tun. Hier ein Beispiel mit drei Schichten:

x = layer1(input) 
x = layer2(x) 
output = layer3(x) 

Sie können den Farbverlauf in den ersten beiden Schichten durch ein Verhältnis von 1/100 zu schrumpfen:

x = layer1(input) 
x = layer2(x) 
x = 1/100*x + (1-1/100)*tf.stop_gradient(x) 
output = layer3(x) 

Auf der Layer2, die „Flow“ ist in zwei Zweige geteilt: einer, der einen Beitrag von 1/100 hat, berechnet seinen Gradienten regelmäßig, aber mit einer Gradientengröße, die um einen Anteil von 1/100 verkleinert ist, liefert der andere Zweig den verbleibenden "Fluss", ohne zu dem Gradienten wegen des tf beizutragen .stop_gradient-Operator. Wenn Sie auf Ihrem Modelloptimierer eine Lernrate von 0,001 verwenden, haben die ersten beiden Schichten praktisch eine Lernrate von 0,00001.

Verwandte Themen