命名空间name_scope与variable_scope的区别

前言:整理name_scope与variable_scope是因为自己在学习的过程中碰到的一些疑惑,后来看书和网上的一些解释。故这里做一些学习记录。


1、大体的认识

tf.name_scope()和tf.variable_scope()是两个作用域,一般与两个创建/调用变量的函数tf.variable() 和tf.get_variable()搭配使用。它们搭配在一起的两个常见用途:

  1. 变量共享
  2. tensorboard画流程图时为了可视化封装变量

这两种用途有特定的搭配方式,掌握好就可以用了。

  • name_scope:为了更好地管理变量的命名空间而提出的。比如在 tensorboard 中,因为引入了 name_scope, 我们的 Graph 看起来才井然有序。
  • variable_scope:大部分情况下,跟 tf.get_variable() 配合使用实现变量共享的功能

2、name_scope与variable_scope的区别

先直接给出结论,然后再进行说明,是其他博主整理的结论,这只是借鉴一下,原文是这个。

  1. name_scope 对 get_variable新建变量的name属性无影响;对variable新建变量的name属性增加了“范围”标识。
  2. variable_scope对get_variable新建变量的name属性和variable新建变量的name属性都增加了“范围”标识。
  3. get_variable新建变量如果遇见重复的name则会因为重复而报错。
  4. variable新建的变量如果遇见重复的name则会自动修改前缀,以避免重复出现。

2.1 tf.name_scope

tf.name_scope 主要结合 tf.Variable() 来使用,方便参数命名管理。

2.1.1 name_scope()对variable的影响

'''
Signature: tf.name_scope(*args, **kwds)
Docstring:
Returns a context manager for use when defining a Python op.
'''
# 也就是说,它的主要目的是为了更加方便地管理参数命名。
# 与 tf.Variable() 结合使用。简化了命名
with tf.name_scope('conv1') as scope:
    weights1 = tf.Variable([1.0, 2.0], name='weights')
    bias1 = tf.Variable([0.3], name='bias')

# 下面是在另外一个命名空间来定义变量的
with tf.name_scope('conv2') as scope:
    weights2 = tf.Variable([4.0, 2.0], name='weights')
    bias2 = tf.Variable([0.33], name='bias')

# 所以,实际上weights1 和 weights2 这两个引用名指向了不同的空间,不会冲突
print weights1.name
print weights2.name

conv1/weights:0
conv2/weights:0

从上面的例子可以看出name_scope()对variable的变量名自动添上命名空间的名称,形式为/

2.1.2 tf.name_scope对tf.get_variable()的影响

with tf.name_scope("a_name_scope") as myscope:
    initializer = tf.constant_initializer(value=1)
    var1 = tf.get_variable(name='var1', shape=[1], dtype=tf.float32, initializer=initializer)

print(var1.name)        

var1:0

可见并没有在变量名前添加命名空间的名称。

2.2 tf.variable_scope

tf.variable_scope() 主要结合 tf.get_variable() 来使用,实现变量共享

2.2.1 variable_scope()对tf.get_variable() 的影响

with tf.variable_scope('v_scope') as scope1:
    Weights1 = tf.get_variable('Weights', shape=[2,3])
    bias1 = tf.get_variable('bias', shape=[3])

# 下面来共享上面已经定义好的变量
# note: 在下面的 scope 中的变量必须已经定义过了,才能设置 reuse=True,否则会报错
with tf.variable_scope('v_scope', reuse=True) as scope2:
    Weights2 = tf.get_variable('Weights')

print Weights1.name
print Weights2.name

v_scope/Weights:0
v_scope/Weights:0

对variable的影响这里就不展示了,这里只提醒一下,当需要共用变量的时候,设置的reuse=True必须是要已经创建过的变量,否则则会报错。

   也许目前还不知道这会有什么用,但给个例子就会发现这样的好处。这里借鉴一下这篇博客的内容。(也可以参考下这篇文章,讲的还算清楚,对变量的共享,因为在卷积神经网络中,卷积层的参数就是共享的呢)

   TensorFlow中的变量一般就是模型的参数。当模型复杂的时候共享变量会无比复杂。

   官网给了一个case,当创建两层卷积的过滤器时,每输入一次图片就会创建一次过滤器对应的变量,但是我们希望所有图片都共享同一过滤器变量,一共有4个变量:conv1_weights,conv1_biases,conv2_weights, and conv2_biases。

通常的做法是将这些变量设置为全局变量。但是存在的问题是打破封装性,这些变量必须文档化被其他代码文件引用,一旦代码变化,调用方也可能需要变化。

还有一种保证封装性的方式是将模型封装成类。

不过TensorFlow提供了Variable Scope 这种独特的机制来共享变量。这个机制涉及两个主要函数:

def conv_relu(input, kernel_shape, bias_shape):
    # Create variable named "weights".
    weights = tf.get_variable("weights", kernel_shape,initializer=tf.random_normal_initializer())
    # Create variable named "biases".
    biases = tf.get_variable("biases", bias_shape,initializer=tf.constant_initializer(0.0))
    conv = tf.nn.conv2d(input, weights,strides=[1, 1, 1, 1], padding='SAME')
    return tf.nn.relu(conv + biases)

但是我们需要两个卷积层,这时可以通过tf.variable_scope()指定作用域进行区分,
如with tf.variable_scope("conv1")这行代码指定了第一个卷积层作用域为conv1,

在这个作用域下有两个变量weights和biases。

def my_image_filter(input_images):
    with tf.variable_scope("conv1"):
        # Variables created here will be named "conv1/weights", "conv1/biases".
        relu1 = conv_relu(input_images, [5, 5, 32, 32], [32])
    with tf.variable_scope("conv2"):
        # Variables created here will be named "conv2/weights", "conv2/biases".
        return conv_relu(relu1, [5, 5, 32, 32], [32])

最后在image_filters这个作用域重复使用第一张图片输入时创建的变量,调用函数reuse_variables(),代码如下:
with tf.variable_scope("image_filters") as scope:
    result1 = my_image_filter(image1)
    scope.reuse_variables()
    result2 = my_image_filter(image2)

    总之,当神经网络结构更加复杂、参数更多时,使用这种变量的管理方式将大大提高程序的可读性。

参考资料:

https://blog.csdn.net/jerr__y/article/details/60877873

https://blog.csdn.net/lucky7213/article/details/78967306

https://www.cnblogs.com/MY0213/p/9208503.html

猜你喜欢

转载自blog.csdn.net/qq_20412595/article/details/83098553
今日推荐