Як зробити ініціалізацію Xavier на TensorFlow


85

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


2
Xavier - це ініціалізація за замовчуванням. Див 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))

Уніформа Глоро та форма Ксав'є - це дві різні назви одного типу ініціалізації. Якщо ви хочете дізнатися більше про те, як використовувати ініціалізації в TF2.0 з Keras або без, зверніться до документації .


Я використав наведений вище код і отримав помилку, як показано нижче; _init_xavier = tf. Змінна (init (shape = shape)) NameError: ім'я 'shape' не визначено
Chiranga

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). Як тільки я застосував цей ініціалізатор до ВСІХ прихованих шарів, я отримую неймовірно високі показники перевірки вже з перших кількох сотень епох. Я не можу повірити, яка різниця це зробила!
сципілот

12

@ Aleph7, ініціалізація Xavier / Glorot залежить від кількості вхідних з'єднань (fan_in), кількості вихідних з'єднань (fan_out) та виду функції активації (сигмовидної або тангової) нейрона. Див. Це: 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

Гарна обгортка навколо tensorflowвикликає 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-внесок має 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)

На додаток до цього, у tensorflow є інші ініціалізатори:


спасибі, сер , це було дуже корисно, я хочу запитати вас , якщо я можу ініціалізувати зміщення з допомогою xavier_initializer
Sakhri Houssem

4

Я подивився і не міг знайти нічого вбудованого. Однак відповідно до цього:

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

Ініціалізація Ксав'є - це просто вибірка розподілу (як правило, Гауса), де дисперсія є функцією кількості нейронів. 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))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.