TensorFlow : name_scope和variable_scope 区别分析

前言

最近学习TensorFlow,看源码,其中有一些代码就在with tf.name_scope(‘nameScope’):下书写,定义变量,还有一些就在with tf.variable_scope(‘varScope’):下面,就很奇怪,想知道是怎么回事为什么要用这两个东西,写下这篇博客。

TensorFlow生成变量

首先要将的是TensorFlow生成变量,这主要有两种方式:

  • tf.get_variable()
  • tf.Variable()
  • tf.get_variable()

    我们先了解一下tf.get_variable() ,代码如下:

    var_0 = tf.get_variable(name='test2002000', shape=[1, ]) #  name 必须填写,
    var_01 = tf.get_variable(name='test2002001', shape=[1, ]) 
    
    var_1 = tf.get_variable(shape=[1, ], name='var_122')  # 这里已经生成了name=var_122 的变量
    var_2 = tf.get_variable(shape=[1, ], name='var_122')  # 报错,有重复的变量名称
    
    print(var_0.name)   # test22002000:0
    
    print(var_01.name)  # test22002001:0
    
    print(var_1.name)
    print(var_2.name)
    
    

    运行可以知道,会以name值作为该变量在TF中的名称,而且用get_variable 不能name名存在,存在就会报错,报错信息:

    ValueError: Variable var_122 already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope? Originally defined at:
    

    报错信息很直接,就是name值重复了,你把name值改成不一样就不会有问题。

    tf.Variable()的测试代码
    var_0 = tf.Variable(initial_value=[0])
    var_01 = tf.Variable(initial_value=[0])
    
    var_1 = tf.Variable(initial_value=[0], name='var_1')
    var_2 = tf.Variable(initial_value=[0], name='var_1')
    var_3 = tf.Variable(initial_value=[0], name='var_1')
    
    print(var_0.name)   #  Variable_1:0
    print(var_01.name)   #  Variable_2:0
    
    print(var_1.name)  # var_1_1:0
    print(var_2.name)  # var_1_2:0
    print(var_3.name)  # var_1_3:0
    

    tf.Variable 可以name值一样,如果不给name就会默认Variable_开头,后面接1、2、3等数字,这样还不会报错。
    那这样就涉及到一个问题,我定义了一个变量,给这个变量一个name了,这个变量我后面还想利用,从变成语言的角度来看,我是不是可以把这个变量定义为全局变量,这样,我就可以直接拿变量,但在TF中,特别是定义的网路中,好像不是这样的,重点就是为什么要给变量一个name属性?我猜测在TF中定义网络用name来区分变量,同样用name作为一个变量来赋值,用name来获取变量值,不知道是不是这样,暂时自己的一个猜测,我们来验证一下。

    tf.variable_scope(‘variableScope’)

    先看一段代码:

    varScope_Var_1 = tf.Variable(initial_value=[0], name='var_11')
    print("varScope_Var_1 = ",varScope_Var_1)
    var_1 = tf.get_variable(shape=[1, ],name='var_33')  #  
    print("var_1 = ",var_1)
    
    with tf.variable_scope('varScope'):
        
        test_var_1 = tf.get_variable(name='var_11', shape=[1, ])
        print("test_var_1=",test_var_1)
        
        test_var_2 = tf.get_variable(name='var_33', shape=[1, ])
        print("test_var_2=",test_var_2)
       
        varScope_Var_2 = tf.Variable(initial_value=[0], name='var_44')
    print(varScope_Var_1.name)
    print(varScope_Var_2.name)
    
    

    代码结果为:

    varScope_Var_1 =  <tf.Variable 'var_11:0' shape=(1,) dtype=int32_ref>
    var_1 =  <tf.Variable 'var_33:0' shape=(1,) dtype=float32_ref>
    test_var_1= <tf.Variable 'varScope/var_11:0' shape=(1,) dtype=float32_ref>
    test_var_2= <tf.Variable 'varScope/var_33:0' shape=(1,) dtype=float32_ref>
    var_11:0
    varScope/var_44:0
    

    我们可以看到 tf.variable_scope 会影响tf.get_variable和tf.Variable 的变量值,这个变量值都会有一个前缀varScope。如果我们要取出这个变量该如何操作:

    
    with tf.variable_scope('varScope', reuse=True):  #  reuse=True 表示 可以允许你复用变量
        test_var_3 = tf.get_variable(name='var_11', shape=[1, ])     
        print("test_var_3=",test_var_3.name)
    	test_var_4 = tf.get_variable(name='var_44', shape=[1, ])      # 报错,不存在
        print("test_var_4=",test_var_4.name)
    
    with tf.variable_scope('varScope111', reuse=True):
        test_var_5 = tf.get_variable(name='var_11', shape=[1, ])      # 报错,不存在
        print("test_var_5=",test_var_5.name)
        
    

    结果输出:

    test_var_3= varScope/var_11:0
    报错:ValueError: Variable varScope111/var_11 does not exist, or was not created with tf.get_variable(). Did you mean to set reuse=tf.AUTO_REUSE in VarScope?
    

    也就说如果tf.variable_scope 命名空间中有这变量name值,就可以获取到,这样的情况就有一个更加专业的名词共享,如果没有这个name值, tf.get_variable 就会报错。
    如果reuse=False,情况就不一样了:

    with tf.variable_scope('varScope111', reuse=False):
        test_var_5 = tf.get_variable(name='var_11', shape=[1, ])      # 报错
        print("test_var_5=",test_var_5.name)
    

    结果输出:

    test_var_5= varScope111/var_11:0
    

    没有就生成一个新的变量,这个变量还可以用来共享,我们从上边的情况中可以得出,get_variable 可以variable_scope下共享变量,并且会加前缀命名空间,tf.Variable 就不能共享变量,但是加前缀命名空间。

    tf.name_scope(‘nameScope’)

    var_0 = tf.Variable(initial_value=[0],name="test1")
    print(var_0.name)
    
    test_var_1 = tf.get_variable(name='test1', shape=[1, ])
    print("test_var_1.name=",test_var_1.name)
    
    with tf.name_scope('nameScope'):
    
        test_var_2 = tf.get_variable(name='test2', shape=[1, ])
        print("test_var_2.name=",test_var_2.name)
    
        nameScope_Var_1 = tf.Variable(initial_value=[0], name='var_1')
        nameScope_Var_2 = tf.Variable(initial_value=[0], name='var_1')
        nameScope_Var_3 = tf.Variable(initial_value=[0], name='var_1')
        print(nameScope_Var_1.name)
        print(nameScope_Var_2.name)
        
    

    运行结果:

    test1:0
    test_var_1.name= test1_1:0
    test_var_2.name= test2:0
    nameScope/var_1:0
    nameScope/var_1_1:0
    

    发现tf.name_scope 对 tf.get_variable 的变量名 不起作用, 对tf.Variable 会产生一个前缀,这个前缀类似文件路径。

    总结

  • tf.variable_scope 对tf.get_variable 和tf.Variable 的变量名都有影响,会加上命名空间前缀,如果要实现变量共享,就必须将tf.variable_scope的reuse=True,而且命名空间必须一样,否则就获取不到变量,报错z。
  • tf.name_scope 对tf.Variable 的变量名有影响,对tf.get_variable没有影响。 后面再继续总结,有可能前面一些内容没有总结到位。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值