• 【TF-2-2】Tensorflow-变量作用域


    目录

    1. 背景
    2. 简介
    3. name_scope
    4. variable_scope
    5. 实例

    一、背景

    通过tf.Variable我们可以创建变量,但是当模型复杂的时候,需要构建大量的变量集,这样会导致我们对于变量管理的复杂性,而且没法共享变量(存在多个相似的变量)。针对这个问题,可以通过TensorFlow提供的变量作用域机制来解决,在构建一个图的时候,就可以非常容易的使用共享命名的变量

    二、简介

    Tensorflow中有两个作用域,一个是name_scope,另一个是variable_scope

    name_score的主要作用是为op_name前加前缀,variable_score是为get_variable创建的变量的名字前缀。简单来讲:使用tf.Variable创建的变量受name_score和variable_score的效果,会给变量添加前缀,但是使用tf.get_variable创建变量只受variable_score的效果。

    注意:variable_score内部会创建一个同名的name_score

    三、name_scope

    用于为变量划分范围。在TensorFlow 中常常会有数以千计的节点,在可视化的过程中很难一下子展示出来,因此用 name_scope 为变量划分范围,在可视化中,这表示在计算图中的一个层级。name_scope会影响 op_name,不会影响用 get_variable()创建的变量,而会影响通过 Variable()创建的变量以及操作的名称,给他们添加一个前缀。

    四、variable_scope

    变量作用域机制在TensorFlow中主要通过两部分组成:tf.get_variable和tf.variable_scope

    v = tf.get_variable(name, shape, dtype, initializer) # 通过所给的名字创建或是返回一个变量

    tf.variable_scope(<scope_name>) # 为变量指定命名空间

    4.1 tf.get_variable

    通过所给定的名字创建或者返回一个对应的变量,这个方法在建立新的变量时与tf.Variable()完全相同。

    • tf.Variable()在定义的时候必须初始化,而tf.get_variable()定义的时候可以先不进行初始化操作。
    • 想要进行变量共享,必须使用tf.get_variable()实现,搭配命名空间,以及reuse关键字的使用,就可以实现变量的共享;而tf.Variable()每次都会生成一个新的变量。

    tf.get_variable方法在调用的时候,主要需要给定参数名称name,形状shape,数据类型dtype以及初始化方式initializer四个参数,前两个参数是必须的。

    • tf.get_variable常用的initializer初始化器:

    初始化器

    描述

    tf.constant_initializer(value)

    初始化为给定的常数值value

    tf.random_uniform_initializer(a, b)

    初始化为从a到b的均匀分布的随机值

    tf.random_normal_initializer(mean, stddev)

    初始化为均值为mean、 方差为stddev的服从高斯分布的随机值

    tf.orthogonal_initializer(gini=1.0)

    初始化一个正交矩阵, gini参数作用是最终返回的矩阵是随机矩阵乘以gini的结果

    tf.identity_initializer(gini=1.0)

    初始化一个单位矩阵, gini参数作用是最终返回的矩阵是随机矩阵乘以gini的结果

    简单代码:

    import tensorflow as tf
    with tf.variable_scope("foo"):
    v = tf.get_variable("v",[1],initializer=tf.constant_initializer(1.0))
    print(v.name)

    with tf.variable_scope("la"):
    with tf.variable_scope("bar"):
    v1 = tf.get_variable("v",[1])
    print(v1.name);
    with tf.variable_scope("b"):
    v2=tf.get_variable("c",[1])
    print(v2.name)
    with tf.variable_scope(""):
    v2 = tf.get_variable("foo/c", [1])
    print(v2.name)

    结果:

    foo/v:0

    la/bar/v:0

    la/bar/b/c:0

    foo/c:0

    4.2 tf.variable_scope

    为通过创建的变量或者操作指定命名空间。它会管理在名为scope_name的域(scope)下传递给tf.get_variable的所有变量名(组成了一个变量空间),根据规则确定这些变量是否进行复用。这个方法最重要的参数是reuse,有None,tf.AUTO_REUSE与True三个选项。

    当reuse值为False(不允许设置):作用域就是创建新变量设置的,此时要求对应的变量不存在,否则报错;

    with tf.variable_scope("foo"):

    v = tf.get_variable("v", [1])

    v2 = tf.get_variable("v", [1])#这里v变量已经定义过了,所以会报错

    assert v.name == "foo/v:0"

    当reuse值为True:作用域就是为重用变量所设置的,此时要求对应的变量必须存在,否则报错。

    当reuse的值为tf.AUTO_REUSE的时候,表示如果变量存在就重用变量,如果变量不存在,就创建新变量返回。(备注:reuse一般设置在variable score对象上)

    • tf.variable_score方法的作用就是定义一个作用域,定义在variable_score作用域中的变量和操作,会将variable score的名称作为前缀添加到变量/操作名称前,支持嵌套的作用域,添加前缀规则和文件目录路径的规则类似。
    • tf.variable_score参数如果给定的是一个已经存在的作用域对象的时候,那么构建变量的时候表示直接跳过当前作用域前缀,直接成为一个完全不同与现在的作用域(直接创建给定作用域下的变量)。但是构建操作的时候,还是和嵌套的方式一样,直接添加子作用域。
    • tf.variable_score参数中,可以给定当前作用域中默认的初始化器initializer,并且子作用域会直接继承父作用域的相关参数(是否重用、默认初始化器等)

    五、实例

    推荐方式二,代码如下:

        1 	def my_func(x):
        2 	    # initializer:初始化器
        3 	    # w = tf.Variable(tf.random_normal([1]), name='w')[0]
        4 	    # b = tf.Variable(tf.random_normal([1]), name='b')[0]
        5 	    w = tf.get_variable(name='w', shape=[1], initializer=tf.random_normal_initializer())[0]
        6 	    b = tf.get_variable(name='b', shape=[1], initializer=tf.random_normal_initializer())[0]
        7 	    r = w * x + b
        8 	    return r, w, b
        9 	def func(x):
       10 	    with tf.variable_scope('op1', reuse=tf.AUTO_REUSE):
       11 	        r1 = my_func(x)
       12 	    return r1
       13 	# 下面两行代码还是属于图的构建
       14 	x1 = tf.constant(3, dtype=tf.float32, name='x1')
       15 	with tf.variable_scope('func1'):
       16 	    r1 = func(x1)
       17 	with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:
       18 	    tf.global_variables_initializer().run()  # 初始化
       19 	    print(sess.run(r1))      # 执行结果
       20 
    

      

  • 相关阅读:
    关于一个单机游戏发行的一些见解
    怎么租借电话号码
    NUMA架构的优缺点
    Windows 安装PostgreSQL
    Oracle查询当前用户下的所有表及sqlplus 设置 列宽
    Xshell调整终端显示的最大行数(缓冲区)
    PostgreSQL 索引膨胀
    Linux 清空缓存
    load多个数据文件的yaml
    Linux LVM逻辑卷配置过程详解(创建,增加,减少,删除,卸载)
  • 原文地址:https://www.cnblogs.com/yifanrensheng/p/12507826.html
Copyright © 2020-2023  润新知