Sto trasferendo la mia rete Caffe su TensorFlow ma non sembra avere l'inizializzazione xavier. Lo sto usando, truncated_normal
ma questo sembra rendere molto più difficile l'allenamento.
Sto trasferendo la mia rete Caffe su TensorFlow ma non sembra avere l'inizializzazione xavier. Lo sto usando, truncated_normal
ma questo sembra rendere molto più difficile l'allenamento.
Risposte:
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 .
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())
get_variable
ma 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?
tf.Variable(...)
e usatf.get_variable(...)
Solo per aggiungere un altro esempio su come definire un tf.Variable
inizializzato 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 nan
valori sulla mia funzione di perdita a causa di instabilità numeriche quando si utilizzano più livelli con RELU.
@ 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
Un bel wrapper intorno tensorflow
chiamato prettytensor
fornisce 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)
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:
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_normal
può farlo per te, devi solo calcolare lo stddev (cioè il numero di neuroni rappresentato dalla matrice di peso che stai tentando di inizializzare).
Tramite il kernel_initializer
parametro per tf.layers.conv2d, tf.layers.conv2d_transpose, tf.layers.Dense
ecc
per esempio
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
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)))