【TensorFlow學習筆記】5:variable_scope和name_scope,圖的基本操作
阿新 • • 發佈:2018-12-26
學習《深度學習之TensorFlow》時的一些實踐。
variable_scope
一般的巢狀
上節有學到在巢狀scope中的變數,一般是:
import tensorflow as tf
# with tf.variable_scope("scopeA") as spA:
# var1 = tf.get_variable("v1", [1])
with tf.variable_scope("scopeB"):
with tf.variable_scope("scopeA"):
var3 = tf.get_variable( "v3", [1])
print(var3.name)
scopeB/scopeA/v3:0
使不受外層影響
如果在其前便定義了內層scope,並將其傳入tf.variable_scope
中,即:
import tensorflow as tf
with tf.variable_scope("scopeA") as spA:
var1 = tf.get_variable("v1", [1])
with tf.variable_scope("scopeB"):
with tf.variable_scope(spA):
var3 = tf.get_variable( "v3", [1])
print(var3.name)
scopeA/v3:0
此時不受外層variable_scope的影響。
name_scope
運算結點既受到name_scope限制,也受到variable_scope限制,而Variable僅受到variable_scope限制。
注意,變數和運算結點雖然都是Tensor,但它們分別是:
<class 'tensorflow.python.ops.variables.Variable'> <class 'tensorflow.python.framework.ops.Tensor'>
輸出其type就能檢視到,所以它們才會對不同的scope有不同的表現。
一般使用
with tf.variable_scope("v"):
with tf.name_scope("n1"):
a = tf.get_variable("a", [1]) # Variable
x = 1.0 + a # Op
with tf.name_scope("n2"):
y = 1.0 + a # Op
print(a.name, x.op.name, y.op.name, sep='\n')
v/a:0
v/n1/add:0
v/n1/n2/add:0
返回頂層
當為name_scope指定空字串時,其行為是使其作用域回到頂層,這個比較特殊。
with tf.variable_scope("v"):
with tf.name_scope("n1"):
a = tf.get_variable("a", [1]) # Variable
x = 1.0 + a # Op
with tf.name_scope(""):
y = 1.0 + a # Op
b = tf.get_variable("b", [1]) # Variable僅受到variable_scope的限制
print(a.name, x.op.name, y.op.name, b.name, sep='\n')
v/a:0
v/n1/add
add
v/b:0
因為b是一個Variable,僅受到variable_scope的限制,所以這個“回到頂層”對它不奏效。
圖的基本操作
圖即是一個計算任務,每個T程式預設就帶一個計算圖。
建立圖
import tensorflow as tf
# 在TF預設的圖上建立的常量Tensor
c = tf.constant(0.0)
print(c.graph)
<tensorflow.python.framework.ops.Graph object at 0x00000000032B99B0>
# 建立圖g,並在它上面建立個常量Tensor
g = tf.Graph()
with g.as_default():
c1 = tf.constant(0.0)
print(c1.graph) # 可以通過變數的graph屬性獲取所在的圖
print(g)
<tensorflow.python.framework.ops.Graph object at 0x000000000A611588>
<tensorflow.python.framework.ops.Graph object at 0x000000000A611588>
# 獲取預設圖,看看預設圖是哪個
g2 = tf.get_default_graph()
print(g2)
<tensorflow.python.framework.ops.Graph object at 0x00000000032B99B0>
# 重置預設圖,相當於重新建立了一個圖
tf.reset_default_graph() # 使用該函式時必須保證當前圖的資源已經全部釋放
g3 = tf.get_default_graph()
print(g3)
<tensorflow.python.framework.ops.Graph object at 0x000000000A611550>
獲取圖中的Tensor
這裡是獲取其中的常量Tensor,只要根據它的名稱就可以將它取出。
import tensorflow as tf
g = tf.Graph()
with g.as_default():
c = tf.constant(0.0)
print(c.name)
# 通過名稱得到對應元素:通過Tensor的名稱得到圖中的c
t = g.get_tensor_by_name(name="Const:0")
print(c is t)
Const:0
True
不過我暫時還是不理解這樣做有什麼意義,可能是在某些情形下能訪問到圖卻無法直接得到裡面的變數吧。
獲取圖中的op
注意op是op包下的Tensor的屬性,而不是Tensor本身!
import tensorflow as tf
# 兩個常量Tensor
a = tf.constant([[1.0, 2.0]])
b = tf.constant([[1.0], [3.0]])
# 定義它們做矩陣乘法的操作
mymul = tf.matmul(a, b, name='mymul')
print(mymul.op.name) # 注意這裡是.op.name
# 因為這個op在預設圖裡,先獲取到預設圖
dft_g = tf.get_default_graph()
# 再從預設圖裡取出來
mymul_op = dft_g.get_operation_by_name(name="mymul") # 注意這裡沒有':0'
mymul_tensor = dft_g.get_tensor_by_name(name="mymul:0")
print(mymul is mymul_op)
print(mymul_op is mymul_tensor)
print(mymul is mymul_tensor)
mymul
False
False
True
從這個例子中可以看到,前面定義的mymul看似是一個操作,其實它是一個Tensor而不是op,必須要訪問其op屬性得到的才是op,而get_operation_by_name
得到的就是op,get_tensor_by_name
得到的卻是Tensor,這不一樣,很容易弄混。
獲取元素列表
import tensorflow as tf
g = tf.Graph()
with g.as_default():
c = tf.constant(0.0)
d = tf.constant(1.1)
ops = g.get_operations()
print(ops)
[<tf.Operation 'Const' type=Const>, <tf.Operation 'Const_1' type=Const>]
得到的是圖g中的所有元素。
通過物件獲取元素
前面是通過名字獲取元素,這裡是通過傳入物件本身來獲取元素,這就更搞不懂為什麼了。。不過書上說這個函式有驗證和轉換的功能,在多執行緒中有時會用到。
g = tf.Graph()
with g.as_default():
c1 = tf.constant(0.0)
c1_cpoy = g.as_graph_element(c1)
print(c1 is c1_cpoy)
True