tensorflow variable_scope\name_scope

转载自http://blog.csdn.net/u011636567/article/details/71124211



转载自http://blog.csdn.net/qq_19918373/article/details/69499091



为了研究一下tensorflow的name_scopevariable_scope到底有啥区别,我对Variable和Summary对象分别试验了这两种scope。直接上代码:

1.对Variable先加name_scope,再加variable_scope

import tensorflow as tf

with tf.name_scope('ns1'):          #name_scope
    v1 = tf.get_variable('v1', shape=(1,))
    with tf.variable_scope('vs1'):  #variable_scope
        v2 = tf.get_variable('v2', shape=(1,))

v1v2_coll = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,scope='ns1') #[]
v2_coll = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,scope='vs1')   #'vs1/v2:0'
#name_scope对变量无效, 'vs1/v2:0'的prefix里没有'ns1/'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2.对Variable先加variable_scope,再加name_scope

with tf.variable_scope('vs2'):      #variable_scope
    v1 = tf.get_variable('v1', shape=(1,))
    with tf.name_scope('ns2'):      #name_scope
        v2 = tf.get_variable('v2', shape=(1,))

v1v2_coll = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,scope='vs2') #'vs2/v1:0'
v2_coll = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,scope='ns2')   #[]
#name_scope对变量无效, 'vs2/v1:0'的prefix里没有'ns2/'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3.对Summary先加name_scope,再加variable_scope

with tf.name_scope('ns3'):          #name_scope
    tf.summary.histogram('sum_ns', tf.convert_to_tensor([1]))
    with tf.variable_scope('vs3'):  #variable_scope
        tf.summary.histogram('sum_nsvs', tf.convert_to_tensor([1]))

sum_ns_coll = tf.get_collection(tf.GraphKeys.SUMMARIES,scope='ns3')
#'ns3/sum_ns:0', 'ns3/vs3/sum_vs:0'
sum_nsvs_coll = tf.get_collection(tf.GraphKeys.SUMMARIES,scope='ns3/vs3')
#'ns3/vs3/sum_nsvs:0'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

4.对Summary先加variable_scope,再加name_scope

with tf.variable_scope('vs4'):      #variable_scope
    tf.summary.histogram('sum_vs', tf.convert_to_tensor([1]))
    with tf.name_scope('ns4'):      #name_scope
        tf.summary.histogram('sum_ns', tf.convert_to_tensor([1]))

sum_vs_coll = tf.get_collection(tf.GraphKeys.SUMMARIES,scope='vs4')
#'vs4/sum_vs:0', 'vs4/ns4/sum_ns:0'
sum_vsns_coll = tf.get_collection(tf.GraphKeys.SUMMARIES,scope='vs4/ns4')
#'vs4/ns4/sum_ns:0'

还有需要注意一点的是tf.variable_scope("name") 与 tf.variable_scope(scope)的区别,看下面代码

代码1

import tensorflow as tf
with tf.variable_scope("scope"):
    tf.get_variable("w",shape=[1])#这个变量的name是 scope/w
    with tf.variable_scope("scope"):
        tf.get_variable("w", shape=[1]) #这个变量的name是 scope/scope/w
# 这两个变量的名字是不一样的,所以不会产生冲突
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

代码2

import tensorflow as tf
with tf.variable_scope("yin"):
    tf.get_variable("w",shape=[1])
    scope = tf.get_variable_scope()#这个变量的name是 scope/w
    with tf.variable_scope(scope):#这种方式设置的scope,是用的外部的scope
        tf.get_variable("w", shape=[1])#这个变量的name也是 scope/w
# 两个变量的名字一样,会报错


主要针对 tf.get_variable 来介绍共享变量的用法。

tf.get_variable 与 tf.variable 的用法不同。前者在创建变量时会查名字,如果给的名字在之前已经被别的变量占用,则会报错,不会创建相应变量。而后者并不进行检查,如果有重复,则自动的修改名字,加上数字来进行区别。所以从这来看要想共享变量并不能通过使用相同的名字来调用多次 tf.get_variable 和 tf.variable 做到。

比如下面这样的代码:

[python]  view plain  copy
  1. <span style="font-size:14px;">def my_image_filter(input_images):  
  2.     conv1_weights = tf.Variable(tf.random_normal([553232]),  
  3.         name="conv1_weights")  
  4.     conv1_biases = tf.Variable(tf.zeros([32]), name="conv1_biases")  
  5.     conv1 = tf.nn.conv2d(input_images, conv1_weights,  
  6.         strides=[1111], padding='SAME')  
  7.     relu1 = tf.nn.relu(conv1 + conv1_biases)  
  8.   
  9.     conv2_weights = tf.Variable(tf.random_normal([553232]),  
  10.         name="conv2_weights")  
  11.     conv2_biases = tf.Variable(tf.zeros([32]), name="conv2_biases")  
  12.     conv2 = tf.nn.conv2d(relu1, conv2_weights,  
  13.         strides=[1111], padding='SAME')  
  14.     return tf.nn.relu(conv2 + conv2_biases)</span>  
在这个函数中,我们有 'conv1_weights','conv1_biases','conv2_weights','conv2_biases' 4个变量。如果我们重用这个函数,则会产生多组变量,并不会使用相同的变量,如下面调用:

[python]  view plain  copy
  1. <span style="font-size:14px;"># First call creates one set of variables.  
  2. result1 = my_image_filter(image1)  
  3. # Another set is created in the second call.  
  4. result2 = my_image_filter(image2)</span>  
上面实际上用两个不同的滤波器对 image1 和 image2 进行滤波,虽然用的是相同的函数。所以呢,这就产生了问题,下面介绍如何进行变量共享。

我们使用 with tf.variable_scope 来进行共享。比如有下面的代码:

[python]  view plain  copy
  1. <span style="font-size:14px;">def conv_relu(input, kernel_shape, bias_shape):  
  2.     # Create variable named "weights".  
  3.     weights = tf.get_variable("weights", kernel_shape,  
  4.         initializer=tf.random_normal_initializer())  
  5.     # Create variable named "biases".  
  6.     biases = tf.get_variable("biases", bias_shape,  
  7.         initializer=tf.constant_intializer(0.0))  
  8.     conv = tf.nn.conv2d(input, weights,  
  9.         strides=[1111], padding='SAME')  
  10.     return tf.nn.relu(conv + biases)  
  11. def my_image_filter(input_images):  
  12.     with tf.variable_scope("conv1"):  
  13.         # Variables created here will be named "conv1/weights", "conv1/biases".  
  14.         relu1 = conv_relu(input_images, [553232], [32])  
  15.     with tf.variable_scope("conv2"):  
  16.         # Variables created here will be named "conv2/weights", "conv2/biases".  
  17.         return conv_relu(relu1, [553232], [32])</span>  
若要调用两次 my_image_filter 并且使用相同的变量,则如下所示:

[python]  view plain  copy
  1. <span style="font-size:14px;">with tf.variable_scope("image_filters") as scope:  
  2.     result1 = my_image_filter(image1)  
  3.     scope.reuse_variables()  
  4.     result2 = my_image_filter(image2)</span>  
利用 reuse_variables() 来使变量重用。值得注意的是下面的代码解释了  tf.get_variable  工作原理:

[python]  view plain  copy
  1. <span style="font-size:14px;">with tf.variable_scope("foo"):  
  2.     v = tf.get_variable("v", [1])  
  3. with tf.variable_scope("foo", reuse=True):  
  4.     v1 = tf.get_variable("v", [1])  
  5. assert v1 == v</span>  
如果 reuse 开启,当检查到有相同的名字时,直接返回那个有相同名字的变量而不是重新定义一个再复制值。


下面是使用时需要注意的地方

1. 在 variable_scope 里面的 variable_scope 会继承上面的 reuse 值,即上面一层开启了 reuse ,则下面的也跟着开启。但是不能人为的设置 reuse 为 false ,只有退出 variable_scope 才能让 reuse 变为 false:

[python]  view plain  copy
  1. <span style="font-size:14px;">with tf.variable_scope("root"):  
  2.     # At start, the scope is not reusing.  
  3.     assert tf.get_variable_scope().reuse == False  
  4.     with tf.variable_scope("foo"):  
  5.         # Opened a sub-scope, still not reusing.  
  6.         assert tf.get_variable_scope().reuse == False  
  7.     with tf.variable_scope("foo", reuse=True):  
  8.         # Explicitly opened a reusing scope.  
  9.         assert tf.get_variable_scope().reuse == True  
  10.         with tf.variable_scope("bar"):  
  11.             # Now sub-scope inherits the reuse flag.  
  12.             assert tf.get_variable_scope().reuse == True  
  13.     # Exited the reusing scope, back to a non-reusing one.  
  14.     assert tf.get_variable_scope().reuse == False</span>  


2. 当在某一 variable_scope 内使用别的 scope 的名字时,此时不再受这里的等级关系束缚,直接与使用的 scope 的名字一样:

[python]  view plain  copy
  1. <span style="font-size:14px;">with tf.variable_scope("foo") as foo_scope:  
  2.     assert foo_scope.name == "foo"  
  3. with tf.variable_scope("bar")  
  4.     with tf.variable_scope("baz") as other_scope:  
  5.         assert other_scope.name == "bar/baz"  
  6.         with tf.variable_scope(foo_scope) as foo_scope2:  
  7.             assert foo_scope2.name == "foo"  # Not changed.</span>  

3. name_scope 与 variable_scope 稍有不同。name_scope 只会影响 ops 的名字,而并不会影响 variables 的名字。

[python]  view plain  copy
  1. <span style="font-size:14px;">with tf.variable_scope("foo"):  
  2.     with tf.name_scope("bar"):  
  3.         v = tf.get_variable("v", [1])  
  4.         x = 1.0 + v  
  5. assert v.name == "foo/v:0"  
  6. assert x.op.name == "foo/bar/add"</span>  

猜你喜欢

转载自blog.csdn.net/qq_38255689/article/details/78531657
今日推荐