Come eseguire l'inizializzazione di Xavier su TensorFlow


Risposte:


12

In Tensorflow 2.0 e successivi entrambi tf.contrib.*e tf.get_variable()sono deprecati. Per eseguire l'inizializzazione di Xavier ora devi passare 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))

Glorot uniform e Xavier uniform sono due nomi diversi dello stesso tipo di inizializzazione. Se vuoi saperne di più su come usare le inizializzazioni in TF2.0 con o senza Keras, fai riferimento alla documentazione .


Ho usato il codice sopra e ottengo un errore come di seguito; _init_xavier = tf.Variable (init (shape = shape)) NameError: il nome 'shape' non è definito
Chiranga

119

Dalla versione 0.8 esiste un inizializzatore Xavier, vedi qui per la documentazione .

Puoi usare qualcosa del genere:

W = tf.get_variable("W", shape=[784, 256],
           initializer=tf.contrib.layers.xavier_initializer())

3
sapete farlo senza dare la forma get_variablema dandola invece all'inizializzatore? Avevo tf.truncated_normal(shape=[dims[l-1],dims[l]], mean=mu[l], stddev=std[l], dtype=tf.float64)e ho specificato la forma lì, ma ora il tuo suggerimento mi ha rovinato il codice. Hai qualche suggerimento?
Pinocchio

1
@Pinocchio puoi semplicemente scrivere un involucro che ha la stessa firma tf.Variable(...)e usatf.get_variable(...)
jns

2
Collegamento "corrente" senza versione: tensorflow.org/api_docs/python/tf/contrib/layers/…
scipilot

28

Solo per aggiungere un altro esempio su come definire un tf.Variableinizializzato usando il metodo di 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))
    ...

Ciò mi ha impedito di avere nanvalori sulla mia funzione di perdita a causa di instabilità numeriche quando si utilizzano più livelli con RELU.


2
Questo formato si adattava al meglio al mio codice e mi ha permesso di riportare il mio tasso di apprendimento a 0,5 (ho dovuto abbassarlo a 0,06 quando ho aggiunto un altro livello relu'd). Una volta applicato questo inizializzatore a TUTTI i livelli nascosti, ottengo tassi di convalida incredibilmente alti fin dalle prime centinaia di epoche. Non riesco a credere alla differenza che ha fatto!
scipilot

12

@ Aleph7, l'inizializzazione di Xavier / Glorot dipende dal numero di connessioni in entrata (fan_in), dal numero di connessioni in uscita (fan_out) e dal tipo di funzione di attivazione (sigmoide o tanh) del neurone. Vedi questo: http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf

Quindi ora, alla tua domanda. Ecco come lo farei in 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))

Nota che dovremmo campionare da una distribuzione uniforme e non dalla distribuzione normale come suggerito nell'altra risposta.

Per inciso, ho scritto un file ieri post per qualcosa di diverso usando TensorFlow che utilizza anche l'inizializzazione di Xavier. Se sei interessato, c'è anche un taccuino Python con un esempio end-to-end: https://github.com/delip/blog-stuff/blob/master/tensorflow_ufp.ipynb


1
Come possiamo usarlo con la funzione di attivazione relu.
gautam840

Questo documento studia il comportamento dei gradienti di peso sotto diverse funzioni di attivazione con l'inizializzazione comunemente usata. Quindi propongono un'inizializzazione universale indipendentemente da qualsiasi funzione di attivazione. Inoltre, il tuo metodo non dipende nemmeno dalla funzione di attivazione, quindi è meglio usare l'inizializzazione Xavier incorporata in Tensorflow.
Vahid Mirjalili

8

Un bel wrapper intorno tensorflowchiamato prettytensorfornisce un'implementazione nel codice sorgente (copiato direttamente da qui ):

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 ha xavier_initializer. Ecco un esempio di come 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)

Oltre a questo, tensorflow ha altri inizializzatori:


grazie, signore questo è stato molto utile, voglio chiederle se posso inizializzare il bias usando xavier_initializer
Sakhri Houssem

4

Ho cercato e non sono riuscito a trovare nulla di integrato. Tuttavia, secondo questo:

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

L'inizializzazione di Xavier sta semplicemente campionando una distribuzione (solitamente gaussiana) in cui la varianza è una funzione del numero di neuroni. tf.random_normalpuò farlo per te, devi solo calcolare lo stddev (cioè il numero di neuroni rappresentato dalla matrice di peso che stai tentando di inizializzare).


Vince dovresti campionare da una distribuzione uniforme.
Delip


3

Nel caso in cui desideri utilizzare una riga come fai con:

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

Tu puoi fare:

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))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.