Tensorflow 和变量范围 - 如何正确重用范围?
Tensorflow and Variable Scope - How to reuse scopes correctly?
我重新设计了一个之前用 Keras 制作的 GAN。到目前为止没有问题,但是我注意到我的模型没有正确训练,这取决于我实现范围重用的方式。也许有人可以帮助我了解正在发生的事情:
工作版本:
with tf.variable_scope('g/h0') as scope:
reuse_scope = scope if reuse else None
h0 = tf.contrib.layers.fully_connected(
z,
4*4*512,
activation_fn=None,
reuse=reuse_scope,
scope='g/h0'
)
h0 = tf.nn.relu(h0)
无效版本:
with tf.variable_scope('g/h0') as scope:
if reuse:
scope.reuse_variables()
h0 = tf.contrib.layers.fully_connected(
z,
4*4*512,
activation_fn=None
)
h0 = tf.nn.relu(h0)
这两个版本都导致了一个工作网络,但是第二个导致了一个永不更新的网络。而且我不明白为什么第一个版本会导致正确的情况。
在 TensorBoard 中,根据我选择的版本不同,图表看起来也大不相同。我怀疑梯度反向传播不正确。
第二个版本有什么办法吗?我发现它更容易理解。
我认为您应该尝试这种定义范围的方式:
reuse = ... # True or False
with tf.variable_scope('g/h0') as scope:
h0 = tf.contrib.layers.fully_connected(
z,
4*4*512,
activation_fn=None,
reuse=reuse,
scope='fully_connected',
)
h0 = tf.nn.relu(h0)
如果将重用设置为 False
,将创建全连接层 "as usual"。如果将其设置为 True
,则不会创建其他参数,但权重和偏差将从另一个范围 重用 (具有相同名称且具有相同名称的变量具有当然是创建的)。
reuse
参数必须是True
或False
(自然是None
)
scope
参数与reuse
无关。它只是内部范围名称。比如你设置了scope = 'g/h0'
,你的全连接层里面的权重参数就是'g/h0/g/h0/weights:0'
,如果不设置,就是'g/h0/fully_connected/weights:0'
.
此 中解决了类似的问题。它与您的问题大致相同,只是使用了 conv2d 层并且未明确设置范围。
编辑:
我不知道这是一个错误还是正常的,但是要在 tf.contrib.layers.fully_connected
中使用 reuse=True
变量,您需要指定 scope
...
完整的工作示例:
import tensorflow as tf
## A value for z that you did not specify in your question
z = tf.placeholder(tf.float32, (2,1))
## First fully-connected layer with ut result
with tf.variable_scope('g/h0'):
h0 = tf.contrib.layers.fully_connected(
z,
4*4*512,
activation_fn=None,
reuse=None
)
h0 = tf.nn.relu(h0)
tf.global_variables()
# Returns [<tf.Variable 'g/h0/fully_connected/weights:0' shape=(1, 8192) dtype=float32_ref>, <tf.Variable 'g/h0/fully_connected/biases:0' shape=(8192,) dtype=float32_ref>]
# Second layer ith resuse = True
with tf.variable_scope('g/h0'):
h0 = tf.contrib.layers.fully_connected(
z,
4*4*512,
activation_fn=None,
reuse=True, scope = 'fully_connected'
)
h0 = tf.nn.relu(h0)
tf.global_variables()
# Returns [<tf.Variable 'g/h0/fully_connected/weights:0' shape=(1, 8192) dtype=float32_ref>, <tf.Variable 'g/h0/fully_connected/biases:0' shape=(8192,) dtype=float32_ref>]
# => the same parameters are used for both layers
我先定义了reuse=True,然后:
与 tf.compat.v1.variable_scope('layer_1'):
....
....
....
tf.compat.v1.variable_scope('layer_2'):
我重新设计了一个之前用 Keras 制作的 GAN。到目前为止没有问题,但是我注意到我的模型没有正确训练,这取决于我实现范围重用的方式。也许有人可以帮助我了解正在发生的事情:
工作版本:
with tf.variable_scope('g/h0') as scope:
reuse_scope = scope if reuse else None
h0 = tf.contrib.layers.fully_connected(
z,
4*4*512,
activation_fn=None,
reuse=reuse_scope,
scope='g/h0'
)
h0 = tf.nn.relu(h0)
无效版本:
with tf.variable_scope('g/h0') as scope:
if reuse:
scope.reuse_variables()
h0 = tf.contrib.layers.fully_connected(
z,
4*4*512,
activation_fn=None
)
h0 = tf.nn.relu(h0)
这两个版本都导致了一个工作网络,但是第二个导致了一个永不更新的网络。而且我不明白为什么第一个版本会导致正确的情况。
在 TensorBoard 中,根据我选择的版本不同,图表看起来也大不相同。我怀疑梯度反向传播不正确。
第二个版本有什么办法吗?我发现它更容易理解。
我认为您应该尝试这种定义范围的方式:
reuse = ... # True or False
with tf.variable_scope('g/h0') as scope:
h0 = tf.contrib.layers.fully_connected(
z,
4*4*512,
activation_fn=None,
reuse=reuse,
scope='fully_connected',
)
h0 = tf.nn.relu(h0)
如果将重用设置为 False
,将创建全连接层 "as usual"。如果将其设置为 True
,则不会创建其他参数,但权重和偏差将从另一个范围 重用 (具有相同名称且具有相同名称的变量具有当然是创建的)。
reuse
参数必须是True
或False
(自然是None
)scope
参数与reuse
无关。它只是内部范围名称。比如你设置了scope = 'g/h0'
,你的全连接层里面的权重参数就是'g/h0/g/h0/weights:0'
,如果不设置,就是'g/h0/fully_connected/weights:0'
.
此
编辑:
我不知道这是一个错误还是正常的,但是要在 tf.contrib.layers.fully_connected
中使用 reuse=True
变量,您需要指定 scope
...
完整的工作示例:
import tensorflow as tf
## A value for z that you did not specify in your question
z = tf.placeholder(tf.float32, (2,1))
## First fully-connected layer with ut result
with tf.variable_scope('g/h0'):
h0 = tf.contrib.layers.fully_connected(
z,
4*4*512,
activation_fn=None,
reuse=None
)
h0 = tf.nn.relu(h0)
tf.global_variables()
# Returns [<tf.Variable 'g/h0/fully_connected/weights:0' shape=(1, 8192) dtype=float32_ref>, <tf.Variable 'g/h0/fully_connected/biases:0' shape=(8192,) dtype=float32_ref>]
# Second layer ith resuse = True
with tf.variable_scope('g/h0'):
h0 = tf.contrib.layers.fully_connected(
z,
4*4*512,
activation_fn=None,
reuse=True, scope = 'fully_connected'
)
h0 = tf.nn.relu(h0)
tf.global_variables()
# Returns [<tf.Variable 'g/h0/fully_connected/weights:0' shape=(1, 8192) dtype=float32_ref>, <tf.Variable 'g/h0/fully_connected/biases:0' shape=(8192,) dtype=float32_ref>]
# => the same parameters are used for both layers
我先定义了reuse=True,然后:
与 tf.compat.v1.variable_scope('layer_1'): .... .... .... tf.compat.v1.variable_scope('layer_2'):