Jak przeprowadzić inicjalizację Xaviera w TensorFlow

85

Przenoszę moją sieć Caffe do TensorFlow, ale wygląda na to, że nie ma inicjalizacji Xavier. Używam, truncated_normalale wydaje mi się, że trenowanie jest o wiele trudniejsze.

Alejandro
źródło
2
Xavier jest domyślną inicjalizacją. Zobacz stackoverflow.com/questions/37350131/…
Thomas Ahle

Odpowiedzi:

12

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 .

y.selivonchyk
źródło
Użyłem powyższego kodu i otrzymałem błąd jak poniżej; _init_xavier = tf.Variable (init (shape = shape)) NameError: name 'shape' nie jest zdefiniowana
Chiranga
119

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())
Sung Kim
źródło
3
czy wiesz, aby to zrobić bez nadawania kształtu, get_variableale 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?
Pinokio,
1
@Pinocchio, możesz po prostu napisać sobie opakowanie, które ma ten sam podpis, co tf.Variable(...)i używatf.get_variable(...)
jns
2
Link „Bieżący” bez wersji: tensorflow.org/api_docs/python/tf/contrib/layers/…
scipilot
28

Aby dodać kolejny przykład, jak zdefiniować tf.Variablezainicjowany 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 nanwartości mojej funkcji utraty z powodu niestabilności numerycznej podczas używania wielu warstw z RELU.

Saullo GP Castro
źródło
2
Ten format najlepiej pasował do mojego kodu - i pozwolił mi przywrócić współczynnik uczenia się do 0,5 (musiałem obniżyć go do 0,06 podczas dodawania kolejnej warstwy relu'd). Kiedy zastosowałem ten inicjator do WSZYSTKICH ukrytych warstw, otrzymuję niewiarygodnie wysokie wskaźniki walidacji od pierwszych kilkuset epok. Nie mogę uwierzyć, jaka to różnica!
scipilot
12

@ 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

Delip
źródło
1
Jak możemy go używać z funkcją aktywacji relu.
gautam840
W artykule tym badano zachowanie gradientów ciężaru przy różnych funkcjach aktywacji z powszechnie stosowaną inicjalizacją. Następnie proponują uniwersalną inicjalizację niezależnie od funkcji aktywacji. Co więcej, Twoja metoda również nie zależy od funkcji aktywacji, więc lepiej jest użyć wbudowanej inicjalizacji Xavier w Tensorflow.
Vahid Mirjalili
8

Ładne opakowanie wokół tensorflowwywołania prettytensordaje 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)
Haczykowaty
źródło
8

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:

Salvador Dali
źródło
dzięki, sir, to było bardzo pomocne, chcę cię zapytać, czy mogę zainicjować odchylenie za pomocą xavier_initializer
Sakhri Houssem
4

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_normalmożesz to zrobić za Ciebie, wystarczy obliczyć odchylenie standardowe (tj. liczbę neuronów reprezentowaną przez macierz wag, którą próbujesz zainicjować).

Vince Gatto
źródło
Vince, powinieneś pobierać próbki z jednolitej dystrybucji.
Delip
4

Poprzez kernel_initializerparametr 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

https://www.tensorflow.org/api_docs/python/tf/layers/Dense

xilef
źródło
3

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)))
Tony Power
źródło
0

Tensorflow 1:

W1 = tf.get_variable("W1", [25, 12288],
    initializer = tf.contrib.layers.xavier_initializer(seed=1)

Tensorflow 2:

W1 = tf.get_variable("W1", [25, 12288],
    initializer = tf.random_normal_initializer(seed=1))
mruanova
źródło