Ich portiere mein Caffe-Netzwerk auf TensorFlow, aber es scheint keine Xavier-Initialisierung zu haben. Ich benutze, truncated_normal
aber das scheint es viel schwieriger zu machen, zu trainieren.
Ich portiere mein Caffe-Netzwerk auf TensorFlow, aber es scheint keine Xavier-Initialisierung zu haben. Ich benutze, truncated_normal
aber das scheint es viel schwieriger zu machen, zu trainieren.
Antworten:
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 .
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())
get_variable
sondern 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?
tf.Variable(...)
und verwendettf.get_variable(...)
Nur um ein weiteres Beispiel zum Definieren einer tf.Variable
Initialisierung 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.
@ 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
Ein netter Wrapper tensorflow
namens prettytensor
gibt 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)
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:
Über den kernel_initializer
Parameter zu tf.layers.conv2d, tf.layers.conv2d_transpose, tf.layers.Dense
etc.
z.B
layer = tf.layers.conv2d(
input, 128, 5, strides=2,padding='SAME',
kernel_initializer=tf.contrib.layers.xavier_initializer())
https://www.tensorflow.org/api_docs/python/tf/layers/conv2d
https://www.tensorflow.org/api_docs/python/tf/layers/conv2d_transpose
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_normal
Wenn 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).
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)))