[tf]中的variable scope以及三种创建变量方式

变量的命名空间是为了更好的管理和重用变量,因为神经网络的节点和参数非常多,我们需要scope来清楚的知道变量是那一层的。

  • name_scope: 为了更好地管理变量的命名空间而提出的。比如在 tensorboard 中,因为引入了 name_scope, 我们的 Graph 看起来才井然有序
  • variable_scope:绝大部分情况下,根tf.get_variable()配合使用,实现变量共享的功能。

三种方式创建变量

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

tf.placeholder

  • tf.placeholder(dtype, shape=None, name=None) 占位符。trainable==False,类似于函数的传递参数,在图运行前必须先传入值。
import tensorflow as tf
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = input1 * input2
with tf.Session() as sess:
    print sess.run(output, feed_dict = {input1:[3.], input2: [4.]})

tf.Variable

  • tf.Variable([1,2,3], initializer = init , name = 'va') ,先创建形状,在创建初始化,再创建name的方式。
  • tf.Variable(tf.truncated_normal([1,2,3], stddev =0.1)):直接创建初始化:应该是最为方便的方式。
  • tf.Variable(tf.constant(0.1 , shape =[1,2,3])):也是直接创建初始化的一种形式,只不过是直接使用常数进行初始化。
  • global_step = tf.Variable(0 , trainable = False):创建一个用于记录的不可训练的变量。
  • 下面这两个定义是等价的,常数初始化函数tf.constant_initializer和常数生成函数tf.constant在功能上是一致的。
v = tf.get_variable('v', shape =[1], initializer = tf.constant_initializer(1.0))
v = tf.Variable(tf.constant(1.0 , shape =[1], name = 'v')

tf.get_variable 不仅可以创建变量,也可以用来获取变量。

tf.get_variable中变量名称是一个必填的参数,这个函数会根据这个名字常见或获取变量,如果创建失败(有同名的参数),那么程序就会报错,这是为了避免无意识的变量复用造成的错误。

  • tf.get_variable('conv_1',initializer = tf.random_normal(shape=[1,2,3],minval=0.4,maxval=1.4))一般都是和 tf.variable_scope() 配合使用,从而实现变量共享的功能。
  • tf.name_scope() 并不会对tf.get_variable() 创建的变量有任何影响。 即在name_scope('hello')内部使用 get_variable() 中定义的 variable ,这个variable的 name 并没有 “hello/”前缀。
  • tf.name_scope() 主要是用来管理命名空间的,这样子让我们的整个模型更加有条理。而 tf.variable_scope() 的作用是为了实现变量共享,它和tf.get_variable()来完成变量共享的功能,tf.name_scope()可以和with tf.variable_scope():联合使用,用于给get_variable创建的变量加上联合命名空间
with tf.name_scope("name1"):
    with tf.variable_scope("var1"):
        w = tf.get_variable("w",shape=[2])
        res = tf.add(w,[3])
>>var1/w:0
name1/var1/Add:0
  • tf.trainable_variables()获取所有的可训练的变量,默认的是tf.variabletf.get_variable()创建的。
vs = tf.trainable_variables()
print 'There are %d train_able_variables in the Graph: ' % len(vs)
for v in vs:
with tf.name_scope('nsc1'):
    v1 = tf.Variable([1], name='v1')
    with tf.variable_scope('vsc1'):
        v2 = tf.Variable([1], name='v2')
        v3 = tf.get_variable(name='v3', shape=[])
print ('v1.name: ', v1.name)
print ('v2.name: ', v2.name)
print ('v3.name: ', v3.name)
>>v1.name:  nsc1/v1:0
v2.name:  nsc1/vsc1/v2:0
v3.name:  vsc1/v3:0

一个例子比较variable()和get_ variable()

  • variable可以看到 重复命名的,后面使用标号_1进行区分。
import tensorflow as tf
# 设置GPU按需增长
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)
 
# 拿官方的例子改动一下
def my_image_filter():
    conv1_weights = tf.Variable(tf.random_normal([5, 5, 32, 32]),
        name="conv1_weights")
    conv1_biases = tf.Variable(tf.zeros([32]), name="conv1_biases")
    conv2_weights = tf.Variable(tf.random_normal([5, 5, 32, 32]),
        name="conv2_weights")
    conv2_biases = tf.Variable(tf.zeros([32]), name="conv2_biases")
    return None
 
# First call creates one set of 4 variables.
result1 = my_image_filter()
# Another set of 4 variables is created in the second call.
result2 = my_image_filter()
# 获取所有的可训练变量
vs = tf.trainable_variables()
print 'There are %d train_able_variables in the Graph: ' % len(vs)
for v in vs:
    print v
>>There are 8 train_able_variables in the Graph: 
Tensor("conv1_weights/read:0", shape=(5, 5, 32, 32), dtype=float32)
Tensor("conv1_biases/read:0", shape=(32,), dtype=float32)
Tensor("conv2_weights/read:0", shape=(5, 5, 32, 32), dtype=float32)
Tensor("conv2_biases/read:0", shape=(32,), dtype=float32)
Tensor("conv1_weights_1/read:0", shape=(5, 5, 32, 32), dtype=float32)
Tensor("conv1_biases_1/read:0", shape=(32,), dtype=float32)
Tensor("conv2_weights_1/read:0", shape=(5, 5, 32, 32), dtype=float32)
Tensor("conv2_biases_1/read:0", shape=(32,), dtype=float32)
  • tf.get_variable() 可以使用scope.reuse_variables()来重用变量,除了使用这个函数还可以在with tf.variable_scope("image_filters",reuse=True) as scope:中直接变量重用。
import tensorflow as tf
# 设置GPU按需增长
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)
 
# 下面是定义一个卷积层的通用方式
def conv_relu(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))
    return None
def my_image_filter():
    # 按照下面的方式定义卷积层,非常直观,而且富有层次感
    with tf.variable_scope("conv1"):
        # Variables created here will be named "conv1/weights", "conv1/biases".
        relu1 = conv_relu([5, 5, 32, 32], [32])
    with tf.variable_scope("conv2"):
        # Variables created here will be named "conv2/weights", "conv2/biases".
        return conv_relu( [5, 5, 32, 32], [32])
with tf.variable_scope("image_filters") as scope:
    # 下面我们两次调用 my_image_filter 函数,但是由于引入了 变量共享机制
    # 可以看到我们只是创建了一遍网络结构。
    result1 = my_image_filter()
    scope.reuse_variables()
    result2 = my_image_filter()
# 看看下面,完美地实现了变量共享!!!
vs = tf.trainable_variables()
print 'There are %d train_able_variables in the Graph: ' % len(vs)
for v in vs:
    print v
>>There are 4 train_able_variables in the Graph: 
Tensor("image_filters/conv1/weights/read:0", shape=(5, 5, 32, 32), dtype=float32)
Tensor("image_filters/conv1/biases/read:0", shape=(32,), dtype=float32)
Tensor("image_filters/conv2/weights/read:0", shape=(5, 5, 32, 32), dtype=float32)
Tensor("image_filters/conv2/biases/read:0", shape=(32,), dtype=float32)

一个变量重用的例子

import tensorflow as tf
#在名字为foo的命名空间内创建名字为v的变量
with tf.variable_scope("foo"):
    #创建一个常量为1的v
    v= tf.get_variable('v',[1],initializer = tf.constant_initializer(1.0))
#因为在foo空间已经创建v的变量,所以下面的代码会报错
#with tf.variable_scope("foo"):
#   v= tf.get_variable('v',[1])
#在生成上下文管理器时,将参数reuse设置为True。这样tf.get_variable的函数将直接获取已声明的变量
#且调用with tf.variable_scope("foo")必须是定义的foo空间,而不能是with tf.variable_scope("")未命名或者其他空间。
with tf.variable_scope("foo",reuse =True):
    v1= tf.get_variable('v',[1])#  不写[1]也可以
    print(v1==v) #输出为True,代表v1与v是相同的变量

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容