Tensorflow和Variable Scope - 如何正确地重用范围?

时间:2017-10-13 10:33:45

标签: tensorflow deep-learning tensorflow-gpu tensor

我重新设计了一个我以前用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中,图表看起来完全不同,具体取决于我选择的版本。我怀疑梯度反向传播不正确。

第二个版本有没有办法做到这一点?我发现它更容易理解。

1 个答案:

答案 0 :(得分:2)

我认为您应该尝试这种方式来定义您的范围:

 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,则会像往常一样创建完全连接的图层""。如果您将其设置为True,则不会创建其他参数,但权重和偏差将从另一个范围重用(具有相同名称且已创建具有相同名称的变量,当然)。

  • reuse参数必须为TrueFalse(或None,自然而然)
  • scope参数与reuse无关。它只是内部范围名称。例如,如果您设置scope = 'g/h0',则完全连接图层内的权重参数将为'g/h0/g/h0/weights:0',但如果您未设置,则为'g/h0/fully_connected/weights:0'

answer解决了类似问题。它与您的问题中的上下文大致相同,只是使用了conv2d图层并且未明确设置范围。

修改 我不知道这是一个错误还是正常但是要使用reuse=True中的tf.contrib.layers.fully_connected变量,您需要指定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