''' Created on Apr 21, 2017 @author: P0079482 ''' #如何通過tf.variable_scope函數來控制tf.ger_variable函數獲取已經創建過的變量 #在名字為foo的命名空間內創建名字為v的變量 import tensorflow as tf with tf.variable_scope("foo"): v = tf.get_variable("v",shape=[1],initializer=tf.constant_initializer(1.0))
#因為在命名空間foo中已經存在名為v的變量,所有下面的代碼將會報錯: #Variable foo/v already exists, with tf.variable_scope("foo"): v = tf.get_variable("v",[1])
#在生成上下文管理器時,將參數reuse設置為True.這樣tf.get_variable函數將直接獲取已經聲明的變量 with tf.variable_scope("foo",reuse=True): v1 = tf.get_variable("v",[1]) print(v==v1) #輸出為True,代表v,v1代表的是相同的Tensorflow中的變量
#將參數reuse設置為True是,tf.variable_scope將只能獲取已經創建過的變量。 #因為在命名空間bar中還沒有創建變量v,所以下面的代碼將會報錯 with tf.variable_scope("bar",reuse=True): v = tf.get_variable("v",[1])
#如果tf.variable_scope函數使用reuse=None或者reuse=False創建上下文管理器 #tf.get_variable操作將創建新的變量。 #如果同名的變量已經存在,則tf.get_variable函數將報錯 #Tensorflow中tf.variable_scope函數是可以嵌套的 with tf.variable_scope("root"): #可以通過tf.get_variable_scope().reuse函數來獲取上下文管理器中reuse參數的值 print(tf.get_variable_scope().reuse) #輸出False,即最外層reuse是False with tf.variable_scope("foo",reuse=True): #新建一個嵌套的上下文管理器並指定reuse為True print(tf.get_variable_scope().reuse) #輸出True with tf.variable_scope("bar"): #新建一個嵌套的上下文管理器,但不指定reuse,這時reuse的取值會和外面一層保持一致 print(tf.get_variable_scope().reuse) #輸出True print(tf.get_variable_scope().reuse) #輸出False
#tf.variable_scope函數生成的上下文管理器也會創建一個Tensorflow中的命名空間 #在命名空間內創建的變量名稱都會帶上這個命名空間作為前綴 #所以tf.variable_scope函數除了可以控制tf.get_variable執行的功能之外 #這個函數也提供了一個管理命名空間的方式 v1 = tf.get_variable("v",[1]) print(v1.name)#輸出v:0 "v"為變量的名稱,":0"表示這個變量是生成變量這個運算的第一個結果
with tf.variable_scope("foo"): v2 = tf.get_variable("v",[1]) print(v2.name)#輸出foo/v:0 在tf.variable_scope中創建的變量,名稱前面會 #加入命名空間的名稱,並通過/來分隔命名空間的名稱和變量的名稱
with tf.variable_scope("foo"): with tf.variable_scope("bar"): v3 = tf.get_variable("v",[1]) print(v3.name) #輸出foo/bar/v:0 命名空間可以嵌套,同時變量的名稱也會加入所有命名空間的名稱作為前綴 v4 = tf.get_variable("v1",[1]) print(v4.name) #輸出foo/v1:0 當命名空間退出之后,變量名稱也就不會再被加入其前綴了
#創建一個名稱為空的命名空間,並設置reuse=True with tf.variable_scope("",reuse=True): v5=tf.get_variable("foo/bar/v",[1])#可以直接通過帶命名空間名稱的變量名來獲取其他命名空間下的變量。 print(v5==v3) v6=tf.get_variable("foo/v1",[1]) print(v6==v4)
#通過tf.variable_scope和tf.get_variable函數,以下代碼對inference函數的前向傳播結果做了一些改進 def inference(input_tensor,reuse=False): #定義第一層神經網絡的變量和前向傳播過程 with tf.variable_scope('layer1',reuse=reuse): #根據傳進來的reuse來判斷是創建新變量還是使用已經創建好了。在第一次構造網絡時需要創建新的變量, #以后每次調用這個函數都直接使用reuse=True就不需要每次將變量傳進來了 weights= tf.get_variable("weights",[INPUT_NODE,LAYER1_NODE],initializer=tf.truncated_normal_initializer(stddev=0.1)) biases= tf.get_variable("biases",[LAYER1_NODE],initializer=tf.constant_initializer(0.0)) layer1 = tf.nn.relu(tf.matmul(input_tensor,weights)+biases) #類似地定義第二層神經網絡的變量和前向傳播過程 with tf.variable_scope('layer2',reuse=reuse): weights=tf.get_variable("weights",[LAYER1_NODE,OUTPUT_NODE],initializer=tf.truncated_normal_initializer(stddev=0.1)) biases=tf.get_variable("biases",[OUTPUT_NODE],initializer=tf.constant_initializer(0.0)) layer2=tf.matmul(layer1,weights)+biases #返回最后的前向傳播結果 return layer2 x=tf.placeholder(tf.float32,[None,INPUT_NODE],name='x-input') y=inference(x) #在程序中需要使用訓練好的神經網絡進行推倒時,可以直接調用inference(new_x,True)