Я переношу свою сеть Caffe на TensorFlow, но, похоже, у нее нет инициализации xavier. Я использую, truncated_normal
но похоже, что это затрудняет тренировку.
Ответы:
В Tensorflow 2.0 и последующих версиях оба tf.contrib.*
и tf.get_variable()
устарели. Теперь, чтобы выполнить инициализацию Xavier, вам нужно переключиться на:
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 и форма Xavier - это два разных имени одного и того же типа инициализации. Если вы хотите узнать больше о том, как использовать инициализации в TF2.0 с или без Keras, обратитесь к документации .
Начиная с версии 0.8 существует инициализатор Xavier, см. Здесь документы .
Вы можете использовать что-то вроде этого:
W = tf.get_variable("W", shape=[784, 256],
initializer=tf.contrib.layers.xavier_initializer())
get_variable
а вместо этого передавая ее инициализатору? Раньше у tf.truncated_normal(shape=[dims[l-1],dims[l]], mean=mu[l], stddev=std[l], dtype=tf.float64)
меня была форма , и я указывал здесь форму, но теперь ваше предложение как бы портит мой код. У вас есть какие-нибудь предложения?
tf.Variable(...)
и использоватьtf.get_variable(...)
Просто чтобы добавить еще один пример того, как определить tf.Variable
инициализированный с помощью метода Ксавьера и Йошуа :
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))
...
Это мешало мне иметь nan
значения в моей функции потерь из-за численной нестабильности при использовании нескольких слоев с RELU.
@ Aleph7, инициализация Xavier / Glorot зависит от количества входящих подключений (fan_in), количества исходящих подключений (fan_out) и типа функции активации (сигмоида или tanh) нейрона. См. Это: http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf
Итак, теперь к вашему вопросу. Вот как я бы сделал это в 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))
Обратите внимание, что мы должны выбирать из равномерного распределения, а не из нормального распределения, как предлагается в другом ответе.
Между прочим, вчера я написал сообщение о другом использовании TensorFlow, которое также использует инициализацию Xavier. Если вам интересно, есть также блокнот на Python со сквозным примером: https://github.com/delip/blog-stuff/blob/master/tensorflow_ufp.ipynb
Хорошая обертка вокруг tensorflow
named prettytensor
дает реализацию в исходном коде (скопированном прямо отсюда ):
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 имеет xavier_initializer
. Вот пример того, как его использовать:
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)
В дополнение к этому у tenorflow есть другие инициализаторы:
Я посмотрел и не нашел ничего встроенного. Однако, согласно этому:
http://andyljones.tumblr.com/post/110998971763/an-explanation-of-xavier-initialization
Инициализация Xavier - это просто выборка распределения (обычно гауссова), где дисперсия является функцией количества нейронов. tf.random_normal
может сделать это за вас, вам просто нужно вычислить stddev (то есть количество нейронов, представленных весовой матрицей, которую вы пытаетесь инициализировать).
Через kernel_initializer
параметр в tf.layers.conv2d, tf.layers.conv2d_transpose, tf.layers.Dense
etc
например
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
На всякий случай вы хотите использовать одну строку, как вы это делаете с:
W = tf.Variable(tf.truncated_normal((n_prev, n), stddev=0.1))
Ты можешь сделать:
W = tf.Variable(tf.contrib.layers.xavier_initializer()((n_prev, n)))