Tensorflow 变量命名空间及变量重用

来源:互联网 发布:linux echo是什么意思 编辑:程序博客网 时间:2024/05/17 22:11

参考:tensorflow中文文档 variable_scope

变量命名空间

tf里面的命名空间和C++的命名空间基本上是同一种东西,能够更好的管理模块的变量(特别是将来会重用到的变量)。最简单的用法就是

with tf.variable_scope("layer1"):    # 这里就创建了一个名叫layer1的变量空间    v = tf.get_variable("vector", [3], initializer=tf.random_normal_initializer(stddev=1.0, mean=0.0)) # 创建了在这个layer1空间中的一个名为vector的向量并且初始化assert v.name = "layer1/vector:0" # 加上变量空间,变量全称为"layer1/vector:0",具有唯一性

通过这样可以将一层网络的参数放在一起,发生变量重用的时候会很方便。

变量重用

变量重用则是通过get_variable函数 重复创建 同名变量来共享变量值。
举例子,我们要对图片进行特征提取。有两个已有的函数:

'''激活函数为ReLU的卷积层'''def conv_relu(input, kernel_shape, bias_shape):    # 创建变量名为"weights".    weights = tf.get_variable("weights", kernel_shape,        initializer=tf.random_normal_initializer())    # 创建变量名为"biases".    biases = tf.get_variable("biases", bias_shape,    # 卷积操作    conv = tf.nn.conv2d(input, weights,        strides=[1, 1, 1, 1], padding='SAME')    return tf.nn.relu(tf.nn.bias_add(conv, biases)) # 加上偏置然后输入激活函数得到响应'''对输入图片进行特征提取/滤波'''def my_image_filter(input_images):    with tf.variable_scope("conv1"):        # 变量名字为"conv1/weights", "conv1/biases".        relu1 = conv_relu(input_images, [5, 5, 32, 32], [32])    with tf.variable_scope("conv2"):        # 变量名字为"conv2/weights", "conv2/biases".        return conv_relu(relu1, [5, 5, 32, 32], [32])

如果直接调用两次函数my_image_filter,第二次调用时tf的get_variable函数会检测是否已经存在已经命名的变量,所以就会报错:

result1 = my_image_filter(image1)result2 = my_image_filter(image2)# ValueError(... conv1/weights already exists ...)

如果想要重用变量,则需要将变量打上重用标签。

被重用的变量需要落在同一个变量空间中,有三种方式来设置变量的重用标签reuse。
第一种:

with tf.variable_scope("image_filters") as scope:    result1 = my_image_filter(image1)    scope.reuse_variables() # 用scope来调用reuse_variables函数    result2 = my_image_filter(image2)

第二种:

with tf.variable_scope("image_filters"):    result1 = my_image_filter(image1)with tf.variable_scope("foo", reuse=True): # 设置命名空间的reuse标签    result2 = my_image_filter(image2)

第三种:

with tf.variable_scope("image_filters"):    result1 = my_image_filter(image1)    tf.get_variable_scope().reuse_variables() # 用get_variable_scope函数得到当前空间    result2 = my_image_filter(image2)

命名空间独立性

如果之前已经存在一个命名了的命名空间,在嵌套内层如果开启该命名空间,会自动忽略上层嵌套的命名空间,该命名空间里面的变量名字保持原样。

with tf.variable_scope("foo") as foo_scope:    assert foo_scope.name == "foo"with tf.variable_scope("bar"):    with tf.variable_scope("baz") as other_scope:        assert other_scope.name == "bar/baz"        with tf.variable_scope(foo_scope) as foo_scope2:            assert foo_scope2.name == "foo"  # 该空间实例foo_scope之前已经存在

但是如果直接用名字”foo”,则会不一样,会开启一个新的不一样的命名空间:

with tf.variable_scope("foo") as foo_scope:    assert foo_scope.name == "foo"with tf.variable_scope("bar"):    with tf.variable_scope("baz") as other_scope:        assert other_scope.name == "bar/baz"        with tf.variable_scope("foo") as foo_scope2:            assert foo_scope2.name == "bar/baz/foo" # 会开启一个新的处于内层的命名空间

对ops(操作)命名

第一种:

with tf.variable_scope("foo"):    x = 1.0 + tf.get_variable("v", [1])assert x.op.name == "foo/add"

第二种(tf.name_scope仅仅对ops有用,不改变变量命名):

with tf.variable_scope("foo"):    with **tf.name_scope("bar")**:        v = tf.get_variable("v", [1])        x = 1.0 + vassert v.name == "foo/v:0"assert x.op.name == "foo/bar/add"

Initializer的继承和覆盖

在嵌套命名空间里,Initializer可以继承或覆盖上层嵌套的初始化设置。

0 0
原创粉丝点击