Tensorflow-Variables-變量-LowlevelApi-翻譯整理

Variables變量用于共享、持久化狀態管理。

tf.Variable表示此數值在計算過程中可能會變化,它獨立于sess.run上下文存在。因此我們可以在sessionA中利用ops操作改變這個變量,進而在sessionB中使用這個變量,以此達到傳遞共享數值的目的。


創建變量

使用tf.get_variable(name,shape,dtype,initializer)創建變量。

如果設定了初initializer初始化函數返回明確的值,那么不能同時使用shape參數,否則必須指定shape。

import tensorflow as tf
sess=tf.Session()

v1 = tf.get_variable("v1", [1, 2, 3]) #隨機0~1之間
v2 = tf.get_variable("v2", [1, 2, 3],initializer=tf.zeros_initializer) #全0
v3 = tf.get_variable("v3", dtype=tf.int32,initializer=tf.constant([23, 42])) #不能同時設定shape!

init=tf.global_variables_initializer()
sess.run(init)

print(sess.run(v1))
print(sess.run(v2))
print(sess.run(v3))

打印結果

[[[-0.8628024   0.6660923   0.8403772 ]
  [-0.5985474  -0.073349    0.23826087]]]
[[[0. 0. 0.]
  [0. 0. 0.]]]
[23 42]
變量集合Variable collections

將一組變量放入集合進行管理

import tensorflow as tf
sess=tf.Session()

v1 = tf.get_variable("v1", [1, 2, 3])
tf.add_to_collection("mycollection", v1) #將v1放入名稱為mycollection的集合

mycollection=tf.get_collection("mycollection")
print(mycollection) #一個列表

init=tf.global_variables_initializer()
sess.run(init)

print(sess.run(mycollection[0])) #獲取v1

打印結果

[<tf.Variable 'v1:0' shape=(1, 2, 3) dtype=float32_ref>]
[[[-0.28881794  0.46018004 -0.83893764]
  [-0.93932706  0.84757173  0.78609943]]]

默認情況tf.Variable都會被放入兩個默認的集:

  • tf.GraphKeys.GLOBAL_VARIABLES可用于多設備共享變量
  • tf.GraphKeys.TRAINABLE_VARIABLES會被計算梯度下降

也可以在創建變量的時候立即放入集合,語法:

my_local = tf.get_variable(name="my_local",
                                   shape=(),
                                   collections=[tf.GraphKeys.LOCAL_VARIABLES])

或者直接設定變量可被訓練:

my_non_trainable = tf.get_variable("my_non_trainable",
                                   shape=(),
                                   trainable=False)
Device placement設備放置

可以把變量限定在特定設備,例如下面代碼把v變量放置在GPU1下面:

with tf.device("/device:GPU:1"):
  v = tf.get_variable("v", [1])

分布式計算中變量的設備非常重要,放置不當可能導致運算緩慢甚至出錯。tf.train.replica_device_setter方法可以自動化處理。

cluster_spec = {
    "ps": ["ps0:2222", "ps1:2222"],
    "worker": ["worker0:2222", "worker1:2222", "worker2:2222"]}
with tf.device(tf.train.replica_device_setter(cluster=cluster_spec)):
  v = tf.get_variable("v", shape=[20, 20])  

初始化變量

變量在使用前必須被初始化。使用low level api的時候必須手工明確初始化,hight level api中的tf.contrib.slim, tf.estimator.Estimator and Keras會自動在訓練前完成初始化。

  • 一次性初始化所有變量tf.global_variables_initializer()
  • 初始化單個變量session.run(my_variable.initializer)
  • 查看哪些變量沒被初始化session.run(tf.report_uninitialized_variables())

注意,tf.global_variables_initializer()初始化時候并沒有固定順序,如果某個變量依賴于其他變量的求值,那將遇到錯誤。當所有變量沒被初始化完成的時候,用variable.initialized_value()來獲取計算值,而不要直接使用變量。

v = tf.get_variable("v", shape=(), initializer=tf.zeros_initializer())
w = tf.get_variable("w", initializer=v.initialized_value() + 1)

使用變量

在計算圖中,變量可以當作tf.tensor張量對象使用。例如

v = tf.get_variable("v", shape=(), initializer=tf.zeros_initializer())
w = v + 1

設定變量的值,可以直接使用變量自帶的方法assign, assign_add,assign_sub等。

import tensorflow as tf
sess=tf.Session()

v = tf.get_variable("v", shape=(), initializer=tf.zeros_initializer())
assignment = v.assign_add(1)

init=tf.global_variables_initializer()
sess.run(init)

print(sess.run(assignment)) #或者assignment.op.run(), 或assignment.eval()

輸出

1.0

由于類似梯度下降算法這樣的優化器會在運算時候不斷修改變量,所以變量是不穩定的。我們可以用tf.Variable.read_value方法讀取變化之后的值。

import tensorflow as tf
sess=tf.Session()

v = tf.get_variable("v", shape=(), initializer=tf.zeros_initializer())
assignment = v.assign_add(1)


init=tf.global_variables_initializer()
sess.run(init)

print(sess.run(v.read_value()))
with tf.control_dependencies([assignment]):
    w = v.read_value()    
    print(sess.run(w))

打印結果

0.0
1.0

共享變量Sharing variables

Tensorflow有兩種方法共享變量:

  • 顯式的傳遞tf.Variable對象
  • 隱式的使用tf.variable_scope包裹tf.variable對象

比如下面的示意代碼中,我們創建了一個卷積層(線性整流單元):

def conv_relu(input, kernel_shape, bias_shape):
    # 創建變量 "weights".
    weights = tf.get_variable("weights", kernel_shape,
        initializer=tf.random_normal_initializer())
    # 創建變量"biases".
    biases = tf.get_variable("biases", bias_shape,
        initializer=tf.constant_initializer(0.0))
    conv = tf.nn.conv2d(input, weights,
        strides=[1, 1, 1, 1], padding='SAME')
    return tf.nn.relu(conv + biases)

上面的代碼定義了conv_relu方法,其中有兩個變量weight和biases??瓷先ズ芮宄?,當我們使用它的時候就遇到了問題:

input1 = tf.random_normal([1,10,10,32])
input2 = tf.random_normal([1,20,20,32])
x = conv_relu(input1, kernel_shape=[5, 5, 32, 32], bias_shape=[32])
x = conv_relu(x, kernel_shape=[5, 5, 32, 32], bias_shape = [32])  # 失?。?

我們試圖鏈接兩個卷積層,但計算機在計算的時候無法清楚是重新創建weight和biases還是繼續使用已經存在的。
下面的代碼正確的創建兩個卷積層,使用新的變量:

def my_image_filter(input_images):
    with tf.variable_scope("conv1"):
        # 這里創建的變量被重新命名為 "conv1/weights", "conv1/biases".
        relu1 = conv_relu(input_images, [5, 5, 32, 32], [32])
    with tf.variable_scope("conv2"):
        # 這里創建的變量被重新命名為 "conv2/weights", "conv2/biases".
        return conv_relu(relu1, [5, 5, 32, 32], [32])

如果你需要共享變量而不是重新創建,以下兩種語法都可以實現:

with tf.variable_scope("model"):
  output1 = my_image_filter(input1)
with tf.variable_scope("model", reuse=True): #注意這里reuse=True
  output2 = my_image_filter(input2)
with tf.variable_scope("model") as scope:
  output1 = my_image_filter(input1)
  scope.reuse_variables() #注意這里!
  output2 = my_image_filter(input2)

其中上一種方法可以改進為

with tf.variable_scope("model") as scope: # 注意這里的as scope
  output1 = my_image_filter(input1)
with tf.variable_scope(scope, reuse=True): #注意這里傳入的scope
  output2 = my_image_filter(input2)

本篇小結

  • 創建變量tf.get_variable(name,shape,dtype,initializer)
  • 變量集合tf.add_to_collection("mycollection", v1)
  • 置入不同的設備
  • 變量初始化方法tf.global_variables_initializer()session.run(my_variable.initializer)
  • 使用變量
  • 修改變量assign, assign_add,assign_sub
  • 共享變量tf.variable_scope

探索人工智能的新邊界

如果您發現文章錯誤,請不吝留言指正;
如果您覺得有用,請點喜歡;
如果您覺得很有用,感謝轉發~


END

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容