官方Tensorflow API文档声称tf.layers.conv2d和tf.layers.dense的参数 kernel_initializer 默认为None。
但是,阅读图层教程(https://www.tensorflow.org/tutorials/layers),我注意到代码中没有设置此参数。例如:
# Convolutional Layer #1
conv1 = tf.layers.conv2d(
inputs=input_layer,
filters=32,
kernel_size=[5, 5],
padding="same",
activation=tf.nn.relu)
本教程中的示例代码运行时没有任何错误,因此我认为默认kernel_initializer
不是None
。那么,使用哪个初始化器?
在另一段代码中,我没有设置conv2d和密集层的kernel_initializer
,一切都很好。但是,当我尝试将kernel_initializer
设置为tf.truncated_normal_initializer(stddev=0.1, dtype=tf.float32)
时,我收到了NaN错误。这里发生了什么?有人可以帮忙吗?
答案 0 :(得分:91)
好问题!找出来是一个很好的技巧!
tf.layers.conv2d
variable_scope.get_variable
:在代码中:
self.kernel = vs.get_variable('kernel',
shape=kernel_shape,
initializer=self.kernel_initializer,
regularizer=self.kernel_regularizer,
trainable=True,
dtype=self.dtype)
下一步:what does the variable scope do when the initializer is None?
这里说:
如果初始化程序为
None
(默认值),则传入默认初始值设定项 使用了构造函数。如果那个也是None
,我们使用新的glorot_uniform_initializer
。
所以答案是:它使用glorot_uniform_initializer
为了完整性,此初始化程序的定义:
Glorot统一初始化器,也称为Xavier统一初始化器。 它从[-limit,limit]内的均匀分布中抽取样本 其中
limit
是sqrt(6 / (fan_in + fan_out))
其中fan_in
是权重张量中的输入单位数fan_out
是权重张量中的输出单位数。 参考:http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf
编辑:这是我在代码和文档中找到的。也许您可以通过在权重上运行eval来验证初始化是否像这样!
答案 1 :(得分:1)
根据Andrew Ng和this course的Xavier documentation,如果您使用 ReLU 作为激活函数,则最好更改默认的权重初始值设定项( Xavier统一)通过以下方式较正常:
y = tf.layers.conv2d(x, kernel_initializer=tf.contrib.layers.xavier_initializer(uniform=False), )
答案 2 :(得分:1)
2.0兼容答案:即使在Tensorflow 2.0中,Kernel Initializer
和tf.keras.layers.Conv2D
中的默认 tf.keras.layers.Dense
为 { {1}} 。
这在Tensorflow.org网站中指定。
glorot_uniform
的链接为https://www.tensorflow.org/api_docs/python/tf/keras/layers/Conv2D?version=nightly#init
, Conv2D
的链接为
https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dense?version=nightly#init
答案 3 :(得分:0)
在CNN中,内核值是随机初始化的。然后将在反向传播期间重新调整值,以产生更好的边缘检测(!)内核。参见this