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参数必须是TrueFalse(自然是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'):