name/variable_scope 的作用
从上面的实验结果来看,这三种方式所定义的变量具有相同的类型。而且只有 tf.get_variable() 创建的变量之间会发生命名冲突。在实际使用中,三种创建变量方式的用途也是分工非常明确的。其中
tf.name_scope() 并不会对 tf.get_variable() 创建的变量有任何影响。
tf.name_scope() 主要是用来管理命名空间的,这样子让我们的整个模型更加有条理。而 tf.variable_scope() 的作用是为了实现变量共享,它和 tf.get_variable() 来完成变量共享的功能。
1. 使用tf.Variable()
的时候,tf.name_scope()
和tf.variable_scope()
都会给 Variable
和 op
的 name
属性加上前缀。
2. 使用tf.get_variable()
的时候,tf.name_scope()
就不会给 tf.get_variable()
创建出来的Variable
加前缀。但是 tf.Variable()
创建出来的就会受到 name_scope
的影响.
典型的 TensorFlow 可以有数以千计的节点,如此多而难以一下全部看到,甚至无法使用标准图表工具来展示。为简单起见,我们为op/tensor
名划定范围,并且可视化把该信息用于在图表中的节点上定义一个层级。默认情况下, 只有顶层节点会显示。下面这个例子使用tf.name_scope在hidden命名域下定义了三个操作:
import tensorflow as tf
with tf.name_scope('hidden') as scope:
a = tf.constant(5, name='alpha')
W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0), name='weights')
b = tf.Variable(tf.zeros([1]), name='biases')
print a.name
print W.name
print b.name1.2.3.4.5.6.7.8.9.
结果是得到了下面三个操作名:
hidden/alpha
hidden/weights
hidden/biases
name_scope 是给op_name加前缀, variable_scope是给get_variable()创建的变量的名字加前缀。
tf.variable_scope有时也会处理命名冲突
登录后复制
import tensorflow as tf
def test(name=None):
with tf.variable_scope(name, default_name="scope") as scope:
w = tf.get_variable("w", shape=[2, 10])
test()
test()
ws = tf.trainable_variables()
for w in ws:
print(w.name)
#scope/w:0
#scope_1/w:0
#可以看出,如果只是使用default_name这个属性来创建variable_scope
#的时候,会处理命名冲突
TensorFlow 支持两种共享变量的方式:
tf.Variable
对象。tf.variable_scope
对象内隐式包装 tf.Variable
对象。虽然显式传递变量的代码非常清晰,但有时编写 TensorFlow 函数(在实现中隐式使用变量)非常方便。tf.layer
中的大多数功能层以及所有 tf.metrics
和部分其他库工具都使用这种方法。
变量作用域允许您在调用隐式创建和使用变量的函数时控制变量重用。作用域还允许您以分层和可理解的方式命名变量。
例如,假设我们编写一个函数来创建一个卷积/relu 层:
登录后复制
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)
此函数使用短名称 weights
和 biases
,这有利于清晰区分二者。然而,在真实模型中,我们需要很多此类卷积层,而且重复调用此函数将不起作用:
登录后复制
input1 = tf.random_normal([1,10,10,32])input2 = tf
.random_normal([1,20,20,32])x = conv_relu(input1, kernel_shape=[5, 5, 32, 32],
bias_shape=[32])x = conv_relu(x, kernel_shape=[5, 5, 32, 32], bias_shape = [32])
# This fails.
由于期望的操作不清楚(创建新变量还是重新使用现有变量?),因此 TensorFlow 将会失败。不过,在不同作用域内调用 conv_relu
可表明我们想要创建新变量:
登录后复制
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])
如果您想要共享变量,有两种方法可供选择。首先,您可以使用 variable_scope :reuse=True 创建具
有相同名称的作用域:
登录后复制
with tf.variable_scope("model"): output1 = my_image_filter(input1)with tf
.variable_scope("model", reuse=True): output2 = my_image_filter(input2)
您也可以调用 scope.reuse_variables()
以触发重用:
登录后复制
with tf.variable_scope("model") as scope: output1 = my_image_filter(input1) scope
.reuse_variables() output2 = my_image_filter(input2)
由于根据作用域的具体字符串名称初始化变量作用域可能比较危险,因此也可以根据另一作用域进行初始化:
登录后复制
with tf.variable_scope("model") as scope: output1 = my_image_filter(input1)with tf
.variable_scope(scope, reuse=True): output2 = my_image_filter(input2)
C/C++基本语法学习
STL
C++ primer
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删