我正在将我的 Caffe 网络移植到 TensorFlow,但它似乎没有 xavier 初始化。我正在使用truncated_normal
,但这似乎使训练变得更加困难。
10 回答
从 0.8 版开始,有一个 Xavier 初始化程序,请参阅此处的文档。
你可以使用这样的东西:
W = tf.get_variable("W", shape=[784, 256],
initializer=tf.contrib.layers.xavier_initializer())
只是添加另一个关于如何使用Xavier 和 Yoshuatf.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))
...
由于在使用带有 RELU 的多个层时数值不稳定性,这使我无法nan
在损失函数上获得值。
在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 uniform 和 Xavier uniform 是同一个初始化类型的两个不同名字。如果您想了解更多关于如何在 TF2.0 中使用或不使用 Keras 的初始化,请参阅文档。
@Aleph7,Xavier/Glorot 初始化取决于神经元的传入连接数(fan_in)、传出连接数(fan_out)和激活函数类型(sigmoid 或 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
一个很好的被调用的包装器在源代码中给出了一个实现(直接从这里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)
除此之外,tensorflow 还有其他初始化器:
通过kernel_initializer
参数到tf.layers.conv2d, tf.layers.conv2d_transpose, tf.layers.Dense
等
例如
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
我看了看,找不到任何内置的东西。但是,据此:
http://andyljones.tumblr.com/post/110998971763/an-explanation-of-xavier-initialization
Xavier 初始化只是对一个(通常是高斯)分布进行采样,其中方差是神经元数量的函数。 tf.random_normal
可以为您做到这一点,您只需要计算 stddev(即您尝试初始化的权重矩阵表示的神经元数量)。
以防万一您想使用一行:
W = tf.Variable(tf.truncated_normal((n_prev, n), stddev=0.1))
你可以做:
W = tf.Variable(tf.contrib.layers.xavier_initializer()((n_prev, n)))
张量流1:
W1 = tf.get_variable("W1", [25, 12288],
initializer = tf.contrib.layers.xavier_initializer(seed=1)
张量流2:
W1 = tf.get_variable("W1", [25, 12288],
initializer = tf.random_normal_initializer(seed=1))