關(guān)于 TensorFlow
TensorFlow? 是一個采用數(shù)據(jù)流圖(data flow graphs),用于數(shù)值計算的開源軟件庫。節(jié)點(Nodes)在圖中表示數(shù)學(xué)操作,圖中的線(edges)則表示在節(jié)點間相互聯(lián)系的多維數(shù)據(jù)數(shù)組,即張量(tensor)。它靈活的架構(gòu)讓你可以在多種平臺上展開計算,例如臺式計算機中的一個或多個CPU(或GPU),服務(wù)器,移動設(shè)備等等。TensorFlow 最初由Google大腦小組(隸屬于Google機器智能研究機構(gòu))的研究員和工程師們開發(fā)出來,用于機器學(xué)習(xí)和深度神經(jīng)網(wǎng)絡(luò)方面的研究,但這個系統(tǒng)的通用性使其也可廣泛用于其他計算領(lǐng)域。
Tensorflow是谷歌公司在2015年9月開源的一個深度學(xué)習(xí)框架。
什么是數(shù)據(jù)流圖(Data Flow Graph)?
數(shù)據(jù)流圖用“結(jié)點”(nodes)和“線”(edges)的有向圖來描述數(shù)學(xué)計算?!肮?jié)點” 一般用來表示施加的數(shù)學(xué)操作,但也可以表示數(shù)據(jù)輸入(feed in)的起點/輸出(push out)的終點,或者是讀取/寫入持久變量(persistent variable)的終點。“線”表示“節(jié)點”之間的輸入/輸出關(guān)系。這些數(shù)據(jù)“線”可以輸運“size可動態(tài)調(diào)整”的多維數(shù)據(jù)數(shù)組,即“張量”(tensor)。張量從圖中流過的直觀圖像是這個工具取名為“Tensorflow”的原因。一旦輸入端的所有張量準備好,節(jié)點將被分配到各種計算設(shè)備完成異步并行地執(zhí)行運算。

TensorFlow的特征
高度的靈活性
TensorFlow 不是一個嚴格的“神經(jīng)網(wǎng)絡(luò)”庫。只要你可以將你的計算表示為一個數(shù)據(jù)流圖,你就可以使用Tensorflow。你來構(gòu)建圖,描寫驅(qū)動計算的內(nèi)部循環(huán)。我們提供了有用的工具來幫助你組裝“子圖”(常用于神經(jīng)網(wǎng)絡(luò)),當然用戶也可以自己在Tensorflow基礎(chǔ)上寫自己的“上層庫”。定義順手好用的新復(fù)合操作和寫一個python函數(shù)一樣容易,而且也不用擔心性能損耗。當然萬一你發(fā)現(xiàn)找不到想要的底層數(shù)據(jù)操作,你也可以自己寫一點c++代碼來豐富底層的操作。
真正的可移植性(Portability)
Tensorflow 在CPU和GPU上運行,比如說可以運行在臺式機、服務(wù)器、手機移動設(shè)備等等。想要在沒有特殊硬件的前提下,在你的筆記本上跑一下機器學(xué)習(xí)的新想法?Tensorflow可以辦到這點。準備將你的訓(xùn)練模型在多個CPU上規(guī)?;\算,又不想修改代碼?Tensorflow可以辦到這點。想要將你的訓(xùn)練好的模型作為產(chǎn)品的一部分用到手機app里?Tensorflow可以辦到這點。你改變主意了,想要將你的模型作為云端服務(wù)運行在自己的服務(wù)器上,或者運行在Docker容器里?Tensorfow也能辦到。Tensorflow就是這么拽 :)
將科研和產(chǎn)品聯(lián)系在一起
過去如果要將科研中的機器學(xué)習(xí)想法用到產(chǎn)品中,需要大量的代碼重寫工作。那樣的日子一去不復(fù)返了!在Google,科學(xué)家用Tensorflow嘗試新的算法,產(chǎn)品團隊則用Tensorflow來訓(xùn)練和使用計算模型,并直接提供給在線用戶。使用Tensorflow可以讓應(yīng)用型研究者將想法迅速運用到產(chǎn)品中,也可以讓學(xué)術(shù)性研究者更直接地彼此分享代碼,從而提高科研產(chǎn)出率。
自動求微分
基于梯度的機器學(xué)習(xí)算法會受益于Tensorflow自動求微分的能力。作為Tensorflow用戶,你只需要定義預(yù)測模型的結(jié)構(gòu),將這個結(jié)構(gòu)和目標函數(shù)(objective function)結(jié)合在一起,并添加數(shù)據(jù),Tensorflow將自動為你計算相關(guān)的微分導(dǎo)數(shù)。計算某個變量相對于其他變量的導(dǎo)數(shù)僅僅是通過擴展你的圖來完成的,所以你能一直清楚看到究竟在發(fā)生什么。
多語言支持
Tensorflow 有一個合理的c++使用界面,也有一個易用的python使用界面來構(gòu)建和執(zhí)行你的graphs。你可以直接寫python/c++程序,也可以用交互式的ipython界面來用Tensorflow嘗試些想法,它可以幫你將筆記、代碼、可視化等有條理地歸置好。當然這僅僅是個起點——我們希望能鼓勵你創(chuàng)造自己最喜歡的語言界面,比如Go,Java,Lua,Javascript,或者是R。
性能最優(yōu)化
比如說你又一個32個CPU內(nèi)核、4個GPU顯卡的工作站,想要將你工作站的計算潛能全發(fā)揮出來?由于Tensorflow 給予了線程、隊列、異步操作等以最佳的支持,Tensorflow 讓你可以將你手邊硬件的計算潛能全部發(fā)揮出來。你可以自由地將Tensorflow圖中的計算元素分配到不同設(shè)備上,Tensorflow可以幫你管理好這些不同副本。
誰可以用 TensorFlow?
任何人都可以用Tensorflow。學(xué)生、研究員、愛好者、極客、工程師、開發(fā)者、發(fā)明家、創(chuàng)業(yè)者等等都可以在Apache 2.0 開源協(xié)議下使用Tensorflow。
Tensorflow 還沒竣工,它需要被進一步擴展和上層建構(gòu)。我們剛發(fā)布了源代碼的最初版本,并且將持續(xù)完善它。我們希望大家通過直接向源代碼貢獻,或者提供反饋,來建立一個活躍的開源社區(qū),以推動這個代碼庫的未來發(fā)展。
為啥Google要開源這個神器?
如果Tensorflow這么好,為啥不藏起來而是要開源呢?答案或許比你想象的簡單:我們認為機器學(xué)習(xí)是未來新產(chǎn)品和新技術(shù)的一個關(guān)鍵部分。在這一個領(lǐng)域的研究是全球性的,并且發(fā)展很快,卻缺少一個標準化的工具。通過分享這個我們認為是世界上最好的機器學(xué)習(xí)工具庫之一的東東,我們希望能夠創(chuàng)造一個開放的標準,來促進交流研究想法和將機器學(xué)習(xí)算法產(chǎn)品化。Google的工程師們確實在用它來提供用戶直接在用的產(chǎn)品和服務(wù),而Google的研究團隊也將在他們的許多科研文章中分享他們對Tensorflow的使用。
TensorflowSharp中的概念
TensorflowSharp / Tensorflow中最重要的幾個概念:
圖(Graph):它包含了一個計算任務(wù)中的所有變量和計算方式??梢詫⑺虲#中的表達式樹進行類比。例如,一個1+2可以被看作為兩個常量表達式,以一個二元運算表達式連接起來。在Tensorflow的世界中,則可以看成是兩個tensor和一個op(operation的縮寫,即操作)。簡單來說,做一個機器學(xué)習(xí)的任務(wù)就是計算一張圖。
在計算圖之前,當然要把圖建立好。例如,計算(1+2)*3再開根號,是一個包括了3個tensor和3個Op的圖。
不過,Tensorflow的圖和常規(guī)的表達式還有所不同,Tensorflow中的節(jié)點變量是可以被遞歸的更新的。我們所說的“訓(xùn)練”,也就是不停的計算一個圖,獲得圖的計算結(jié)果,再根據(jù)結(jié)果的值調(diào)整節(jié)點變量的值,然后根據(jù)新的變量的值再重新計算圖,如此重復(fù),直到結(jié)果令人滿意(小于某個閾值),或跑到了一個無窮大/?。ㄟ@說明圖的變量初始值設(shè)置的有問題),或者結(jié)果基本不變了為止。
前面說過,從內(nèi)部機制上來說,TF就是建立數(shù)據(jù)流圖來進行數(shù)值計算。所以,當你使用TF來搭建模型時,其實主要涉及兩個方面:根據(jù)模型建立計算圖,然后送入數(shù)據(jù)運行計算圖得到結(jié)果。計算圖computational graph是TF中很重要的一個概念,其是由一系列節(jié)點(nodes)組成的圖模型,每個節(jié)點對應(yīng)的是TF的一個算子(operation)。每個算子會有輸入與輸出,并且輸入和輸出都是張量。所以我們使用TF的算子可以構(gòu)建自己的深度學(xué)習(xí)模型,其背后的就是一個計算圖。還有一點這個計算圖是靜態(tài)的,意思是這個計算圖每個節(jié)點接收什么樣的張量和輸出什么樣的張量已經(jīng)固定下來。要運行這個計算圖,你需要開啟一個會話(session),在session中這個計算圖才可以真正運行。
我們用一個簡單的例子來說明圖模型的機理,首先定義一個計算圖:
public static void BasicOperation2()
{
using (var s = new TFSession())
{
var g = s.Graph;
var a = g.Const(5);
var b = g.Const(3);
var c = g.Mul(a, b);
var d = g.Add(a, b);
var e = g.Add(c, d);
var runner = s.GetRunner();
var result = runner.Run(e);
Console.WriteLine($"相加的結(jié)果:{result.GetValue()}");
// 相加的結(jié)果:23
}
}
代碼很簡單,我們引入TF庫,然后利用TF的基本算術(shù)算子(和Numpy接口一致)創(chuàng)建了一個簡單的計算圖如下圖所示。其中每個圓圈代表的是每個算子定義的節(jié)點。節(jié)點之間的邊就是張量,這里其實都是標量(scalers)。

當我們想得到e的值時,TF會根據(jù)創(chuàng)建好的計算圖查找e節(jié)點所有的依賴節(jié)點,這可以看成一個抽取子計算圖的過程。得到這個子計算圖就可以從a和b節(jié)點開始計算最終得到e的值。還有一點TF會對這個計算過程做并行化優(yōu)化,不過這都是底層的事了。TF更靈活的一點你可以指定各個節(jié)點在哪個具體的設(shè)備上運行,如CPU和GPU。理解好計算圖,就掌握了TF的基本運作原理。
會話(Session):為了獲得圖的計算結(jié)果,圖必須在會話中被啟動。圖是會話類型的一個成員,會話類型還包括一個runner,負責(zé)執(zhí)行這張圖。會話的主要任務(wù)是在圖運算時分配CPU或GPU。
張量(tensor): Tensorflow中所有的輸入輸出變量都是張量,而不是基本的int,double這樣的類型,即使是一個整數(shù)1,也必須被包裝成一個0維的,長度為1的張量【1】。一個張量和一個矩陣差不多,可以被看成是一個多維的數(shù)組,從最基本的一維到N維都可以。張量擁有階(rank),形狀(shape),和數(shù)據(jù)類型。其中,形狀可以被理解為長度,例如,一個形狀為2的張量就是一個長度為2的一維數(shù)組。而階可以被理解為維數(shù)。
| 階 | 數(shù)學(xué)實例 | Python 例子 |
|---|---|---|
| 0 | 純量 (只有大小) | s = 483 |
| 1 | 向量(大小和方向) | v = [1.1, 2.2, 3.3] |
| 2 | 矩陣(數(shù)據(jù)表) | m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] |
| 3 | 3階張量 (數(shù)據(jù)立體) | t = [[[2], [4], [6]], [[8], [10], [12]], [[14], [16], [18]]] |
對于任何深度學(xué)習(xí)框架,你都要先了解張量(Tensor)的概念,張量可以看成是向量和矩陣的衍生。向量是一維的,而矩陣是二維的,對于張量其可以是任何維度的。一般情況下,你要懂得張量的兩個屬性:形狀(shape)和秩(rank)。秩很好理解,就是有多少個維度;而形狀是指的每個維度的大小。下面是常見的張量的形象圖表示:

名字就是TensorFlow,直觀來看,就是張量的流動。張量(tensor),即任意維度的數(shù)據(jù),一維、二維、三維、四維等數(shù)據(jù)統(tǒng)稱為張量。而張量的流動則是指保持計算節(jié)點不變,讓數(shù)據(jù)進行流動。這樣的設(shè)計是針對連接式的機器學(xué)習(xí)算法,比如邏輯斯底回歸,神經(jīng)網(wǎng)絡(luò)等。連接式的機器學(xué)習(xí)算法可以把算法表達成一張圖,張量從圖中從前到后走一遍就完成了前向運算;而殘差從后往前走一遍,就完成了后向傳播。
Tensorflow中的運算(op)有很多很多種,最簡單的當然就是加減乘除,它們的輸入和輸出都是tensor。
Runner:在建立圖之后,必須使用會話中的Runner來運行圖,才能得到結(jié)果。在運行圖時,需要為所有的變量和占位符賦值,否則就會報錯。
TensorflowSharp中的幾類主要變量
- Const:常量,這很好理解。它們在定義時就必須被賦值,而且值永遠無法被改變。
- Placeholder:占位符。這是一個在定義時不需要賦值,但在使用之前必須賦值(feed)的變量,通常用作訓(xùn)練數(shù)據(jù)。
- Variable:變量,它和占位符的不同是它在定義時需要賦值,而且它的數(shù)值是可以在圖的計算過程中隨時改變的。因此,占位符通常用作圖的輸入(即訓(xùn)練數(shù)據(jù)),而變量用作圖中可以被“訓(xùn)練”或“學(xué)習(xí)”的那些tensor,例如y=ax+b中的a和b。
Cloud Machine Learning
前面已經(jīng)介紹了TensorFlow相關(guān)的全部內(nèi)容,細心的網(wǎng)友可能已經(jīng)發(fā)現(xiàn),TensorFlow功能強大,但究其本質(zhì)還是一個library,用戶除了編寫TensorFlow應(yīng)用代碼還需要在物理機上起服務(wù),并且手動指定訓(xùn)練數(shù)據(jù)和模型文件的目錄,維護成本比較大,而且機器之間不可共享。
縱觀大數(shù)據(jù)處理和資源調(diào)度行業(yè),Hadoop生態(tài)儼然成為了業(yè)界的標準,通過MapReduce或Spark接口來處理數(shù)據(jù),用戶通過API提交任務(wù)后由Yarn進行統(tǒng)一的資源分配和調(diào)度,不僅讓分布式計算成為可能,也通過資源共享和統(tǒng)一調(diào)度平的臺極大地提高了服務(wù)器的利用率。很遺憾TensorFlow定義是深度學(xué)習(xí)框架,并不包含集群資源管理等功能,但開源TensorFlow以后,Google很快公布了Google Cloud ML服務(wù),我們從Alpha版本開始已經(jīng)是Cloud ML的早期用戶,深深體會到云端訓(xùn)練深度學(xué)習(xí)的便利性。通過Google Cloud ML服務(wù),我們可以把TensorFlow應(yīng)用代碼直接提交到云端運行,甚至可以把訓(xùn)練好的模型直接部署在云上,通過API就可以直接訪問,也得益于TensorFlow良好的設(shè)計,我們基于Kubernetes和TensorFlow serving實現(xiàn)了Cloud Machine Learning服務(wù),架構(gòu)設(shè)計和使用接口都與Google Cloud ML類似。

總結(jié)
一篇短而精悍的小文肯定不能把TF所有的方面展示出來,但是這是一個起點,盡情地使用Tensorflow吧!