Как выполнить инициализацию Xavier на TensorFlow

86

Я переношу свою сеть Caffe на TensorFlow, но, похоже, у нее нет инициализации xavier. Я использую, truncated_normalно похоже, что это затрудняет тренировку.

Алехандро
источник
2
Ксавье - инициализация по умолчанию. См stackoverflow.com/questions/37350131/...
Thomas Ахле

Ответы:

12

В 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, обратитесь к документации .

Ю.Селивончик
источник
Я использовал приведенный выше код и получил сообщение об ошибке, как показано ниже; _init_xavier = tf.Variable (init (shape = shape)) NameError: имя 'shape' не определено
Чиранга
119

Начиная с версии 0.8 существует инициализатор Xavier, см. Здесь документы .

Вы можете использовать что-то вроде этого:

W = tf.get_variable("W", shape=[784, 256],
           initializer=tf.contrib.layers.xavier_initializer())
Сунг Ким
источник
3
знаете ли вы, что это нужно делать, не придавая форму, get_variableа вместо этого передавая ее инициализатору? Раньше у tf.truncated_normal(shape=[dims[l-1],dims[l]], mean=mu[l], stddev=std[l], dtype=tf.float64)меня была форма , и я указывал здесь форму, но теперь ваше предложение как бы портит мой код. У вас есть какие-нибудь предложения?
Пиноккио
1
@Pinocchio, вы можете просто написать себе обертку с такой же подписью tf.Variable(...)и использоватьtf.get_variable(...)
jns
2
«Текущая» ссылка без версии: tensorflow.org/api_docs/python/tf/contrib/layers/…
scipilot
28

Просто чтобы добавить еще один пример того, как определить 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.

Саулло Г. П. Кастро
источник
2
Этот формат лучше всего соответствовал моему коду - и он позволил мне вернуть скорость обучения до 0,5 (мне пришлось снизить ее до 0,06 при добавлении еще одного слоя relu'd). После того, как я применил этот инициализатор ко ВСЕМ скрытым слоям, я получаю невероятно высокие показатели проверки уже с первых нескольких сотен эпох. Я не могу поверить в разницу!
scipilot
12

@ 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

Делип
источник
1
Как мы можем использовать его с функцией активации relu.
gautam840
В этой статье изучается поведение градиентов веса при различных функциях активации с обычно используемой инициализацией. Затем они предлагают универсальную инициализацию независимо от какой-либо функции активации. Кроме того, ваш метод также не зависит от функции активации, поэтому лучше использовать встроенную инициализацию Xavier в Tensorflow.
Вахид Мирджалили
8

Хорошая обертка вокруг tensorflownamed 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)
Зацепил
источник
8

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 есть другие инициализаторы:

Сальвадор Дали
источник
спасибо, сэр, это было очень полезно, я хочу спросить вас, могу ли я инициализировать смещение с помощью xavier_initializer
Сахри Хусем
4

Я посмотрел и не нашел ничего встроенного. Однако, согласно этому:

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

Инициализация Xavier - это просто выборка распределения (обычно гауссова), где дисперсия является функцией количества нейронов. tf.random_normalможет сделать это за вас, вам просто нужно вычислить stddev (то есть количество нейронов, представленных весовой матрицей, которую вы пытаетесь инициализировать).

Винс Гатто
источник
Винс, вы должны делать выборку из равномерного распределения.
Delip
3

На всякий случай вы хотите использовать одну строку, как вы это делаете с:

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

Ты можешь сделать:

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))
Мруанова
источник