如何在 TensorFlow 上进行 Xavier 初始化
Posted
技术标签:
【中文标题】如何在 TensorFlow 上进行 Xavier 初始化【英文标题】:How to do Xavier initialization on TensorFlow 【发布时间】:2016-02-11 22:56:11 【问题描述】:我正在将我的 Caffe 网络移植到 TensorFlow,但它似乎没有 xavier 初始化。我正在使用truncated_normal
,但这似乎让训练变得更加困难。
【问题讨论】:
Xavier 是默认初始化。见***.com/questions/37350131/… 【参考方案1】:从 0.8 版开始,有一个 Xavier 初始化程序,see here for the docs。
你可以这样使用:
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)
,我在那里指定了形状,但现在你的建议有点搞砸了我的代码。你有什么建议吗?
@Pinocchio 您可以简单地为自己编写一个与tf.Variable(...)
具有相同签名并使用tf.get_variable(...)
的包装器
“当前”链接无版本:tensorflow.org/api_docs/python/tf/contrib/layers/…【参考方案2】:
只是添加另一个示例,说明如何定义使用Xavier and Yoshua 的方法初始化的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 一起使用时,数值不稳定。
【讨论】:
这种格式最适合我的代码 - 它允许我将学习率返回到 0.5(添加另一个 relu'd 层时我不得不将其降低到 0.06)。一旦我将这个初始化程序应用于所有隐藏层,我从前几百个 epoch 开始就获得了令人难以置信的高验证率。我无法相信它所带来的不同!【参考方案3】:在 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 的初始化,请参阅documentation。
【讨论】:
我使用了上面的代码,得到如下错误; _init_xavier = tf.Variable(init(shape=shape)) NameError: name 'shape' is not defined【参考方案4】:@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 写了一个 post yesterday 来做一些不同的事情,碰巧也使用 Xavier 初始化。如果你有兴趣,还有一个带有端到端示例的 python notebook:https://github.com/delip/blog-stuff/blob/master/tensorflow_ufp.ipynb
【讨论】:
我们如何将它与relu激活函数一起使用。 那篇论文用常用的初始化方法研究了不同激活函数下权重梯度的行为。然后他们提出了一个通用初始化,而不管任何激活函数。此外,您的方法也不依赖于激活函数,因此最好使用 Tensorflow 中内置的 Xavier 初始化。【参考方案5】:围绕tensorflow
的一个很好的包装称为prettytensor
在源代码中提供了一个实现(直接从here 复制):
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)
【讨论】:
【参考方案6】: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 还有其他初始化器:
xavier_initializer_conv2d variance_scaling_initializer constant_initializer zeros_initializer ones_initializer uniform_unit_scaling_initializer truncated_normal_initializer random_uniform_initializer random_normal_initializer orthogonal_initializer as well as a lot of initializers from keras【讨论】:
谢谢,先生,这很有帮助,我想问您是否可以使用 xavier_initializer 初始化 bias【参考方案7】:我看了看,找不到任何内置的东西。但是,据此:
http://andyljones.tumblr.com/post/110998971763/an-explanation-of-xavier-initialization
Xavier 初始化只是对一个(通常是高斯)分布进行采样,其中方差是神经元数量的函数。 tf.random_normal
可以为您做到这一点,您只需要计算标准差(即您尝试初始化的权重矩阵表示的神经元数量)。
【讨论】:
Vince 你应该从均匀分布中抽样。【参考方案8】:通过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
https://www.tensorflow.org/api_docs/python/tf/layers/Dense
【讨论】:
【参考方案9】:以防万一您想像使用一样使用一行:
W = tf.Variable(tf.truncated_normal((n_prev, n), stddev=0.1))
你可以这样做:
W = tf.Variable(tf.contrib.layers.xavier_initializer()((n_prev, n)))
【讨论】:
【参考方案10】:张量流 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))
【讨论】:
以上是关于如何在 TensorFlow 上进行 Xavier 初始化的主要内容,如果未能解决你的问题,请参考以下文章
在 Jetson nano 和 jetson xavier 上运行 Nvidia-docker 以实现 tensorflow 等深度学习框架