Cómo hacer la inicialización de Xavier en TensorFlow

85

Estoy transfiriendo mi red Caffe a TensorFlow pero no parece tener una inicialización xavier. Estoy usando, truncated_normalpero esto parece hacer que sea mucho más difícil entrenar.

Alejandro
fuente
2
Xavier es la inicialización predeterminada. Ver stackoverflow.com/questions/37350131/…
Thomas Ahle

Respuestas:

12

En Tensorflow 2.0 y posteriores, ambos tf.contrib.*y tf.get_variable()están en desuso. Para realizar la inicialización de Xavier, ahora debe cambiar a:

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))

El uniforme Glorot y el uniforme Xavier son dos nombres diferentes del mismo tipo de inicialización. Si desea saber más sobre cómo usar las inicializaciones en TF2.0 con o sin Keras, consulte la documentación .

y.selivonchyk
fuente
Usé el código anterior y recibí un error como el siguiente; _init_xavier = tf.Variable (init (shape = shape)) NameError: el nombre 'forma' no está definido
Chiranga
119

Dado que la versión 0.8 hay un inicializador de Xavier, consulte aquí los documentos .

Puedes usar algo como esto:

W = tf.get_variable("W", shape=[784, 256],
           initializer=tf.contrib.layers.xavier_initializer())
Sung Kim
fuente
3
¿Sabes hacer esto sin darle la forma get_variablesino dársela al inicializador? Solía ​​tener tf.truncated_normal(shape=[dims[l-1],dims[l]], mean=mu[l], stddev=std[l], dtype=tf.float64)y especifiqué la forma allí, pero ahora tu sugerencia arruina mi código. ¿Tienes alguna sugerencia?
Pinocho
1
@Pinocho, simplemente puede escribir usted mismo un envoltorio que tenga la misma firma que tf.Variable(...)y usatf.get_variable(...)
jns
2
Enlace "actual" sin versión: tensorflow.org/api_docs/python/tf/contrib/layers/…
scipilot
28

Solo para agregar otro ejemplo sobre cómo definir un tf.Variableinicializado usando el método de Xavier y 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))
    ...

Esto me impidió tener nanvalores en mi función de pérdida debido a inestabilidades numéricas al usar múltiples capas con RELU.

Saullo GP Castro
fuente
2
Este formato se ajustaba mejor a mi código, y me permitió devolver mi tasa de aprendizaje a 0.5 (tuve que bajarla a 0.06 cuando agregué otra capa relu). Una vez que apliqué este inicializador a TODAS las capas ocultas, obtengo tasas de validación increíblemente altas desde los primeros cientos de épocas. ¡No puedo creer la diferencia que ha hecho!
scipilot
12

La inicialización de @ Aleph7, Xavier / Glorot depende del número de conexiones entrantes (fan_in), el número de conexiones salientes (fan_out) y el tipo de función de activación (sigmoidea o tanh) de la neurona. Vea esto: http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf

Así que ahora, a tu pregunta. Así es como lo haría en 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))

Tenga en cuenta que deberíamos tomar muestras de una distribución uniforme y no de la distribución normal como se sugiere en la otra respuesta.

Por cierto, ayer escribí una publicación para algo diferente usando TensorFlow que también usa la inicialización de Xavier. Si está interesado, también hay un cuaderno de Python con un ejemplo de extremo a extremo: https://github.com/delip/blog-stuff/blob/master/tensorflow_ufp.ipynb

Delip
fuente
1
¿Cómo podemos usarlo con la función de activación relu?
gautam840
Ese artículo estudia el comportamiento de los gradientes de peso bajo diferentes funciones de activación con la inicialización comúnmente utilizada. Luego proponen una inicialización universal independientemente de cualquier función de activación. Además, su método tampoco depende de la función de activación, por lo que es mejor usar la inicialización de Xavier incorporada en Tensorflow.
Vahid Mirjalili
8

Un buen envoltorio tensorflowllamado prettytensorofrece una implementación en el código fuente (copiado directamente desde aquí ):

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)
Enganchado
fuente
8

TF-contrib tiene xavier_initializer. Aquí hay un ejemplo de cómo usarlo:

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)

Además de esto, tensorflow tiene otros inicializadores:

Salvador Dalí
fuente
gracias, señor, esto fue muy útil, quiero preguntarle si puedo inicializar el sesgo usando xavier_initializer
Sakhri Houssem
4

Miré y no pude encontrar nada integrado. Sin embargo, de acuerdo con esto:

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

La inicialización de Xavier solo muestra una distribución (generalmente gaussiana) donde la varianza es una función del número de neuronas. tf.random_normalpuede hacer eso por usted, solo necesita calcular el stddev (es decir, el número de neuronas que está representado por la matriz de peso que está intentando inicializar).

Vince Gatto
fuente
Vince, deberías tomar muestras de una distribución uniforme.
Delip
3

En caso de que quiera usar una línea como lo hace con:

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

Tu puedes hacer:

W = tf.Variable(tf.contrib.layers.xavier_initializer()((n_prev, n)))
Tony Power
fuente
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
fuente