zoukankan      html  css  js  c++  java
  • tf.name_scope()、tf.variable_scope()函数解析(最清晰的解释)

    欢迎关注WX公众号:【程序员管小亮】

    最近在看tf.slim实现的inception_v1的代码,发现一个函数tf.variable_scope()不太清楚,查询到网上多对比name和variable,特意记录一下。

    论文翻译:GoogLeNet - Going Deeper with Convolutions全文翻译

    代码实现
    在这里插入图片描述

    1 tf.name_scope(‘scope_name’)

    tf.name_scope 主要结合 tf.Variable() 来使用,方便参数命名管理。

    import tensorflow as tf
    
    # 也就是说,它的主要目的是为了更加方便地管理参数命名。
    # 与 tf.Variable() 结合使用。简化了命名
    with tf.name_scope('conv1') as scope:
        weights1 = tf.Variable([1.0, 2.0], name='weights')
        bias1 = tf.Variable([0.3], name='bias')
    
    # 下面是在另外一个命名空间来定义变量的
    with tf.name_scope('conv2') as scope:
        weights2 = tf.Variable([4.0, 2.0], name='weights')
        bias2 = tf.Variable([0.33], name='bias')
    
    # 所以,实际上weights1 和 weights2 这两个引用名指向了不同的空间,不会冲突
    print(weights1.name)
    print(weights2.name)
    
    > conv1/weights:0
    > conv2/weights:0
    
    import tensorflow as tf
    
    # 注意,这里的 with 和 python 中其他的 with 是不一样的
    # 执行完 with 里边的语句之后,这个 conv1/ 和 conv2/ 空间还是在内存中的
    # 这时候如果再次执行上面的代码就会再生成其他命名空间
    with tf.name_scope('conv1') as scope:
        weights1 = tf.Variable([1.0, 2.0], name='weights')
        bias1 = tf.Variable([0.3], name='bias')
    
    with tf.name_scope('conv2') as scope:
        weights2 = tf.Variable([4.0, 2.0], name='weights')
        bias2 = tf.Variable([0.33], name='bias')
    
    print(weights1.name)
    print(weights2.name)
    
    > conv1_1/weights:0
    > conv2_1/weights:0
    

    为什么变量名加了后缀将在第三节说明。

    2 tf.variable_scope(‘scope_name’)

    tf.variable_scope() 主要结合 tf.get_variable() 来使用,实现 变量共享。

    # 这里是正确的打开方式~~~可以看出,name 参数才是对象的唯一标识
    import tensorflow as tf
    
    with tf.variable_scope('v_scope') as scope1:
        Weights1 = tf.get_variable('Weights', shape=[2,3])
        bias1 = tf.get_variable('bias', shape=[3])
    
    # 下面来共享上面已经定义好的变量
    # note: 在下面的 scope 中的变量必须已经定义过了,才能设置 reuse=True,否则会报错
    with tf.variable_scope('v_scope', reuse=True) as scope2:
        Weights2 = tf.get_variable('Weights')
    
    print(Weights1.name)
    print(Weights2.name)
    # 可以看到这两个引用名称指向的是同一个内存对象
    
    > v_scope/Weights:0
    > v_scope/Weights:0
    

    tf.variable_scope() 也可以结合 tf.variable() 一块使用。

    import tensorflow as tf
    
    # 注意, bias1 的定义方式
    with tf.variable_scope('v_scope') as scope1:
        Weights1 = tf.get_variable('Weights', shape=[2,3])
    #	bias1 = tf.Variable([0.52], name='bias')
    
    # 下面来共享上面已经定义好的变量
    # note: 在下面的 scope 中的 get_variable()变量必须已经定义过了,
    # 才能设置 reuse=True,否则会报错
    with tf.variable_scope('v_scope', reuse=True) as scope2:
        Weights2 = tf.get_variable('Weights')
        bias2 = tf.Variable([0.52], name='bias')
    
    print(Weights1.name)
    print(Weights2.name)
    #print(bias1.name)
    print(bias2.name)
    
    > v_scope/Weights:0
    > v_scope/Weights:0
    > v_scope_1/bias:0
    

    如果 reuse=True 的scope中的变量没有已经定义,会报错!!

    import tensorflow as tf
    
    # 注意, bias1 的定义方式
    with tf.variable_scope('v_scope') as scope1:
        Weights1 = tf.get_variable('Weights', shape=[2,3])
        bias1 = tf.Variable([0.52], name='bias')
    
    print(Weights1.name)
    print(bias1.name)
    
    # 下面来共享上面已经定义好的变量
    # note: 在下面的 scope 中的get_variable()变量必须已经定义过了,
    # 才能设置 reuse=True,否则会报错
    with tf.variable_scope('v_scope', reuse=True) as scope2:
        Weights2 = tf.get_variable('Weights')
        bias2 = tf.get_variable('bias', [1])  # 'bias'
    
    print(Weights2.name)
    print(bias2.name)
    
    # 这样子的话就会报错
    # Variable v_scope/bias does not exist, or was not created with tf.get_variable()
    

    3 name_scope和variable_scope

    tf.get_variable()遇到重命名的变量创建且变量名没有设置成共享变量(所谓的共享是指在同一参数空间下的共享,参数空间名称不一样就不能共享了)时,就会报错 ;相对应的,变量名称这个参数是必填参数,tf.get_variable()会根据这个参数去创建或者获取变量。如果这个变量name已经存在,直接使用这个变量;如果不存在,则重新创建。

    tf.Variable()每次调用都会产生一个新的变量,它会自动检测命名冲突并自行处理,如果这个变量已存在,则后缀会增加0、1、2等数字编号予以区别。

    import tensorflow as tf
    
    with tf.name_scope("a_name_scope"):
    	initializer = tf.constant_initializer(value=1)
    	var1 = tf.get_variable(name='var1', shape=[1], 
    						dtype=tf.float32,initializer=initializer)
    	var2 = tf.Variable(name='var2', initial_value=[2], dtype=tf.float32)
    	var21 = tf.Variable(name='var2', initial_value=[2.1], dtype=tf.float32)
    	var22 = tf.Variable(name='var2', initial_value=[2.2], dtype=tf.float32)
    
    with tf.Session() as sess:
    	sess.run(tf.initialize_all_variables())
    	print(var1.name)
    	print(sess.run(var1))
    	print(var2.name)
    	print(sess.run(var2))
    	print(var21.name)
    	print(sess.run(var21))
    	print(var22.name)
    	print(sess.run(var22))
    
    > var1:0
    > [1.]
    > a_name_scope/var2:0
    > [2.]
    > a_name_scope/var2_1:0
    > [2.1]
    > a_name_scope/var2_2:0
    > [2.2]
    

    可以看出使用 tf.Variable() 定义变量的时候, 虽然var2, var21, var22的 name 一样, 但是为了不重复变量名, Tensorflow 为它们做了附加的区分,因为输出的变量名是不一样的. 所以, 本质上tensorflow令 var2, var21, var22 成为不一样的变量。

    变量作用域也支持嵌套定义。tf.get_variable得到的结果带有前缀,方便知道是哪一个嵌套下的变量。

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

    python课程推荐。
    在这里插入图片描述

    参考文章:
  • 相关阅读:
    zookeeper集群搭建
    Redis集群管理
    postman的使用
    python接口自动化:requests+ddt+htmltestrunner数据驱动框架
    python实现建立websocket通信
    python实现建立soap通信(调用及测试webservice接口)
    python接口自动化:响应内容中json字符串对象的处理
    python接口自动化:调试接口的代码(无token情况下)
    python接口自动化:https请求,取消警告
    python接口自动化:对外接口sign签名
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13302854.html
Copyright © 2011-2022 走看看