Przenoszę moją sieć Caffe do TensorFlow, ale wygląda na to, że nie ma inicjalizacji Xavier. Używam, truncated_normal
ale wydaje mi się, że trenowanie jest o wiele trudniejsze.
Odpowiedzi:
W Tensorflow 2.0 i nowszych oba tf.contrib.*
i tf.get_variable()
są przestarzałe. Aby wykonać inicjalizację Xaviera, musisz teraz przełączyć się na:
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))
Mundur Glorot i mundur Xaviera to dwie różne nazwy tego samego typu inicjalizacji. Jeśli chcesz dowiedzieć się więcej o tym, jak używać inicjalizacji w TF2.0 z lub bez Keras, zajrzyj do dokumentacji .
Od wersji 0.8 istnieje inicjator Xavier, zobacz tutaj dokumentację .
Możesz użyć czegoś takiego:
W = tf.get_variable("W", shape=[784, 256],
initializer=tf.contrib.layers.xavier_initializer())
get_variable
ale zamiast tego przekazując go inicjatorowi? Kiedyś miałem tf.truncated_normal(shape=[dims[l-1],dims[l]], mean=mu[l], stddev=std[l], dtype=tf.float64)
i określałem tam kształt, ale teraz twoja sugestia trochę psuje mój kod. Masz jakieś sugestie?
tf.Variable(...)
i używatf.get_variable(...)
Aby dodać kolejny przykład, jak zdefiniować tf.Variable
zainicjowany przy użyciu metody Xaviera i Yoshua :
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))
...
Uniemożliwiło mi to uzyskanie nan
wartości mojej funkcji utraty z powodu niestabilności numerycznej podczas używania wielu warstw z RELU.
@ Aleph7, inicjalizacja Xavier / Glorot zależy od liczby połączeń przychodzących (fan_in), liczby połączeń wychodzących (fan_out) i rodzaju funkcji aktywacji (sigmoid lub tanh) neuronu. Zobacz: http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf
A teraz do twojego pytania. Oto jak zrobiłbym to w TensorFlow:
(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))
Zauważ, że powinniśmy pobierać próbki z rozkładu jednorodnego, a nie z rozkładu normalnego, jak sugeruje inna odpowiedź.
Nawiasem mówiąc, wczoraj napisałem post dotyczący czegoś innego za pomocą TensorFlow, który również używa inicjalizacji Xavier. Jeśli jesteś zainteresowany, jest też notatnik Pythona z pełnym przykładem: https://github.com/delip/blog-stuff/blob/master/tensorflow_ufp.ipynb
Ładne opakowanie wokół tensorflow
wywołania prettytensor
daje implementację w kodzie źródłowym (skopiowanym bezpośrednio stąd ):
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)
Wkład TF ma xavier_initializer
. Oto przykład, jak go używać:
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)
Oprócz tego tensorflow ma inne inicjatory:
Szukałem i nie mogłem znaleźć nic wbudowanego. Jednak zgodnie z tym:
http://andyljones.tumblr.com/post/110998971763/an-explanation-of-xavier-initialization
Inicjalizacja Xaviera polega po prostu na próbkowaniu rozkładu (zwykle Gaussa), w którym wariancja jest funkcją liczby neuronów. tf.random_normal
możesz to zrobić za Ciebie, wystarczy obliczyć odchylenie standardowe (tj. liczbę neuronów reprezentowaną przez macierz wag, którą próbujesz zainicjować).
Poprzez kernel_initializer
parametr do tf.layers.conv2d, tf.layers.conv2d_transpose, tf.layers.Dense
itp
na przykład
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
Na wszelki wypadek, gdybyś chciał użyć jednej linii, tak jak robisz z:
W = tf.Variable(tf.truncated_normal((n_prev, n), stddev=0.1))
Możesz to zrobić:
W = tf.Variable(tf.contrib.layers.xavier_initializer()((n_prev, n)))