Como fazer a inicialização do Xavier no TensorFlow


Respostas:


12

No Tensorflow 2.0 e posteriores, ambos tf.contrib.*e tf.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 .


Usei o código acima e recebo um erro como abaixo; _init_xavier = tf.Variable (init (shape = shape)) NameError: o nome 'forma' não está definido
Chiranga

119

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

3
você sabe fazer isso sem dar a forma a, get_variablemas em vez disso dando ao inicializador? Eu costumava ter tf.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?
Pinóquio

1
@Pinocchio, você pode simplesmente escrever um invólucro que tenha a mesma assinatura tf.Variable(...)e usetf.get_variable(...)
jns


28

Apenas para adicionar outro exemplo de como definir um tf.Variableinicializado 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 nanvalores na minha função de perda devido a instabilidades numéricas ao usar várias camadas com RELUs.


2
Este formato se ajustou melhor ao meu código - e me permitiu retornar minha taxa de aprendizado para 0,5 (eu tive que diminuí-la para 0,06 ao adicionar outra camada recarregada). Depois de aplicar esse inicializador a TODAS as camadas ocultas, estou obtendo taxas de validação incrivelmente altas desde as primeiras centenas de épocas. Eu não posso acreditar a diferença que fez!
scipilot

12

@ 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


1
Como podemos usá-lo com a função de ativação relu.
gautam840

Esse artigo estuda o comportamento dos gradientes de peso sob diferentes funções de ativação com a inicialização comumente usada. Em seguida, eles propõem uma inicialização universal, independentemente de qualquer função de ativação. Além disso, seu método também não depende da função de ativação, então é melhor usar a inicialização Xavier integrada no Tensorflow.
Vahid Mirjalili

8

Um bom wrapper tensorflowchamado prettytensorfornece 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)

8

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:


obrigado, senhor, isso foi muito útil, gostaria de perguntar se posso inicializar o bias usando xavier_initializer
Sakhri Houssem

4

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


Vince você deve estar amostrando de uma distribuição uniforme.
Delip


3

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:

W = tf.Variable(tf.contrib.layers.xavier_initializer()((n_prev, n)))

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))
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.