So führen Sie die Xavier-Initialisierung in TensorFlow durch

85

Ich portiere mein Caffe-Netzwerk auf TensorFlow, aber es scheint keine Xavier-Initialisierung zu haben. Ich benutze, truncated_normalaber das scheint es viel schwieriger zu machen, zu trainieren.

Alejandro
quelle
2
Xavier ist die Standardinitialisierung. Siehe stackoverflow.com/questions/37350131/…
Thomas Ahle

Antworten:

12

In Tensorflow 2.0 und weiter sind beide tf.contrib.*und tf.get_variable()veraltet. Um die Xavier-Initialisierung durchzuführen, müssen Sie jetzt wechseln zu:

init = tf.initializers.GlorotUniform()
var = tf.Variable(init(shape=shape))
# or a oneliner with a little confusing brackets
var = tf.Variable(tf.initializers.GlorotUniform()(shape=shape))

Glorot-Uniform und Xavier-Uniform sind zwei verschiedene Namen desselben Initialisierungstyps. Weitere Informationen zur Verwendung von Initialisierungen in TF2.0 mit oder ohne Keras finden Sie in der Dokumentation .

y.selivonchyk
quelle
119

Seit Version 0.8 gibt es einen Xavier-Initialisierer. Die Dokumentation finden Sie hier .

Sie können so etwas verwenden:

W = tf.get_variable("W", shape=[784, 256],
           initializer=tf.contrib.layers.xavier_initializer())
Kim gesungen
quelle
3
Wissen Sie, dass Sie dies tun müssen, ohne die Form zu geben, get_variablesondern sie dem Initialisierer zu geben? Früher hatte tf.truncated_normal(shape=[dims[l-1],dims[l]], mean=mu[l], stddev=std[l], dtype=tf.float64)ich die Form dort angegeben, aber jetzt schraubt Ihr Vorschlag meinen Code irgendwie durcheinander. Hast du irgendwelche Vorschläge?
Pinocchio
1
@ Pinocchio Sie können sich einfach einen Wrapper schreiben, der die gleiche Signatur hat tf.Variable(...)und verwendettf.get_variable(...)
jns
2
"Aktueller" Link ohne Version: tensorflow.org/api_docs/python/tf/contrib/layers/…
scipilot
28

Nur um ein weiteres Beispiel zum Definieren einer tf.VariableInitialisierung mit der Methode von Xavier und Yoshua hinzuzufügen :

graph = tf.Graph()
with graph.as_default():
    ...
    initializer = tf.contrib.layers.xavier_initializer()
    w1 = tf.Variable(initializer(w1_shape))
    b1 = tf.Variable(initializer(b1_shape))
    ...

Das hat mich daran gehindert nan ich aufgrund numerischer Instabilitäten bei Verwendung mehrerer Ebenen mit RELUs Werte für meine Verlustfunktion hatte.

Saullo GP Castro
quelle
2
Dieses Format passte am besten zu meinem Code - und ich konnte meine Lernrate auf 0,5 zurücksetzen (ich musste sie auf 0,06 senken, wenn ich eine weitere relu'd-Ebene hinzufügte). Sobald ich diesen Initialisierer auf ALLE versteckten Ebenen angewendet hatte, erhalte ich bereits in den ersten paar hundert Epochen unglaublich hohe Validierungsraten. Ich kann den Unterschied nicht glauben, den es gemacht hat!
Scipilot
12

@ Aleph7, Xavier / Glorot-Initialisierung hängt von der Anzahl der eingehenden Verbindungen (fan_in), der Anzahl der ausgehenden Verbindungen (fan_out) und der Art der Aktivierungsfunktion (Sigmoid oder Tanh) des Neurons ab. Siehe hierzu: http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf

Nun zu Ihrer Frage. So würde ich es in TensorFlow machen:

(fan_in, fan_out) = ...
    low = -4*np.sqrt(6.0/(fan_in + fan_out)) # use 4 for sigmoid, 1 for tanh activation 
    high = 4*np.sqrt(6.0/(fan_in + fan_out))
    return tf.Variable(tf.random_uniform(shape, minval=low, maxval=high, dtype=tf.float32))

Beachten Sie, dass wir eine Stichprobe aus einer gleichmäßigen Verteilung ziehen sollten und nicht aus der Normalverteilung, wie in der anderen Antwort vorgeschlagen.

Übrigens habe ich gestern mit TensorFlow einen Beitrag für etwas anderes geschrieben, das zufällig auch die Xavier-Initialisierung verwendet. Wenn Sie interessiert sind, gibt es auch ein Python-Notizbuch mit einem End-to-End-Beispiel: https://github.com/delip/blog-stuff/blob/master/tensorflow_ufp.ipynb

Löschen
quelle
1
Wie können wir es mit Relu-Aktivierungsfunktion verwenden?
Gautam840
In diesem Artikel wird das Verhalten von Gewichtsgradienten unter verschiedenen Aktivierungsfunktionen mit der häufig verwendeten Initialisierung untersucht. Dann schlagen sie eine universelle Initialisierung vor, unabhängig von einer Aktivierungsfunktion. Darüber hinaus hängt Ihre Methode auch nicht von der Aktivierungsfunktion ab. Verwenden Sie daher besser die integrierte Xavier-Initialisierung in Tensorflow.
Vahid Mirjalili
8

Ein netter Wrapper tensorflownamens prettytensorgibt eine Implementierung im Quellcode (direkt von hier kopiert ):

def xavier_init(n_inputs, n_outputs, uniform=True):
  """Set the parameter initialization using the method described.
  This method is designed to keep the scale of the gradients roughly the same
  in all layers.
  Xavier Glorot and Yoshua Bengio (2010):
           Understanding the difficulty of training deep feedforward neural
           networks. International conference on artificial intelligence and
           statistics.
  Args:
    n_inputs: The number of input nodes into each output.
    n_outputs: The number of output nodes for each input.
    uniform: If true use a uniform distribution, otherwise use a normal.
  Returns:
    An initializer.
  """
  if uniform:
    # 6 was used in the paper.
    init_range = math.sqrt(6.0 / (n_inputs + n_outputs))
    return tf.random_uniform_initializer(-init_range, init_range)
  else:
    # 3 gives us approximately the same limits as above since this repicks
    # values greater than 2 standard deviations from the mean.
    stddev = math.sqrt(3.0 / (n_inputs + n_outputs))
    return tf.truncated_normal_initializer(stddev=stddev)
Süchtig
quelle
8

TF-Contrib hat xavier_initializer. Hier ist ein Beispiel für die Verwendung:

import tensorflow as tf
a = tf.get_variable("a", shape=[4, 4], initializer=tf.contrib.layers.xavier_initializer())
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print sess.run(a)

Darüber hinaus verfügt Tensorflow über weitere Initialisierer:

Salvador Dali
quelle
Danke, Sir, das war sehr hilfreich. Ich möchte Sie fragen, ob ich die Verzerrung mit xavier_initializer
Sakhri Houssem
3

Ich habe nachgesehen und konnte nichts Eingebautes finden. Demnach jedoch:

http://andyljones.tumblr.com/post/110998971763/an-explanation-of-xavier-initialization

Bei der Xavier-Initialisierung wird lediglich eine (normalerweise Gaußsche) Verteilung abgetastet, bei der die Varianz von der Anzahl der Neuronen abhängt. tf.random_normalWenn Sie dies für Sie tun können, müssen Sie nur den Standardwert berechnen (dh die Anzahl der Neuronen, die durch die Gewichtsmatrix dargestellt werden, die Sie initialisieren möchten).

Vince Gatto
quelle
Vince Sie sollten Proben aus einer gleichmäßigen Verteilung nehmen.
Löschen Sie den
3

Nur für den Fall, dass Sie eine Zeile verwenden möchten, wie Sie es tun mit:

W = tf.Variable(tf.truncated_normal((n_prev, n), stddev=0.1))

Du kannst tun:

W = tf.Variable(tf.contrib.layers.xavier_initializer()((n_prev, n)))
Tony Power
quelle