Tensorflow 之 name/variable_scope 的使用

Posted 小河沟大河沟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tensorflow 之 name/variable_scope 的使用相关的知识,希望对你有一定的参考价值。

  • * name_scope: * 为了更好地管理变量的命名空间而提出的。比如在 tensorboard 中,因为引入了 name_scope, 我们的 Graph 看起来才井然有序。

  • * variable_scope: * 大大大部分情况下,跟 tf.get_variable() 配合使用,实现变量共享的功能。

2.三种方式创建变量: tf.placeholder, tf.Variable, tf.get_variable

从上面的实验结果来看,这三种方式所定义的变量具有相同的类型。而且只有 tf.get_variable() 创建的变量之间会发生命名冲突。在实际使用中,三种创建变量方式的用途也是分工非常明确的。其中

  • tf.placeholder() 占位符。* trainable==False *
  • tf.Variable() 一般变量用这种方式定义。 * 可以选择 trainable 类型 *
  • tf.get_variable() 一般都是和 tf.variable_scope() 配合使用,从而实现变量共享的功能。 * 可以选择 trainable 类型 *

3. 探索 name_scope 和 variable_scope

tf.name_scope() 并不会对 tf.get_variable() 创建的变量有任何影响。
tf.name_scope() 主要是用来管理命名空间的,这样子让我们的整个模型更加有条理。而 tf.variable_scope() 的作用是为了实现变量共享,它和 tf.get_variable() 来完成变量共享的功能。

  • 首先我们要确立一种 Graph 的思想。在 TensorFlow 中,我们定义一个变量,相当于往 Graph 中添加了一个节点。和普通的 python 函数不一样,在一般的函数中,我们对输入进行处理,然后返回一个结果,而函数里边定义的一些局部变量我们就不管了。但是在 TensorFlow 中,我们在函数里边创建了一个变量,就是往 Graph 中添加了一个节点。出了这个函数后,这个节点还是存在于 Graph 中的。

共享变量

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)

此函数使用短名称 weightsbiases,这有利于清晰区分二者。然而,在真实模型中,我们需要很多此类卷积层,而且重复调用此函数将不起作用:

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])

如果您想要共享变量,有两种方法可供选择。首先,您可以使用 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)

以上是关于Tensorflow 之 name/variable_scope 的使用的主要内容,如果未能解决你的问题,请参考以下文章

TensorFlow篇--Tensorflow框架可视化之Tensorboard

TensorFlow 之创建交互式 TensorFlow 会话

tensorflow笔记之基础知识

TensorFlow 之 手写数字识别MNIST

TensorFlow从0到1之TensorFlow多层感知机实现MINIST分类(22)

TensorFlow从0到1之TensorFlow多层感知机实现MINIST分类(22)