TensorFlow 框架和核心概念
https://www.cnblogs.com/miracle-Z/p/8988701.html
TensorFlow核心概念及基本使用
TensorFlow核心概念
綜述:TensorFlow中的計算可以表示為一個有向圖膳殷,或稱計算圖疟丙,其中每一個運算操作將作為一個節(jié)點,節(jié)點間的鏈接叫做邊鹏倘。這個計算圖描述了數(shù)據(jù)的計算流程激涤,它也負責(zé)維護和更新狀態(tài)包各,用戶可以對計算圖的分支進行條件控制和循環(huán)操作曾雕。計算圖中的每一個節(jié)點可以有任意多個輸入和輸出见芹,每一個節(jié)點描述了一種運算操作钉嘹,節(jié)點可以算是運算操作的實例化鸯乃。在計算圖的邊中流動的的數(shù)據(jù)被稱為張量。
1.計算圖
TensorFlow是一個通過計算圖的形式來表述計算的編程系統(tǒng)隧期。每一個計算都是計算圖的一個節(jié)點飒责,而節(jié)點間的邊描述了計算之間的依賴關(guān)系赘娄。
a.不同的圖上的張量與運算不會共享(每個圖中的數(shù)據(jù)類似于一個代碼塊中的局部變量),因此可以用計算圖來隔離張量和計算,它還提供了管理張量和計算的機制(指定運算進行的設(shè)備)宏蛉。
b.計算圖還有個重要的功能是有效地整理TensorFlow程序中的資源遣臼。在一個計算圖中可以通過集合(collection)來管理不同類別的資源。
2.TensorFlow的數(shù)據(jù)模型-張量(Tensor)
TensorFlow用張量這種數(shù)據(jù)結(jié)構(gòu)來表示所有的數(shù)據(jù).你可以把一個張量想象成一個n維的數(shù)組或列表.一個張量有一個靜態(tài)類型和動態(tài)類型的維數(shù).張量可以在圖中的節(jié)點之間流通.
a.TensorFlow計算的結(jié)果不是一個具體的數(shù)字拾并,而是一個張量結(jié)構(gòu)揍堰。一個張量主要保存了三個屬性:名字(name)、維度(shape)和類型(type)嗅义。
eg:print (result)
輸出:
Tensor("add:0", shape=(2,), dtype=float32)
b.張量有兩大用途:
對中間計算結(jié)果的引用屏歹。當(dāng)一個計算包含很多中間結(jié)果時,使用張量可大大提高代碼的可讀性之碗。
用來獲得計算結(jié)果蝙眶。雖張量本身沒有儲存具體的數(shù)字,但可通過tf.Session().run(...)語句得到計算結(jié)果褪那。
3.TensorFlow的運行模型-會話(Session)
會話(Session)用來執(zhí)行定義好的運算幽纷。會話擁有并管理TensorFlow程序運行時的所有資源。當(dāng)所有計算完成后需關(guān)閉會話來幫助系統(tǒng)回收資源博敬。使用會話的方式一般有兩種:
(1)sess = tf.Session()
sess .run(...)
sess.close()
//因異常退出可能會未執(zhí)行關(guān)閉會話的語句
(2)with tf.Session() as sess:
sess.run(...)
//執(zhí)行完自動關(guān)閉會話
(3)在交互式環(huán)境中友浸,通過設(shè)置默認會話的方式來獲取張量的取值會更加方便。
sess = tf.TnteractiveSession()
sess.close()
無論使用哪種方法都可以通過ConfigProto Protocol Buffer來配置需要生成的會話偏窝。通過ConfigProto可以配置類似并行的線程數(shù)收恢、GPU分配策略、運算超時時間等參數(shù)祭往。
4.變量
變量是一類特殊的運算操作伦意,它可以將一些需要保留的tensor儲存在內(nèi)存或顯存中,比如神經(jīng)網(wǎng)絡(luò)中的系數(shù)链沼。當(dāng)訓(xùn)練模型時默赂,用變量來存儲和更新參數(shù)沛鸵。通常會將一個統(tǒng)計模型中的參數(shù)表示為一組變量. 例如, 你可以將一個神經(jīng)網(wǎng)絡(luò)的權(quán)重作為某個變量存儲在一個 tensor 中. 在訓(xùn)練過程中, 通過重復(fù)運行訓(xùn)練圖, 更新這個 tensor.
變量的作用就是保存和更新以及使用神經(jīng)網(wǎng)絡(luò)中的參數(shù)括勺。
在神經(jīng)網(wǎng)絡(luò)中,給參數(shù)賦予隨機初始值最為常見曲掰,所以一般也使用隨機數(shù)給TensorFlow中的變量初始化疾捍。下面是兩個例子:
1.#將特征向量定義為一個常量,這里是一個1×2的矩陣
x = tf.constant([[0.7,0.9]])
2.#聲明w1變量栏妖,還通過seed參數(shù)設(shè)定了隨機種子乱豆,這樣可以保證每次運行的結(jié)果是一樣的。
w1 = tf.Variable(tf.random_normal((2,3), stddev=1, seed=1))
雖然在變量的定義時給出了變量初始化的方法吊趾,但這個方法并沒有被真正運行宛裕。所以在計算結(jié)果前瑟啃,需要運行下面語句來初始化變量靶衍,為變量賦值肩钠。
sess.run(w1.initializer)
但當(dāng)變量數(shù)目增多舱权,或者變量之間存在依賴關(guān)系時氓栈,單個調(diào)用變量初始化過程就比較麻煩燕刻。TensorFlow提供了一種更為便捷的方式來完成變量的初始化過程怖喻。
init_op = tf.global_variables_initializer()
sess.run(init_op)
該函數(shù)實現(xiàn)初始化所有變量的過程并自動處理變量之間的依賴關(guān)系业岁。
5.神經(jīng)網(wǎng)絡(luò)優(yōu)化的簡單框架
1.前向傳播算法
提取的特征向量通過連接節(jié)點邊的權(quán)重計算操禀,在對應(yīng)節(jié)點求得加權(quán)和作為中間的張量勇边,然后依次向后一層按相同的方式傳播犹撒,最終得到的輸出節(jié)點上的加權(quán)和為輸出結(jié)果。前向傳播算法可得到當(dāng)前的預(yù)測值粒褒。
2.損失函數(shù)
損失函數(shù)用于刻畫當(dāng)前預(yù)測值與真實答案之間的差距识颊,評價學(xué)習(xí)的情況好壞的標準,其重要性不言而喻奕坟。具體的介紹在后面文章總結(jié)谊囚。
3.反向傳播算法
反向傳播算法用于更新變量,既各層的權(quán)重执赡,是訓(xùn)練神經(jīng)網(wǎng)絡(luò)的核心算法镰踏,它可以根據(jù)定義好的損失函數(shù)優(yōu)化神經(jīng)網(wǎng)絡(luò)中參數(shù)的取值,從而使神經(jīng)網(wǎng)絡(luò)模型在訓(xùn)練數(shù)據(jù)集上的損失函數(shù)達到一個最小值沙合。反向傳播算法給出了一個高效的方法在所有參數(shù)上使用梯度下降算法奠伪。梯度下降算法總結(jié)在下文。
TensorFlow的基本使用
1.構(gòu)建圖
import tensorflow as tf
# 創(chuàng)建一個常量 op, 產(chǎn)生一個 1x2 矩陣. 這個 op 被作為一個節(jié)點
# 加到默認圖中.
# 構(gòu)造器的返回值代表該常量 op 的返回值.
matrix1 = tf.constant([[3., 3.]])
# 創(chuàng)建另外一個常量 op, 產(chǎn)生一個 2x1 矩陣.
matrix2 = tf.constant([[2.],[2.]])
# 創(chuàng)建一個矩陣乘法 matmul op , 把 'matrix1' 和 'matrix2' 作為輸入.
# 返回值 'product' 代表矩陣乘法的結(jié)果.
product = tf.matmul(matrix1, matrix2)
2.在一個會話中啟動圖
這個使用在上一點會話中有提到的兩種方法首懈。
TensorFlow系統(tǒng)架構(gòu)
https://blog.csdn.net/u013510838/article/details/84103503
TensorFlow設(shè)計十分精巧绊率,基于分層和模塊化的設(shè)計思想進行開發(fā)的【柯模框架如下圖
整個框架以 C API 為界滤否,分為前端和后端兩大部分。
前端:提供編程模型最仑,多語言的接口支持藐俺,比如Python Java C++等。通過C API建立前后端的連接泥彤,后面詳細講解欲芹。
后端:提供運行環(huán)境,完成計算圖的執(zhí)行吟吝。進一步分為4層
運行時:分為分布式運行時和本地運行時菱父,負責(zé)計算圖的接收,構(gòu)造,編排等浙宜。
計算層:提供各op算子的內(nèi)核實現(xiàn)官辽,例如conv2d, relu等
通信層:實現(xiàn)組件間數(shù)據(jù)通信,基于GRPC和RDMA兩種通信方式
設(shè)備層:提供多種異構(gòu)設(shè)備的支持粟瞬,如CPU GPU TPU FPGA等
模型構(gòu)造和執(zhí)行流程
TensorFlow的一大特點是野崇,圖的構(gòu)造和執(zhí)行相分離。用戶添加完算子亩钟,構(gòu)建好整圖后乓梨,才開始進行訓(xùn)練和執(zhí)行,也就是圖的執(zhí)行清酥。大體流程如下
圖構(gòu)建:用戶在client中基于TensorFlow的多語言編程接口扶镀,添加算子,完成計算圖的構(gòu)造焰轻。
圖傳遞:client開啟session臭觉,通過它建立和master之間的連接。執(zhí)行session.run()時辱志,將構(gòu)造好的graph序列化為graphDef后蝠筑,以protobuf的格式傳遞給master。
圖剪枝:master根據(jù)session.run()傳遞的fetches和feeds列表揩懒,反向遍歷全圖full graph什乙,實施剪枝,得到最小依賴子圖
圖分裂:master將最小子圖分裂為多個Graph Partition已球,并注冊到多個worker上臣镣。一個worker對應(yīng)一個Graph Partition。
圖二次分裂:worker根據(jù)當(dāng)前可用硬件資源智亮,如CPU GPU忆某,將Graph Partition按照op算子設(shè)備約束規(guī)范(例如tf.device('/cpu:0'),二次分裂到不同設(shè)備上阔蛉。每個計算設(shè)備對應(yīng)一個Graph Partition弃舒。
圖運行:對于每一個計算設(shè)備,worker依照op在kernel中的實現(xiàn)状原,完成op的運算聋呢。設(shè)備間數(shù)據(jù)通信可以使用send/recv節(jié)點,而worker間通信遭笋,則使用GRPC或RDMA協(xié)議坝冕。
[圖片上傳失敗...(image-7053eb-1576595920334)]
前端多語言實現(xiàn) - swig包裝器
TensorFlow提供了很多種語言的前端接口徒探,使得用戶可以通過多種語言來完成模型的訓(xùn)練和推斷瓦呼。其中Python支持得最好。這也是TensorFlow之所以受歡迎的一大原因。前端多語言是怎么實現(xiàn)的呢央串?這要歸功于swig包裝器磨澡。
swig是個幫助使用C或者C++編寫的軟件能與其它各種高級編程語言進行嵌入聯(lián)接的開發(fā)工具。在TensorFlow使用bazel編譯時质和,swig會生成兩個wrapper文件
pywrap_tensorflow_internal.py:對接上層Python調(diào)用
pywrap_tensorflow_internal.cc:對接底層C API調(diào)用稳摄。
pywrap_tensorflow_internal.py 模塊被導(dǎo)入時,會加載_pywrap_tensorflow_internal.so動態(tài)鏈接庫饲宿,它里面包含了所有運行時接口的符號厦酬。而pywrap_tensorflow_internal.cc中,則注冊了一個函數(shù)符號表瘫想,實現(xiàn)Python接口和C接口的映射仗阅。運行時,就可以通過映射表国夜,找到Python接口在C層的實現(xiàn)了减噪。
4 tensorflow 源碼結(jié)構(gòu)
TensorFlow源碼基本也是按照框架分層來組織文件的。如下
其中core為tf的核心车吹,它的源碼結(jié)構(gòu)如下
5 總結(jié)
TensorFlow框架設(shè)計精巧筹裕,代碼量也很大,我們可以從以下部分逐步學(xué)習(xí)
TensorFlow內(nèi)核架構(gòu)和源碼結(jié)構(gòu)窄驹。先從全局上對框架進行理解朝卒。
前后端連接的橋梁--Session,重點理解session的生命周期乐埠,并通過相關(guān)源碼可以加深理解Python前端如何調(diào)用底層C實現(xiàn)扎运。
TensorFlow核心對象—Graph。圖graph是TensorFlow最核心的對象饮戳,基本都是圍繞著它來進行的豪治。graph的節(jié)點為算子operation,邊為數(shù)據(jù)tensor扯罐。
TensorFlow圖的節(jié)點 -- Operation负拟。operation是圖graph的節(jié)點,承載了計算算子歹河。
TensorFlow圖的邊 -- Tensor掩浙。Tensor是圖graph的邊,承載了計算的數(shù)據(jù)秸歧。
TensorFlow本地運行時厨姚。
TensorFlow分布式運行時。和本地運行時有一些共用的接口键菱,但區(qū)別也很大谬墙。
TensorFlow設(shè)備層。主要了解設(shè)備層的定義規(guī)范,以及實現(xiàn)拭抬。
TensorFlow隊列和并行運算部默。
TensorFlow斷點檢查checkpoint,模型保存Saver造虎,以及可視化tensorboard傅蹂。這三個為TensorFlow主要的工具。
https://www.ituring.com.cn/book/tupubarticle/24643
版本變遷
TensorFlow自2015年11月開源以來算凿,已經(jīng)發(fā)布了30多個版本份蝴。本節(jié)從TensorFlow的發(fā)展歷程入手,考查其關(guān)鍵特性的發(fā)布和對應(yīng)版本的變遷氓轰。圖1-1展示了這一變化過程搞乏。
1.3 基本架構(gòu)
在展開介紹TensorFlow的使用方法和設(shè)計原理之前,我們有必要建立對TensorFlow基本架構(gòu)的直觀認識戒努。本節(jié)從工作形態(tài)和組件結(jié)構(gòu)這兩個角度對TensorFlow進行概要性的說明请敦。讀者可以以此為切入點,逐步理順學(xué)習(xí)TensorFlow的脈絡(luò)储玫。
1.3.1 工作形態(tài)
基礎(chǔ)平臺層軟件的設(shè)計模式多種多樣侍筛,它們對應(yīng)用層開發(fā)者體現(xiàn)出的工作形態(tài)也有所差別。在眾多平臺設(shè)計模式中撒穷,存在兩類基礎(chǔ)而典型的模式匣椰,即圖1-2所示的庫模式和框架模式。在庫模式下端礼,平臺層軟件以靜態(tài)或動態(tài)的開發(fā)庫(如 .a禽笑、.so文件)形式存在,應(yīng)用層開發(fā)者需要編寫程序調(diào)用這些庫提供的函數(shù)蛤奥,實現(xiàn)計算邏輯佳镜。程序的入口(如main()函數(shù))及整體流程控制權(quán)把握在應(yīng)用層開發(fā)者手中。在框架模式下凡桥,平臺層軟件以可執(zhí)行文件的形式存在蟀伸,并以前端交互式程序或后端守護進程方式獨立運行。應(yīng)用層開發(fā)者需要遵從平臺規(guī)定的接口約束缅刽,開發(fā)包含計算邏輯在內(nèi)的子程序啊掏,交由框架性質(zhì)的平臺層軟件調(diào)度執(zhí)行。程序的入口及整體流程控制權(quán)由框架把握衰猛。
圖1-2 平臺層軟件的典型設(shè)計模式
在高性能與大數(shù)據(jù)計算領(lǐng)域迟蜜,典型的庫模式軟件有用于計算的Eigen、NumPy啡省,以及用于通信的MPI娜睛、ZeroMQ等髓霞。基于這些庫開發(fā)應(yīng)用時微姊,編程方式比較靈活酸茴,部署模式也相對輕量分预。應(yīng)用開發(fā)者具有較大的自由度兢交,但不得不編寫業(yè)務(wù)邏輯之外的不少“腳手架”代碼,以便將算法代碼片段轉(zhuǎn)變?yōu)橥暾捎玫能浖浴5湫偷目蚣苣J杰浖写髷?shù)據(jù)計算平臺Hadoop配喳、Spark,以及基于SQL和類SQL語言的數(shù)據(jù)庫凳干、數(shù)據(jù)倉庫等晴裹。使用這些框架開發(fā)應(yīng)用時,開發(fā)者的工作相對輕松救赐,只需要編寫與業(yè)務(wù)邏輯密切相關(guān)的算法代碼涧团,不用關(guān)心運行時機制的復(fù)雜性。不過经磅,程序的靈活性將受制于框架的約束泌绣。
TensorFlow的設(shè)計采用了庫模式。之所以如此预厌,是出于靈活通用阿迈、端云結(jié)合及高性能等設(shè)計目標的考慮。庫模式的平臺層軟件便于與各種既有的框架協(xié)同工作轧叽,不對軟件的運行時組件添加新的約束苗沧,應(yīng)用范圍也不受制約。除了依賴最基本的編程語言庫和操作系統(tǒng)調(diào)用炭晒,這類平臺層軟件同其他環(huán)境因素解耦待逞,從而可以做到高度的可移植性。在單機和終端等場景下网严,由于沒有守護進程和調(diào)度框架的開銷飒焦,有效計算邏輯的資源利用率也會提高,進而有助于性能優(yōu)化屿笼。
綜上牺荠,TensorFlow的工作形態(tài)是由用戶編寫主程序代碼,調(diào)用Python或其他語言函數(shù)庫提供的接口以實現(xiàn)計算邏輯驴一。用戶部署和使用TensorFlow系統(tǒng)時休雌,不需要啟動專門的守護進程,也不需要調(diào)用特殊的啟動工具肝断,只需要像編寫普通的本地應(yīng)用程序那樣即可上手杈曲。用戶也不用擔(dān)心庫模式的開發(fā)所必需的那些“腳手架”代碼驰凛,因為TensorFlow已經(jīng)提供了多種高級抽象,盡可能地最小化了核心計算邏輯之外的開發(fā)工作担扑。
1.3.2 組件結(jié)構(gòu)
TensorFlow作為一套包含數(shù)十萬行代碼的大型軟件恰响,其組件結(jié)構(gòu)較為復(fù)雜。不過涌献,由于其代碼組織合理胚宦,文檔資料充分,我們很容易將它的軟件結(jié)構(gòu)進行不同抽象程度的宏觀呈現(xiàn)燕垃。初識TensorFlow的新手只需要從最高層的抽象視角觀察其組件構(gòu)成枢劝。圖1-3給出了一幅粗粒度的TensorFlow組件結(jié)構(gòu)示意圖,展示了TensorFlow的主要內(nèi)部結(jié)構(gòu)及其與周邊環(huán)境的關(guān)系卜壕。
構(gòu)成TensorFlow的主體是其運行時核心庫您旁。對于普通的Python應(yīng)用層開發(fā)者而言,這個核心庫就是指通過pip命令等方式安裝TensorFlow之后轴捎,部署到site-packages或類似目錄中的動態(tài)鏈接庫文件鹤盒。生成這個庫的C++ 源代碼大致分為3個層次:分布式運行時、公共運行時和算子核函數(shù)侦副。其中侦锯,公共運行時實現(xiàn)了數(shù)據(jù)流圖計算的基本邏輯,分布式運行時在此基礎(chǔ)上實現(xiàn)了數(shù)據(jù)流圖的跨進程協(xié)同計算邏輯跃洛,算子核函數(shù)則包含圖上具體操作節(jié)點的算法實現(xiàn)代碼率触。
TensorFlow運行時核心庫導(dǎo)出的函數(shù)接口基于C和C++ 語言。為了使用其他語言進行應(yīng)用開發(fā)汇竭,TensorFlow提供了多語言的API層葱蝗。Python應(yīng)用層開發(fā)者在代碼中調(diào)用import tensorflow as tf時,導(dǎo)入的便是TensorFlow安裝在Python第三方庫目錄下的API層模塊(本書后面沿用這種Python包導(dǎo)入慣例细燎,使用tf作為tensorflow命名空間的縮寫)两曼。API層對用戶屏蔽了TensorFlow核心庫的動態(tài)鏈接邏輯,使得用戶可以使用自己熟悉的語言編寫算法模型玻驻。
為了簡化經(jīng)典模型的開發(fā)悼凑,使得TensorFlow成為一套“開箱即用”的工具,Google官方團隊及開源貢獻者們在TensorFlow社區(qū)開設(shè)了若干算法模型庫及人工智能應(yīng)用程序項目璧瞬。用戶可以復(fù)用這些項目的成果户辫,加快自己的項目開發(fā)進度;也可以學(xué)習(xí)它們的實現(xiàn)原理嗤锉,提升自己的模型與應(yīng)用設(shè)計水平渔欢。這些外圍項目中的部分代碼(如Keras)已被認為具有較高的共性價值,因此逐步被加入到TensorFlow主項目之中瘟忱。
TensorFlow運行時核心庫底層對接的是各種計算庫和通信庫奥额。這些庫有的是外部組件(如用于CPU代數(shù)計算的Eigen庫)苫幢,有的則作為TensorFlow源代碼的一部分集成在核心庫內(nèi)部(如用于GPU并行計算的StreamExecutor庫)。用戶在開發(fā)應(yīng)用程序時看不到這些庫的細節(jié)垫挨,只需要按照軟件文檔安裝好必要的外部依賴包即可韩肝。
上面所有組件均運行在本地操作系統(tǒng)和硬件基礎(chǔ)設(shè)施之上。在服務(wù)器端運行場景九榔,最常見的宿主操作系統(tǒng)是Linux哀峻,硬件一般為x86 CPU和NVIDIA GPU。在移動終端運行場景帚屉,宿主操作系統(tǒng)可以是Android谜诫、iOS等漾峡,硬件一般為ARM CPU和專用的人工智能芯片攻旦。TensorFlow不僅支持原生的物理環(huán)境,對虛擬機和容器也完全兼容生逸,這構(gòu)成了云計算環(huán)境下的最佳實踐牢屋。