当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Python tf.compat.v1.variable_scope用法及代码示例


用于定义创建变量(层)的操作的上下文管理器。

用法

tf.compat.v1.variable_scope(
    name_or_scope, default_name=None, values=None, initializer=None,
    regularizer=None, caching_device=None, partitioner=None, custom_getter=None,
    reuse=None, dtype=None, use_resource=None, constraint=None,
    auxiliary_name_scope=True
)

参数

  • name_or_scope stringVariableScope :要打开的范围。
  • default_name 如果 name_or_scope 参数是 None ,则使用的默认名称将是唯一的。如果提供了name_or_scope,它将不会被使用,因此它不是必需的并且可以是None。
  • values 传递给 op 函数的 Tensor 参数列表。
  • initializer 此范围内变量的默认初始化程序。
  • regularizer 此范围内变量的默认正则化器。
  • caching_device 此范围内变量的默认缓存设备。
  • partitioner 此范围内变量的默认分区器。
  • custom_getter 此范围内变量的默认自定义 getter。
  • reuse True,无,或 tf.compat.v1.AUTO_REUSE;如果 True ,我们将进入此范围以及所有 sub-scopes 的重用模式;如果 tf.compat.v1.AUTO_REUSE,我们创建变量,如果它们不存在,否则返回它们;如果没有,我们继承父作用域的重用标志。当启用即刻执行时,总是会创建新变量,除非 EagerVariableStore 或模板当前处于活动状态。
  • dtype 在此范围内创建的变量类型(默​​认为传递范围内的类型,或从父范围继承)。
  • use_resource 如果为 False,所有变量都将是常规变量。如果为 True,则将使用具有明确语义的实验性 ResourceVariables。默认为 False(稍后将更改为 True)。当启用即刻执行时,此参数始终强制为 True。
  • constraint Optimizer 更新后应用于变量的可选投影函数(例如,用于实现层权重的范数约束或值约束)。该函数必须将表示变量值的未投影张量作为输入,并返回投影值的张量(必须具有相同的形状)。在进行异步分布式训练时使用约束是不安全的。
  • auxiliary_name_scope 如果 True ,我们使用范围创建一个辅助名称范围。如果 False ,我们不创建它。注意该参数不被继承,只在创建时生效一次。您只应将其用于重新输入预制变量范围。

抛出

  • ValueError 尝试在创建范围内重用或在重用范围内创建时。
  • TypeError 当某些参数的类型不合适时。

迁移到 TF2

警告:这个 API 是为 TensorFlow v1 设计的。继续阅读有关如何从该 API 迁移到本机 TensorFlow v2 等效项的详细信息。见TensorFlow v1 到 TensorFlow v2 迁移指南有关如何迁移其余代码的说明。

尽管它是一个遗留的compat.v1 api,但只要将tf.compat.v1.variable_scopetf.compat.v1.keras.utils.track_tf1_style_variables 装饰器结合起来,tf.compat.v1.variable_scope 大部分与即刻执行和tf.function 兼容(尽管它的行为就像重用总是设置为AUTO_REUSE .)

有关迁移依赖于基于 variable_scope 的变量重用的代码的更多信息,请参阅模型迁移指南。

当您在启用了即刻执行但没有 tf.compat.v1.keras.utils.track_tf1_style_variables 的情况下使用它时,tf.compat.v1.variable_scope 仍然能够为在范围内创建的变量的名称添加前缀,但它不会启用变量重用或 error-raising 检查变量重用(get_variable在其中调用总是会创建新变量)。

从基于 get_variable 的变量重用机制切换后,要切换到 TF2 API,您只需使用 tf.name_scope 为变量名称添加前缀即可。

此上下文管理器验证(可选)values 是否来自同一个图,确保该图是默认图,并推送名称范围和变量范围。

如果 name_or_scope 不是 None,则按原样使用。如果name_or_scope 为无,则使用default_name。在这种情况下,如果之前在同一范围内使用了相同的名称,则将通过将 _N 附加到它来使其唯一。

变量范围允许您创建新变量并共享已创建的变量,同时提供检查以防止意外创建或共享。有关详细信息,请参阅如何使用变量作用域,这里我们仅提供几个基本示例。

当禁用即刻执行时,变量范围按预期工作。

tf.compat.v1.disable_eager_execution()

如何创建新变量的简单示例:

with tf.compat.v1.variable_scope("foo"):
    with tf.compat.v1.variable_scope("bar"):
        v = tf.compat.v1.get_variable("v", [1])
        assert v.name == "foo/bar/v:0"

如何安全地重新输入预制变量范围的简单示例:

with tf.compat.v1.variable_scope("foo") as vs:
  pass

# Re-enter the variable scope.
with tf.compat.v1.variable_scope(vs,
                       auxiliary_name_scope=False) as vs1:
  # Restore the original name_scope.
  with tf.name_scope(vs1.original_name_scope):
      v = tf.compat.v1.get_variable("v", [1])
      assert v.name == "foo/v:0"
      c = tf.constant([1], name="c")
      assert c.name == "foo/c:0"

请记住,一旦退出父作用域,default_name 的计数器就会被丢弃。因此,当代码重新进入范围时(例如通过保存它),所有嵌套的default_name 计数器都将重新启动。

例如:

with tf.compat.v1.variable_scope("foo") as vs:
  with tf.compat.v1.variable_scope(None, default_name="bar"):
    v = tf.compat.v1.get_variable("a", [1])
    assert v.name == "foo/bar/a:0", v.name
  with tf.compat.v1.variable_scope(None, default_name="bar"):
    v = tf.compat.v1.get_variable("b", [1])
    assert v.name == "foo/bar_1/b:0"

with tf.compat.v1.variable_scope(vs):
  with tf.compat.v1.variable_scope(None, default_name="bar"):
    v = tf.compat.v1.get_variable("c", [1])
    assert v.name == "foo/bar/c:0"   # Uses bar instead of bar_2!

共享变量AUTO_REUSE的基本示例:

def foo():
  with tf.compat.v1.variable_scope("foo", reuse=tf.compat.v1.AUTO_REUSE):
    v = tf.compat.v1.get_variable("v", [1])
  return v

v1 = foo()  # Creates v.
v2 = foo()  # Gets the same, existing v.
assert v1 == v2

使用reuse=True 共享变量的基本示例:

with tf.compat.v1.variable_scope("foo"):
    v = tf.compat.v1.get_variable("v", [1])
with tf.compat.v1.variable_scope("foo", reuse=True):
    v1 = tf.compat.v1.get_variable("v", [1])
assert v1 == v

通过捕获范围和设置重用来共享变量:

with tf.compat.v1.variable_scope("foo") as scope:
    v = tf.compat.v1.get_variable("v", [1])
    scope.reuse_variables()
    v1 = tf.compat.v1.get_variable("v", [1])
assert v1 == v

为了防止意外共享变量,我们在非重用范围内获取现有变量时引发异常。

with tf.compat.v1.variable_scope("foo"):
    v = tf.compat.v1.get_variable("v", [1])
    v1 = tf.compat.v1.get_variable("v", [1])
    #  Raises ValueError("... v already exists ...").

同样,我们在尝试获取重用模式下不存在的变量时引发异常。

with tf.compat.v1.variable_scope("foo", reuse=True):
    v = tf.compat.v1.get_variable("v", [1])
    #  Raises ValueError("... v does not exists ...").

请注意,reuse 标志是继承的:如果我们打开一个重用范围,那么它的所有 sub-scopes 也将成为重用。

关于名称范围的说明:设置 reuse 不会影响其他操作的命名,例如 mult。参见 github#6189 上的相关讨论

请注意,直到版本 1.0(包括版本 1.0),允许(尽管明确不鼓励)将 False 传递给重用参数,从而产生与 None 略有不同的未记录行为。从 1.1.0 开始,传递 None 和 False 作为重用具有完全相同的效果。

关于在multi-threaded 环境中使用变量作用域的注意事项:变量作用域是线程本地的,因此一个线程不会看到另一个线程的当前作用域。此外,在使用 default_name 时,也仅在每个线程的基础上生成唯一的范围名称。如果在不同的线程中使用了相同的名称,则不会阻止新线程创建相同的范围。但是,底层变量存储是跨线程共享的(在同一个图中)。因此,如果另一个线程试图创建一个与前一个线程创建的变量同名的新变量,除非重用为 True,否则它将失败。

此外,每个线程都以一个空的变量范围开始。因此,如果您希望保留主线程范围内的名称前缀,您应该捕获主线程的范围并在每个线程中重新输入它。例如

main_thread_scope = variable_scope.get_variable_scope()

# Thread's target function:
def thread_target_fn(captured_scope):
  with variable_scope.variable_scope(captured_scope):
    # .... regular code for this thread


thread = threading.Thread(target=thread_target_fn, args=(main_thread_scope,))

相关用法


注:本文由纯净天空筛选整理自tensorflow.org大神的英文原创作品 tf.compat.v1.variable_scope。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。