Tensorflow-Graph-Session-圖與會(huì)話-LowLevelApi-翻譯整理

Tensorflow使用數(shù)據(jù)流圖dataflow graph表示各個(gè)獨(dú)立操作之間的依賴關(guān)系。

Tensorflow低級(jí)編程模式:

  • 定義dataflow graph
  • 創(chuàng)建會(huì)話session
  • 使用session在本地或遠(yuǎn)程設(shè)備運(yùn)行g(shù)raph

什么事Dataflow graphs?

Dataflow是平行計(jì)算的通用模式。其中節(jié)點(diǎn)node表示計(jì)算單元,邊線edge表示計(jì)算產(chǎn)生和消耗的數(shù)據(jù)。例如上圖地步的MatMul計(jì)算節(jié)點(diǎn),有兩條數(shù)據(jù)輸入邊線和一條向上的輸出邊線,對(duì)應(yīng)tf.matmul(a,b)方法輸出矩陣a和b相乘的結(jié)果。

Dataflow graph的優(yōu)勢:

  • 平行結(jié)構(gòu)Parallelism。
  • 分布式計(jì)算Distributed execution。Tensorflow可以協(xié)調(diào)多設(shè)備多機(jī)器運(yùn)算。
  • 可編譯Compilation。XLA compiler可以利用數(shù)據(jù)流的關(guān)系產(chǎn)生高效率代碼,融合相鄰運(yùn)算。
  • 可移植Portability。不依賴編程語言存在,可以多語言結(jié)合。

什么是tf.graph?

它包含了兩類相關(guān)信息:

  • 圖結(jié)構(gòu)Graph structure。節(jié)點(diǎn)和邊線表示了各個(gè)操作之間的關(guān)系,但并不限定如何被使用。圖結(jié)構(gòu)類似組裝代碼:從它可以看到很多關(guān)系信息,但并不是實(shí)際代碼。

  • 圖集合Graph collections。Tensorflow提供了一種生成機(jī)制,用來存儲(chǔ)圖中的元數(shù)據(jù)matadata。tf.add_to_collection可以將一個(gè)列表對(duì)象組裝到一個(gè)鍵key(由tf.GraphKeys定義)。例如,當(dāng)我們使用tf.variable創(chuàng)建一個(gè)變量的時(shí)候,它被添加到表示全局變量global variables和可訓(xùn)練變量trainabled
    varibale兩個(gè)集合,當(dāng)稍后再創(chuàng)建其他tf.train.Saver、tf.train.Optimizer的時(shí)候,集合中的這些變量將作為默認(rèn)參數(shù)使用。


創(chuàng)建一個(gè)tf.graph

大多數(shù)Tensorflow程序開始于圖的創(chuàng)建。我們使用tf.oparation創(chuàng)建操作節(jié)點(diǎn),使用tf.Tensor創(chuàng)建張量邊線,然后把它們添加到tf.graph

Tensorflow提供了一個(gè)默認(rèn)圖,作為一個(gè)顯式的參數(shù),作用于同一個(gè)上下文環(huán)境的接口函數(shù)。例如:

  • tf.constant(42.0),這將創(chuàng)建一個(gè)產(chǎn)生42.0的操作tf.operation,并添加到默認(rèn)圖,并返回一個(gè)表示常數(shù)的張量tf.tensor

*tf.matmul(x,y),就是把xy兩個(gè)張量相乘的操作,自動(dòng)添加到默認(rèn)圖,返回相乘的結(jié)果(也是個(gè)張量)。

*v=tf.Variable(0),向默認(rèn)圖添加了一個(gè)操作,這個(gè)操作能夠存儲(chǔ)一個(gè)在會(huì)話多次運(yùn)行之間session.run可讀寫的張量值。tf.Variable對(duì)象包裹著這個(gè)操作,使它可以像普通張量一樣被讀寫使用。tf.Variable對(duì)象自身也附帶了一些方法比如assign,assign_add,這些方法也能生成新的操作,通過這些操作在運(yùn)算時(shí)候改變存儲(chǔ)的張量。

  • tf.train.Optimizer.minimize,將添加操作和張量到默認(rèn)圖,它們用來計(jì)算梯度gradient并返回一個(gè)操作,當(dāng)被運(yùn)行的時(shí)候,這個(gè)操作將把梯度變化應(yīng)用到變量集合上。

絕大多數(shù)程序只要解算默認(rèn)圖就可以了。類似tf.estimator.Estimator接口管理著默認(rèn)圖,當(dāng)然也會(huì)為訓(xùn)練和評(píng)價(jià)創(chuàng)建不同的圖。

Tensorflow大部分API接口都只是創(chuàng)建operation和tensor,并不真正執(zhí)行運(yùn)算。你編織整個(gè)圖譜網(wǎng)絡(luò),直到找到那個(gè)最終結(jié)果或可以得到期望最后結(jié)果的操作,然后把它傳遞到session會(huì)話進(jìn)行求解。


為操作命名

Graph為所有包含的操作定義了一個(gè)命名空間。在圖中,Tensorflow為每一個(gè)操作自動(dòng)設(shè)定了唯一的名稱,這個(gè)名稱與編程中的命名無關(guān)。有兩個(gè)方法覆蓋這個(gè)自動(dòng)的命名:

  • 每個(gè)創(chuàng)建新操作或者返回新張量的的函數(shù)都接受name參數(shù)。例如tf.constant(42.0, name="answer")就會(huì)創(chuàng)建一個(gè)名叫answer的操作,并返回一個(gè)名叫answer:0的張量,如果默認(rèn)圖已經(jīng)存在同名操作,那么新操作就會(huì)被自動(dòng)添加_1,_2這樣的結(jié)尾。

  • tf.name_scope方法可以針對(duì)一個(gè)上下文環(huán)境添為特定范圍內(nèi)的操作都添加名稱前綴。/斜杠用來劃分name_scope的層級(jí),如果已有同名,則自動(dòng)添加_1,_2。

c_0 = tf.constant(0, name="c")  # 得到名稱為c的操作
c_1 = tf.constant(2, name="c")  # 重名!得到名稱為c_1的操作

#外層的命名空間.
with tf.name_scope("outer"):
  c_2 = tf.constant(2, name="c")  #outer/c
  with tf.name_scope("inner"): #嵌套的命名空間
    c_3 = tf.constant(3, name="c")  #outer/inner/c
  c_4 = tf.constant(4, name="c")  #重名!變?yōu)閛uter/c_1
  with tf.name_scope("inner"):
    c_5 = tf.constant(5, name="c")  #重名!變?yōu)閛uter/inner_1/c

tf.Tensor對(duì)象命名規(guī)則是在產(chǎn)生它的操作名稱后面加冒號(hào)加數(shù)字,例如上面提到的answer操作產(chǎn)生的張量命名是answer:0。


將操作放置到不同設(shè)備

tf.device()方法可以把同一個(gè)上下文中產(chǎn)生的各種操作分不到不同的設(shè)備中使用。
設(shè)備參數(shù)格式:
/job:<JOB_NAME>/task:<TASK_INDEX>/device:<DEVICE_TYPE>:<DEVICE_INDEX>

  • JOB_NAME,非數(shù)字開頭字母數(shù)字組成的字符串
  • DEVICE_TYPE,設(shè)備類型,GPU或CPU
  • TASK_INDEX,工作中的任務(wù)序號(hào)
  • DEVICE_TYPE,設(shè)備序號(hào)
# 這里創(chuàng)建的操作自動(dòng)選擇,優(yōu)先GPU
weights = tf.random_normal(...)

with tf.device("/device:CPU:0"):
  #這里創(chuàng)建的操作將使用CPU
  img = tf.decode_jpeg(tf.read_file("img.jpg"))
with tf.device("/device:GPU:0"):
  #這里創(chuàng)建的操作將使用GPU.
  result = tf.matmul(weights, img)

paramaters server(ps)參數(shù)服務(wù)器格式/job:ps,worker工作機(jī)格式/job:worker

with tf.device("/job:ps/task:0"):
  weights_1 = tf.Variable(tf.truncated_normal([784, 100]))
  biases_1 = tf.Variable(tf.zeroes([100]))

with tf.device("/job:ps/task:1"):
  weights_2 = tf.Variable(tf.truncated_normal([100, 10]))
  biases_2 = tf.Variable(tf.zeroes([10]))

with tf.device("/job:worker"):
  layer_1 = tf.matmul(train_batch, weights_1) + biases_1
  layer_2 = tf.matmul(train_batch, weights_2) + biases_2

使用tf.train.replica_device_setter自動(dòng)分配:

with tf.device(tf.train.replica_device_setter(ps_tasks=3)):
  # tf.Variable objects對(duì)象會(huì)被自動(dòng)循環(huán)分配任務(wù)
  w_0 = tf.Variable(...)  # placed on "/job:ps/task:0"
  b_0 = tf.Variable(...)  # placed on "/job:ps/task:1"
  w_1 = tf.Variable(...)  # placed on "/job:ps/task:2"
  b_1 = tf.Variable(...)  # placed on "/job:ps/task:0"

  input_data = tf.placeholder(tf.float32)     # placed on "/job:worker"
  layer_0 = tf.matmul(input_data, w_0) + b_0  # placed on "/job:worker"
  layer_1 = tf.matmul(layer_0, w_1) + b_1     # placed on "/job:worker"

類似張量對(duì)象Tensor-like objects

類似張量對(duì)象可以被隱式的轉(zhuǎn)化為張量,它分為下面幾種:

  • tf.Tensor
  • tf.variable
  • numpy.ndarray
  • list(和由類似張量物體構(gòu)成的list)
  • Python標(biāo)量值:bool,string,int,float

注意,在使用類似張量對(duì)象的時(shí)候,tensorflow每次都創(chuàng)建新的tf.tensor對(duì)象,如果這個(gè)對(duì)象很大,那么多次創(chuàng)建會(huì)消耗大量內(nèi)存。


使用tf.Session對(duì)圖進(jìn)行計(jì)算

Tensorflow使用會(huì)話tf.Session來建立客戶端程序(Python或其他語言編寫的程序)與C++運(yùn)行時(shí)之間的關(guān)系。tf.Session提供了訪問本機(jī)和分布式機(jī)器的能力,并能緩存圖graph的信息以便于多次運(yùn)行。

創(chuàng)建會(huì)話
# 創(chuàng)建默認(rèn)的進(jìn)程內(nèi)in-process會(huì)話.
with tf.Session() as sess:
  # ...

# 創(chuàng)建遠(yuǎn)程會(huì)話
with tf.Session("grpc://example.org:2222"):
  # ...

由于session擁有物理資源(如GPU和網(wǎng)絡(luò)鏈接),所以它只管理自己的代碼塊的內(nèi)容,退出代碼塊就會(huì)關(guān)閉。如果沒有使用代碼塊,那么必須顯式的關(guān)閉它tf.Session.close()

Hight-level Api比如tf.estimator.Estimator將會(huì)自動(dòng)管理session,可以通過target或config參數(shù)對(duì)session進(jìn)行設(shè)置。

tf.Session.init包含三個(gè)參數(shù):

  • 目標(biāo)target。如果為空,會(huì)話只使用本機(jī)。可以使用grpc://URL指定Tensorflow服務(wù)器,會(huì)話將可以使用該服務(wù)器控制的全部機(jī)器的全部設(shè)備。
  • 圖graph。默認(rèn)一個(gè)新的會(huì)話將綁定到默認(rèn)圖,如果你的程序使用了多個(gè)圖,那么可以用它顯式的指定。
  • 設(shè)置config。設(shè)定一個(gè)tf.ConfigProto控制會(huì)話動(dòng)作。它包含了一些設(shè)置比如:
  • allow_soft_placement,使用軟件設(shè)備soft device,這將忽略GPU,只用CPU。
  • cluster_def,當(dāng)使用分布式的TensorFlow的時(shí)候,這個(gè)參數(shù)可以設(shè)定具體使用哪些機(jī)器進(jìn)行計(jì)算。
  • graph_options.optimizer_options,在圖運(yùn)算之前,控制優(yōu)化器。
  • gpu_options.allow_growth,設(shè)置gpu內(nèi)存分配器可以梯度增加內(nèi)存而不是初始占用很多。
使用tf.Session.run執(zhí)行操作

run方法是對(duì)圖進(jìn)行運(yùn)算的最主要的方法,接受一個(gè)或多個(gè)提取器fetches列表。提取器可以是:

  • 一個(gè)操作operation
  • 一個(gè)張量tensor
  • 一個(gè)類似張量如tf.Variable

這些提取器限定了一個(gè)可被運(yùn)行的子圖subgraph,連接到全圖的所有相關(guān)操作。

import tensorflow as tf

x = tf.constant([[37.0, -23.0], [1.0, 4.0]])
w = tf.Variable(tf.random_uniform([2, 2]))
y = tf.matmul(x, w)
output = tf.nn.softmax(y)
init_op = w.initializer

with tf.Session() as sess:
    sess.run(init_op)
    print(sess.run(output))
    y_val, output_val = sess.run([y, output])
    print(y_val)
    print(output_val)

Session.run接收feed_dic參數(shù),一般是placeholder表示的值(scalar、list、numpy array),這些值在被計(jì)算的時(shí)候替換placeholder表示的張量,如下

import tensorflow as tf

x = tf.placeholder(tf.float32, shape=[3])
y = tf.square(x) #這里使用了替代品張量

with tf.Session() as sess:
  print(sess.run(y, {x: [1.0, 2.0, 3.0]}))  # => "[1.0, 4.0, 9.0]"
  print(sess.run(y, feed_dict={x: [0.0, 0.0, 5.0]}))  # => "[0.0, 0.0, 25.0]"

  sess.run(y) #出錯(cuò)!placeholder必須帶有feed_dict
  sess.run(y, {x: 37.0}) #出錯(cuò),數(shù)值形狀與placeholder不匹配

Session.run接收一個(gè)RunOptions參數(shù),可以用來收集運(yùn)算過程中的信息。這些信息可以用來構(gòu)建類似Tensorboard的信息圖譜。

import tensorflow as tf

y = tf.matmul([[37.0, -23.0], [1.0, 4.0]], tf.random_uniform([2, 2]))

with tf.Session() as sess:
  #定義選項(xiàng)
  options = tf.RunOptions()
  options.output_partition_graphs = True
  options.trace_level = tf.RunOptions.FULL_TRACE

  #定義元數(shù)據(jù)容器
  metadata = tf.RunMetadata()

  sess.run(y, options=options, run_metadata=metadata)

  # 打印每個(gè)設(shè)備上執(zhí)行的子圖結(jié)構(gòu).
  print(metadata.partition_graphs)

  # 打印每個(gè)操作執(zhí)行時(shí)候的時(shí)間.
  print(metadata.step_stats)

視覺化計(jì)算圖

Tensorborad的Graph visualizer元件可以將計(jì)算圖的結(jié)構(gòu)渲染到瀏覽器內(nèi),只要在創(chuàng)建圖的時(shí)候把tf.graph對(duì)象傳遞給tf.summary.FileWriter:

import tensorflow as tf
import os

x = tf.placeholder(tf.float32, shape=[3])
y = tf.square(x)

dir_path = os.path.dirname(os.path.realpath(__file__))
sum_path=os.path.join(dir_path,'temp') #不要使用斜杠

with tf.Session() as sess:
  writer = tf.summary.FileWriter(sum_path, sess.graph)
  print(sess.run(y, {x: [1.0, 2.0, 3.0]}))  # => "[1.0, 4.0, 9.0]"
  writer.close()

然后命令行運(yùn)行tensorboard --logdir=~/desktop/Myprojects/xxx/xxx/,再打開任意瀏覽器訪問http://localhost:6006,點(diǎn)擊GRAPHS按鈕即可看到類似下圖:


使用多個(gè)計(jì)算圖編程

當(dāng)訓(xùn)練模型的時(shí)候,通常使用不同的圖進(jìn)行訓(xùn)練、評(píng)價(jià)和預(yù)測。你可以使用不同的Python進(jìn)程來創(chuàng)建和運(yùn)行不同的圖,也可以在統(tǒng)一進(jìn)程內(nèi)處理。

TensorFlow提供了默認(rèn)的graph圖:

  • tf.graph定義了其下所有操作的命名空間,單個(gè)圖內(nèi)的每個(gè)操作必須具有唯一命名,重名會(huì)自動(dòng)添加'_1','_2'后綴。
  • 默認(rèn)圖自動(dòng)存儲(chǔ)每個(gè)添加進(jìn)來的fetches提取器信息(operation、tensor等),如果你的圖包含了大數(shù)量節(jié)點(diǎn)的未連接子圖,最好的辦法是將它們分成不同的圖,以便于更有效的資源回收。

也可以使用自定義的tf.graph來替代默認(rèn)圖,使用tf.graph.as_default語法,以下實(shí)例代碼創(chuàng)建了兩個(gè)session分別運(yùn)行兩個(gè)不同的圖:

import tensorflow as tf

g_1 = tf.Graph()
with g_1.as_default():#以下操作將被添加到`g_1`.
    c = tf.constant("Node in g_1")

    # 這里創(chuàng)建的回話將運(yùn)行`g_1`.
    sess_1 = tf.Session()
    print(sess_1.run(c))

g_2 = tf.Graph()
with g_2.as_default():#以下操作將被添加到`g_2`.
    d = tf.constant("Node in g_2")

    #也可以直接為session指定graph
    sess_2 = tf.Session(graph=g_2)
    print(sess_2.run(d))

以上代碼輸出

b'Node in g_1'
b'Node in g_2'

使用tf.get_default_graph獲取計(jì)算圖

import tensorflow as tf

x = tf.placeholder(tf.float32, shape=[3])
y = tf.square(x) 

g = tf.get_default_graph()
print(g.get_operations())

本篇小結(jié)

  • Dataflow graph數(shù)據(jù)流圖表,由節(jié)點(diǎn)node和邊線edge組成。
  • tf.graph包含了節(jié)點(diǎn)直接的操作關(guān)系
  • 創(chuàng)建的各種節(jié)點(diǎn)和張量都會(huì)被自動(dòng)添加到默認(rèn)圖
  • name參數(shù)讓每個(gè)操作都有唯一的識(shí)別名,產(chǎn)生的每個(gè)張量也都有唯一識(shí)別名
  • 在不同設(shè)備和不同機(jī)器上分布操作
  • Tensor-like objects類似張量對(duì)象
  • tf.Session會(huì)話對(duì)圖進(jìn)行計(jì)算
    • session的創(chuàng)建和初始化
    • tf.Session.run方法運(yùn)行整圖或子圖
  • 利用Tensorboard視覺化計(jì)算圖
  • 使用多個(gè)計(jì)算圖

探索人工智能的新邊界

如果您發(fā)現(xiàn)文章錯(cuò)誤,請不吝留言指正;
如果您覺得有用,請點(diǎn)喜歡;
如果您覺得很有用,感謝轉(zhuǎn)發(fā)~


END

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

推薦閱讀更多精彩內(nèi)容