1. 程式人生 > >徹底弄懂tf.Variable、tf.get_variable、tf.variable_scope以及tf.name_scope異同

徹底弄懂tf.Variable、tf.get_variable、tf.variable_scope以及tf.name_scope異同

我之前有轉載過一篇講tf.variable_scope和tf.name_scope的文章,今天一看,覺得還是沒介紹太清楚,沒講到點子上,畢竟英文什麼的看起來還是挺麻煩的。故而,今天來細細梳理下tf.Variable、tf.get_variable、tf.variable_scope以及tf.name_scope四者之間的區別與聯絡。

1. tf.Variable與tf.get_variable

tensorflow提供了通過變數名稱來建立或者獲取一個變數的機制。通過這個機制,在不同的函式中可以直接通過變數的名字來使用變數,而不需要將變數通過引數的形式到處傳遞。
TensorFlow中通過變數名獲取變數的機制主要是通過tf.get_variable和tf.variable_scope實現的。
當然,變數也可以通過tf.Varivale來建立。當tf.get_variable用於變數建立時,和tf.Variable的功能基本等價

#以下兩個定義是等價的
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_varialbe和tf.Variable最大的區別在於:tf.Variable的變數名是一個可選項,通過name=’v’的形式給出。但是tf.get_variable必須指定變數名

2. tf.get_variable與tf.variable_scope

上面已經提到過了:TensorFlow中通過變數名獲取變數的機制主要是通過tf.get_variable和tf.variable_scope實現的。在這裡,我主要解釋下大家深惡痛絕的reuse問題


其實只要記住一件事情就ok了:當reuse為False或者None時(這也是預設值),同一個tf.variable_scope下面的變數名不能相同;當reuse為True時,tf.variable_scope只能獲取已經建立過的變數。
下面我們通過程式碼來看下:

#reuse=False時會報錯的情況:
with tf.variable_scope('foo'):
    v = tf.get_variable('v',[1],initializer=tf.constant_initializer(1.0))

with tf.variable_scope('foo'):
    v1 = tf.get_variable('v'
,[1])

在這種情況下會報錯:Variable foo/v already exists, disallowed.Did you mean to set reuse=True in Varscope?
其原因就是在名稱空間foo中建立了相同的變數。如果我要在foo下建立一個變數v1,其name=‘v’,只需要將reuse設定為Ture就ok了。將上面第二部分程式碼修改為:

with tf.variable_scope('foo', reuse=True):
    v1 = tf.get_variable('v',[1])
    print(v1.name)      #結果為foo/v

當reuse已經設定為True時,tf.variable_scope只能獲取已經建立過的變數。這個時候,在名稱空間bar中建立name=‘v’的變數v3,將會報錯:Variable bar/v dose not exists, diallowed. Did you mean to set reuse=None in VarScope?

with tf.variable_scope('bar', reuse=True):
    v3 = tf.get_variable('v',[1])

簡而言之,reuse=False時,tf.variable_scope建立變數;reuse=True時,tf.variable_scope獲取變數

3. tf.variable_scope與tf.name_scope

除了tf.variable_scope,tf.name_scope函式也提供了名稱空間管理的功能。這兩個函式在大部分情況下是等價的,唯一的區別是在使用tf.get_variable函式時。
tf.get_variable函式不受tf.name_scope的影響
我們從程式碼看下這句話的具體意思。
首先是tf.variable_scope:

with tf.variable_scope('foo'):
    a = tf.get_variable('bar',[1])
    print(a.name)#結果為foo/bar:0

再看tf.name_scope:

with tf.name_scope('a'):
    a=tf.Variable([1])
    print(a.name)#結果為a/Variable:0

    b=tf.get_variable('b',[1])
    print(b.name)#結果為b:0

從這個結果中,我們能很清晰地看到,tf.get_variable建立的變數並不是a/b:0,而是b:0。這就表示了在tf.name_scope函式下,tf.get_variable不受其約束