Estou transferindo minha rede Caffe para o TensorFlow, mas não parece ter inicialização xavier. Estou usando, truncated_normal
mas parece que está dificultando muito o treino.
python
tensorflow
Alejandro
fonte
fonte
Respostas:
No Tensorflow 2.0 e posteriores, ambos
tf.contrib.*
etf.get_variable()
estão obsoletos. Para fazer a inicialização do Xavier, você agora deve alternar para: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))
Uniforme Glorot e Uniforme Xavier são dois nomes diferentes do mesmo tipo de inicialização. Se você quiser saber mais sobre como usar inicializações no TF2.0 com ou sem Keras, consulte a documentação .
fonte
Desde a versão 0.8 existe um inicializador Xavier, veja aqui os documentos .
Você pode usar algo assim:
W = tf.get_variable("W", shape=[784, 256], initializer=tf.contrib.layers.xavier_initializer())
fonte
get_variable
mas em vez disso dando ao inicializador? Eu costumava tertf.truncated_normal(shape=[dims[l-1],dims[l]], mean=mu[l], stddev=std[l], dtype=tf.float64)
e especificava a forma lá, mas agora sua sugestão meio que bagunçou meu código. Você tem alguma sugestão?tf.Variable(...)
e usetf.get_variable(...)
Apenas para adicionar outro exemplo de como definir um
tf.Variable
inicializado usando o método de Xavier e 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)) ...
Isso me impediu de ter
nan
valores na minha função de perda devido a instabilidades numéricas ao usar várias camadas com RELUs.fonte
@ Aleph7, a inicialização do Xavier / Glorot depende do número de conexões de entrada (fan_in), do número de conexões de saída (fan_out) e do tipo de função de ativação (sigmóide ou tanh) do neurônio. Veja isto: http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf
Então, agora, à sua pergunta. É assim que eu faria no 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))
Observe que devemos obter uma amostra de uma distribuição uniforme, e não da distribuição normal, como sugerido na outra resposta.
A propósito, escrevi um post ontem sobre algo diferente usando o TensorFlow que também usa a inicialização do Xavier. Se você estiver interessado, há também um bloco de notas Python com um exemplo de ponta a ponta: https://github.com/delip/blog-stuff/blob/master/tensorflow_ufp.ipynb
fonte
Um bom wrapper
tensorflow
chamadoprettytensor
fornece uma implementação no código-fonte (copiado diretamente daqui ):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)
fonte
TF-contrib tem
xavier_initializer
. Aqui está um exemplo de como usá-lo: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)
Além disso, o tensorflow tem outros inicializadores:
fonte
Procurei e não encontrei nada embutido. Porém, de acordo com isto:
http://andyljones.tumblr.com/post/110998971763/an-explanation-of-xavier-initialization
A inicialização de Xavier é apenas uma amostra de uma distribuição (geralmente gaussiana) onde a variância é uma função do número de neurônios.
tf.random_normal
pode fazer isso para você, você só precisa calcular o stddev (ou seja, o número de neurônios sendo representado pela matriz de peso que você está tentando inicializar).fonte
Por meio do
kernel_initializer
parâmetro paratf.layers.conv2d, tf.layers.conv2d_transpose, tf.layers.Dense
etcpor exemplo
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
fonte
Apenas no caso de você querer usar uma linha como faz com:
W = tf.Variable(tf.truncated_normal((n_prev, n), stddev=0.1))
Você pode fazer:
fonte
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))
fonte