Estoy transfiriendo mi red Caffe a TensorFlow pero no parece tener una inicialización xavier. Estoy usando, truncated_normal
pero esto parece hacer que sea mucho más difícil entrenar.
Estoy transfiriendo mi red Caffe a TensorFlow pero no parece tener una inicialización xavier. Estoy usando, truncated_normal
pero esto parece hacer que sea mucho más difícil entrenar.
Respuestas:
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 .
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())
get_variable
sino 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?
tf.Variable(...)
y usatf.get_variable(...)
Solo para agregar otro ejemplo sobre cómo definir un tf.Variable
inicializado 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 nan
valores en mi función de pérdida debido a inestabilidades numéricas al usar múltiples capas con RELU.
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
Un buen envoltorio tensorflow
llamado prettytensor
ofrece 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)
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:
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_normal
puede 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).
A través del kernel_initializer
parámetro a tf.layers.conv2d, tf.layers.conv2d_transpose, tf.layers.Dense
etc
p.ej
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
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)))