
人工智能、機器學習和深度學習
在介紹TensorFlow(以下簡稱為TF)之前,我們首先了解一下相關背景。
TF是一種機器學習架構,而機器學習經常和人工智能,深度學習聯系在一起,那麼三者到底是什麼關系呢?
簡單來講三者可以了解為包含于被包含的關系。其中最大的是人工智能(以下簡稱為AI),AI最早起源于1956年的達特茅斯會議,當時AI的幾位先驅在會上展示了最早的AI程式:Logic Theorist,能夠自動推導數學原理第二章前52個定理中的38個,甚至其中一個定理的證明過程比書中給出的還要優雅,他們甚至曾嘗試要發表這一新的證明方式(不過後來被拒了)。總之,簡單來說,AI就是賦予機器以人的智能,讓機器具有學習和認知的能力。
機器學習(以下簡稱為ML)則是實作AI的一種方法。舉個簡單的垃圾郵件過濾的例子,我們人類判斷一個郵件是否是垃圾郵件很簡單,通過标題或内容很快就可以辨識。但是讓機器完成這樣的任務就沒這麼簡單。對于經典的ML算法,首先需要從原始資料(郵件)中提取特征,比如發信人位址、郵件标題、郵件内容關鍵詞等,進而将文字的郵件轉換成包含多個特征的向量,然後利用邏輯回歸算法在已經标定的資料集上進行訓練,得到每個特征的權重。這些權重構成我們的預測模型,對于一封新的郵件,就可以用這個模型判斷其是否是垃圾郵件。
傳統的ML最大的問題就是特征提取。比如讓機器識别照片中的動物是貓還是狗,如何設計特征?深度學習(以下簡稱為DL)正是為了解決特征提取的問題,我們不再需要人工設計特征,而是讓算法從資料中自動學習特征,将簡單的特征組合形成複雜的特征來解決這些問題,是以DL可以說是實作ML的一種技術。
TensorFlow簡介
TensorFlow是什麼
Tensorflow是一個Google開發的第二代機器學習系統,克服了第一代系統DistBelief僅能開發神經網絡算法、難以配置、依賴Google内部硬體等局限性,應用更加廣泛,并且提高了靈活性和可移植性,速度和擴充性也有了大幅提高。字面上了解,TensorFlow就是以張量(Tensor)在計算圖(Graph)上流動(Flow)的方式的實作和執行機器學習算法的架構。具有以下特點:
靈活性。TensorFlow不是一個嚴格的“神經網絡”庫。隻要可以将計算表示成資料流圖,就可以使用TensorFlow,比如科學計算中的偏微分求解等。(實際上其官網的介紹中對TF的定位就是基于資料流圖的科學計算庫,而非僅僅是機器學習庫)
可移植性。同一份代碼幾乎不經過修改既可以部署到有任意數量CPU、GPU或TPU(Tensor Processing Unit,Google專門為機器學習開發的處理器)的PC、伺服器或移動裝置上。
自動求微分。同Theano一樣,TensorFlow也支援自動求微分,使用者不需要再通過反向傳播求解梯度。
多語言支援。TensorFlow官方支援Python、C++、Go和Java接口,使用者可以在硬體配置較好的機器中用Python進行實驗,在資源較緊張或需要低延遲的環境中用C++進行部署。
性能。雖然TensorFlow最開始釋出時僅支援單機,在性能評測上并不出色,但是憑借Google強大的開發實力,TensorFlow性能已經追上了其他架構。
Google為什麼開源Tensorflow
Google第一代分布式機器學習架構DistBelief在内部大規模使用後沒有選擇開源,而第二代TensorFlow于2015年11月在GitHub上開源,并在持續快速開發疊代中。TensorFlow最早由Google Brain的工程師開發,設計初衷是加速機器學習的研究,并快速地将研究原型轉化為産品。Google選擇開源TensorFlow的原因很簡單:第一是希望借助社群的力量,大家一起完善TensorFlow。第二是回饋社群,Google希望讓這個優秀的工具得到更多的應用,提高學術界和工業界使用機器學習的效率。
自從2015年11月開源以來,TensorFlow迅速在衆多的機器學習架構中脫穎而出,在Github上獲得了最多的Star。下圖統計了Github上流行的機器學習架構的Star數量:
TensorFlow大事記
2015年11月9日,Google Research 釋出了文章:TensorFlow - Google’s latest machine learning system, open sourced for everyone,正式宣布其新一代機器學習系統開源。
2016年4月13日,TensorFlow v0.8釋出,提供分布式計算支援。
2016年4月29日,開發AlphaGo的DeepMind宣布從Torch7平台轉向TensorFlow。
2016年4月12日,基于TensorFlow的世界最準确的文法解析器SyntaxNet宣布開源。
2016年6月27日,TensorFlow v0.9釋出,提高對移動裝置的支援。
2016年8月30日,TF-Slim——TensorFlow的高層庫釋出,使用者可以更簡單快速地定義模型。
2017年2月15日,TensorFlow v1.0釋出,提高了速度和靈活性,并且承諾提供穩定的Python API。
TensorFlow架構
TF的系統構架分為兩部分:
前端:提供程式設計模型,負責構造計算圖,提供Python,C++,Java,Go等多種語言支援。
後端:提供運作時環境,負責執行計算圖,采用C++實作。
使用者在搭建算法時,可以根據個人喜好和實際需求采用合适的前端語言來建構計算圖。圖搭建完成後,以Session為橋梁連接配接TF的後端,啟動并執行圖的計算過程。TF的後端根據目前硬體環境調用Operation的Kernal(Operation在某種硬體裝置的特定實作)完成具體的計算。
注:後文對Session,Operation有具體解釋
TensorFlow程式設計模式
符号式程式設計 vs 指令式程式設計
和我們一般常用的指令式(Imperative)程式設計模式不同,TF采用的是符号式(Symbolic)程式設計。我們先認識一下兩種程式設計模式:
指令式程式設計是很常見的程式設計模式,大多數Python或C++程式都采用指令式程式設計。指令式程式設計明确輸入變量,根據程式邏輯逐漸運算。下面是一段指令式程式設計的Python代碼:
import numpy as np a = np.ones(10) b = np.ones(10) * 2 c = b * a d = c + 1
執行完第一步a = np.ones(10)後,程式得到了輸入變量a,第二句後得到了b,當執行c = b * a時,程式通過乘法計算而得到了c。
符号式程式設計則将計算過程抽象為計算圖,所有輸入節點、運算節點和輸出節點均符号化處理。将上述指令式程式設計代碼轉換為符号式程式設計:
A = Variable('A') B = Variable('B') C = B * AD = C + Constant(1) # compiles the function f = compile(D) d = f(A=np.ones(10), B=np.ones(10)*2)
目前四步執行後,程式并沒有A、B、C、D的值,僅僅是建構了由這四個符号構成的計算圖,如下圖所示:
大多數符号式程式設計的程式中都或顯式或隐式地包含編譯的步驟,将前面定義的計算圖打包成可以調用的函數,而實際的計算則發生在編譯後。
Theano和TensorFlow屬于典型的符号式程式設計模式,而Torch則是指令式程式設計模式。在靈活性上,指令式程式設計模式更優,而在記憶體和計算上,符号式程式設計效率更高。
TensorFlow基本概念
要使用TensorFlow,我們必須了解TensorFlow:
使用圖(Graph)表示計算流程
在會話(Session)中執行圖
使用張量(Tensor)表示資料
使用變量(Variable)維護狀态
使用feed和fetch為任意的操作指派或從中擷取資料
TF使用graph表示計算流程。圖中的節點稱為操作(Operation,以下簡稱OP)。每個OP接受0到多個Tensor,執行計算,輸出0到多個Tensor。圖是對計算流程的描述,需要在Session中運作。Session将計算圖的OP配置設定到CPU或GPU等計算單元,并提供相關的計算方法,并且會傳回OP的結果。
張量(Tensor)
TF使用Tensor表示所有資料,相當于Numpy中的ndarray,0維的數值、一維的矢量、二維的矩陣到n維數組都是Tensor。相對于Numpy,TensorFlow提供了建立張量函數的方法,以及導數的自動計算。下表對比了Numpy和TensorFlow的基本用法。
變量(Variable)
在訓練模型時,Variable被用來存儲和更新參數。Variable包含張量儲存在記憶體的緩沖區中,必須顯式地進行初始化,在訓練後可以寫入磁盤。下面代碼中的Variable充當了一個簡單的計數器角色:
# Create a Variable, that will be initialized to the scalar value 0. state = tf.Variable(0, name="counter") # Create an Op to add one to `state`. one = tf.constant(1) new_value = tf.add(state, one) update = tf.assign(state, new_value) # Variables must be initialized by running an `init` Op after having # launched the graph. We first have to add the `init` Op to the graph. init_op = tf.initialize_all_variables() # Launch the graph and run the ops. with tf.Session() as sess: # Run the 'init' op sess.run(init_op) # Print the initial value of 'state' print(sess.run(state)) # Run the op that updates 'state' and print 'state'. for _ in range(3): sess.run(update) print(sess.run(state)) # output: # 0 # 1 # 2 # 3
上述代碼中assign()操作同add()一樣,都是在建構計算圖而沒有執行實際的計算。直到run()函數才會真正執行指派等計算操作。
一般來說,使用者使用一系列Variable來表示一個統計模型,在訓練過程中運作圖計算來不斷更新,訓練完成後可以使用這些Variable構成的模型進行預測。
Feed
TensorFlow除了可以使用Variable和Constant引入資料外,還提供了Feed機制實作從外部導入資料。一般Feed總是與占位符placeholder一起使用。
input1 = tf.placeholder(tf.float32) input2 = tf.placeholder(tf.float32) output = tf.mul(input1, input2) print(sess.run([output], feed_dict={input1:[7.], input2:[2.]})) # [array([ 14.], dtype=float32)]
Fetch
要擷取操作的輸出,需要執行會話的run()函數,并且提供需要提取的OP。下面是擷取輸出的典型例子:
input1 = tf.constant([3.0]) input2 = tf.constant([2.0]) input3 = tf.constant([5.0]) intermed = tf.add(input2, input3) mul = tf.mul(input1, intermed) result = sess.run([mul, intermed]) print(result) # [array([ 21.], dtype=float32), array([ 7.], dtype=float32)]
圖和會話
由于TF采用符号式程式設計模式,是以TF程式通常可以分為兩部分:圖的建構和圖的執行。
圖的建構
建構圖的第一步,是建立源OP(source op),源操作不需要任何輸入,例如常量(constant),源操作的輸出被傳遞給其它操作做運算。
Python庫中,OP構造器的傳回值代表被構造出的OP的輸出,這些傳回值可以傳遞給其它OP構造器作為輸入。
TensorFlow Python庫有一個預設圖 (default graph),OP構造器可以為其增加節點。這個預設圖對許多程式來說已經足夠用了。
import tensorflow as tf # Create a Constant op that produces a 1x2 matrix. The op is # added as a node to the default graph. # # The value returned by the constructor represents the output # of the Constant op. matrix1 = tf.constant([[3., 3.]]) # Create another Constant that produces a 2x1 matrix. matrix2 = tf.constant([[2.],[2.]]) # Create a Matmul op that takes 'matrix1' and 'matrix2' as inputs. # The returned value, 'product', represents the result of the matrix # multiplication. product = tf.matmul(matrix1, matrix2)
上面使用TensorFlow提供的預設圖建構了包含三個節點的計算圖:兩個constant()操作和一個matmul()操作。要實際執行矩陣乘法,必須在Session中運作該計算圖。
圖的執行
要執行計算圖,首先需要建立Session對象,如果不提供參數,Session構造器将運作預設圖。
# Launch the default graph. sess = tf.Session() # To run the matmul op we call the session 'run()' method, passing 'product' # which represents the output of the matmul op. This indicates to the call # that we want to get the output of the matmul op back. # All inputs needed by the op are run automatically by the session. They # typically are run in parallel. # The call 'run(product)' thus causes the execution of three ops in the # graph: the two constants and matmul. # The output of the op is returned in 'result' as a numpy `ndarray` object. result = sess.run(product) print(result) # ==> [[ 12.]] # Close the Session when we're done. sess.close()
Session結束後,需要關閉以釋放資源。使用者也可以使用with控制語句自動關閉會話。
result = sess.run([product])
TensorFlow簡單入門--MNIST字元識别
MNIST是一個簡單的計算機視覺資料集,包含共7萬個手寫數字字元,以灰階圖表示:
MNIST同時包含每個手寫字元對應的數字,稱為标簽(label)。上圖對應的标簽為5,0,4,1。
接下來,我們将使用TensorFlow訓練一個字元識别的多分類器,通過字元圖檔預測對應的數字,這裡我們使用最簡單的多分類器--Softmax回歸。
MNIST資料集
首先讀取MNIST資料集:
from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
MNIST資料集被讀入mnist對象中,分為三部分:55000行的訓練集(mnist.train)、10000行的測試集(mnist.test)和5000行的驗證集(mnist.validation)。這樣的切分很重要,在機器學習模型設計時必須有一個單獨的測試資料集不用于訓練而是用來評估這個模型的性能,進而更加容易把設計的模型推廣到其他資料集上(泛化)。
每個MNIST資料都包含一個字元圖檔和對應的label,分别用“x”和“y”表示。每個圖檔“x”由2828個像素構成,展開得到長度為784的向量。最後,我們得到的訓練資料集即形狀為[55000, 784]的二維數組以及對應的标簽(0-9)。
為了友善實作,這裡使用“one-hot vector”,即向量中除一個元素為1,其餘均為0。舉個例子:對于标簽3,對應的“one-hot vector”為[0,0,0,1,0,0,0,0,0,0],是以訓練集的标簽mnist.train.labels為形狀為[55000, 10]的二維數組。
Softmax回歸
Softmax回歸是二分類器logistic回歸的推廣,是一種最簡單的多分類器。Softmax回歸分為兩步,首先通過權重求和得到一張給定圖檔屬于特定數字類的證據(evidence),如果這個像素具有很強的證據說明這張圖檔不屬于該類,那麼相應的權值為負數,相反如果這個像素擁有有利的證據支援這張圖檔屬于這個類,那麼權值是正數。
下面的圖檔顯示了一個模型學習到的圖檔上每個像素對于特定數字類的權值。紅色代表負數權值,藍色代表正數權值。
我們也需要加入一個額外的偏置量(bias),因為輸入往往會帶有一些無關的幹擾量。是以對于給定的輸入圖檔 x 它代表的是數字 i 的證據可以表示為
其中Wij 為 i 像素對 j字元的權重,bi 為數字類 i 的偏置量,j 代表給定圖檔 x 的像素索引用于像素求和。然後用softmax函數可以把這些證據轉換成機率 y:
這裡的softmax可以看成是一個激勵(activation)函數或者連結(link)函數,把我們定義的線性函數的輸出轉換成我們想要的格式,也就是關于10個數字類的機率分布。是以,給定一張圖檔,它對于每一個數字的吻合度可以被softmax函數轉換成為一個機率值。softmax函數可以定義為:
用矩陣來表示:
實作回歸模型
TF程式可以分為圖的建構和圖的執行兩部分,而圖的建構又可細分為輸入圖、推斷圖、訓練圖和評估圖四部分。
使用TF之前,首先導入它:
輸入圖
x = tf.placeholder("float", [None, 784]) y_ = tf.placeholder("float", [None, 10])
這裡的x和y不是一個特定的值,而是兩個占位符(placeholder),我們在TF運作計算時輸入這個值。我們希望能夠輸入任意數量的MNIST圖像,每一張圖展平成784維的向量。我們用2維的浮點數張量來表示這些圖檔,這個張量的形狀是[None,784]。(這裡的None表示此張量的第一個次元可以是任何長度的。)
推斷圖
W = tf.Variable(tf.zeros([784,10])) b = tf.Variable(tf.zeros([10])) y = tf.nn.softmax(tf.matmul(x,W) + b)
對于模型中的權重和偏置量這些參數,我們使用Variable來表示。初始化模型參數,這裡我們用全為零的張量來初始化W和b。因為我們要學習W和b的值,它們的初值可以随意設定。注意,W的次元是[784,10],因為我們想要用784維的圖檔向量乘以它以得到一個10維的證據值向量,每一位對應不同數字類。b的形狀是[10],是以我們可以直接把它加到輸出上面。
我們用tf.matmul(X,W)表示x乘以W,對應之前等式裡面的,這裡x是一個2維張量擁有多個輸入。然後再加上b,把和輸入到tf.nn.softmax函數裡面。這樣就得到了推斷結果y。
訓練圖
計算圖的第三個要素是訓練圖。為了訓練我們的模型,我們首先需要定義一個名額來評估這個模型是好的。其實,在機器學習,我們通常定義名額來表示一個模型是壞的,這個名額稱為代價(cost)或損失(loss),然後盡量最小化這個名額。
一個非常常見的代價函數是“交叉熵”(cross-entropy)。交叉熵産生于資訊論裡面的資訊壓縮編碼技術,但是它後來演變成為從博弈論到機器學習等其他領域裡的重要技術手段。它的定義如下:
是我們預測的機率分布,是實際的分布(我們輸入的one-hot vector)。比較粗糙的了解是,交叉熵是用來衡量我們的預測用于描述真相的低效性。
實作交叉熵:
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
首先,用tf.log計算y的每個元素的對數。接下來,我們把y_的每一個元素和tf.log(y_)的對應元素相乘。最後,用tf.reduce_sum計算張量的所有元素的總和。(注意,這裡的交叉熵不僅僅用來衡量單一的一對預測和真實值,而是所有100幅圖檔的交叉熵的總和。對于100個資料點的預測表現比單一資料點的表現能更好地描述我們的模型的性能。
現在我們知道我們需要我們的模型做什麼啦,用TensorFlow來訓練它是非常容易的。因為TensorFlow擁有一張描述你各個計算單元的圖,它可以自動地使用反向傳播算法(backpropagation algorithm)來有效地确定你的變量是如何影響你想要最小化的那個代價函數的。然後,TensorFlow會用你選擇的優化算法來不斷地修改變量以降低代價函數。
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
在這裡,我們要求TF用梯度下降算法(gradient descent algorithm)以0.5的學習速率最小化交叉熵。梯度下降算法(gradient descent algorithm)是一個簡單的學習過程,TF隻需将每個變量一點點地往使代價不斷降低的方向移動。當然TF也提供了其他許多優化算法:隻要簡單地調整一行代碼就可以使用其他的算法。
TF在這裡實際上所做的是,它會在背景給描述你的計算的那張圖裡面增加一系列新的計算操作單元用于實作反向傳播算法和梯度下降算法。然後,它傳回給你的隻是一個單一的操作,當運作這個操作時,它用梯度下降算法訓練你的模型,微調你的變量,不斷減少代價。
我們現在可以建立一個Session來運作模型,
sess = tf.InteractiveSession()
首先我們需要初始化所有變量,
tf.global_variables_initializer().run()
然後開始訓練模型,這裡我們讓模型循環訓練1000次!
for _ in range(1000): batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
該循環的每個步驟中,我們都會随機抓取訓練資料中的100個批處理資料點,然後我們用這些資料點作為參數替換之前的占位符來運作train_step。
使用一小部分的随機資料來進行訓練被稱為随機訓練(stochastic training)- 在這裡更确切的說是随機梯度下降訓練。在理想情況下,我們希望用我們所有的資料來進行每一步的訓練,因為這能給我們更好的訓練結果,但顯然這需要很大的計算開銷。是以,每一次訓練我們可以使用不同的資料子集,這樣做既可以減少計算開銷,又可以最大化地學習到資料集的總體特性。
評估圖
最後,我們要評估模型的性能,還需要建構評估圖。
首先讓我們找出那些預測正确的标簽。tf.argmax 是一個非常有用的函數,它能給出某個tensor對象在某一維上的其資料最大值所在的索引值。由于标簽向量是由0,1組成,是以最大值1所在的索引位置就是類别标簽,比如tf.argmax(y,1)傳回的是模型對于任一輸入x預測到的标簽值,而 tf.argmax(y_,1) 代表正确的标簽,我們可以用 tf.equal 來檢測我們的預測是否真實标簽比對(索引位置一樣表示比對)。
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
這行代碼會給我們一組布爾值。為了确定正确預測項的比例,我們可以把布爾值轉換成浮點數,然後取平均值。例如,[True, False, True, True] 會變成 [1,0,1,1] ,取平均值後得到 0.75.
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
最後,我們計算所學習到的模型在測試資料集上面的正确率。
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
這個最終結果值應該大約是92%。
其他機器學習架構
Caffe
Caffe全稱為Convolutional Architecture for Fast Feature Embedding,目前由BVLC(Berkeley Vision and Learning Center)進行維護。其創始人是加州大學伯克利的Ph.D.賈楊清,後來曾在Google Brain工作,開發TensorFlow。
Caffe優點在于使用配置檔案方式定義網絡,容易上手。訓練速度快,而且有大量訓練好的經典模型。元件子產品化,友善拓展到新的模型上。
Caffe最開始設計是隻是針對圖像,沒有考慮文本、語音或者時間序列的資料,是以對卷積神經網絡的支援很好,但是時間序列RNN、LSTM等支援不是很充分。要實作新的神經網絡子產品(Layer)時,需要使用者自己寫C++或CUDA代碼實作正向和反向算法,對新使用者有一定的難度。Caffe沒有原生的分布式支援,官方僅支援單機多CPU的訓練,不過有些第三方的支援,如雅虎開源的CaffeOnSpark,可借助Spark的分布式架構實作Caffe的大規模分布式訓練。
Torch
Torch的定位是LuaJIT上的高效的科學計算庫,其曆史非常悠久,但真正發揚光大是在Facebook開源了其深度學習的元件之後。Torch與TensorFlow一樣,采用了底層C++加腳本語言調用的方式,不過Torch使用的是Lua,其性能非常優秀,常見的代碼通過JIT優化可以到C的性能的80%,但是相對Python并不是那麼主流,對多數使用者有學習成本。另外,Torch與Theano和TensorFlow采用符号程式設計模式不同,其采用指令式程式設計模式,是以實作某些複雜操作以及debug時更友善。
Keras
Keras是一個崇尚極簡、高度子產品化的神經網絡庫,使用Python實作,可以運作在TensorFlow或Theano上,旨在讓使用者進行最快速的原型實驗。不同于Theano、TensorFlow等支援通用的數值計算,Keras專注于深度學習,它提供了目前為止最友善的API,使用者隻需要将進階的子產品拼在一起,就可以搭建神經網絡,大大降低了程式設計開銷、Keras所有子產品都是簡潔、易懂、完全可配置、可任意插拔的,基本沒有使用限制,神經網絡、損失函數、優化器、初始化方法、激活函數和正則化等子產品都可以自由組合。使用Keras,隻需要幾行就可以實作一個MLP,十幾行就可以實作一個AlexNet。如果Theano和TensorFlow是深度學習領域的Numpy,那麼Keras就是這個領域的scikit-learn。Keras最大的問題就是目前無法直接使用多GPU,是以對大規模的資料處理速度沒有其他支援多GPU和分布式的架構快。
參考資料
官網
TensorFlow Website(最權威、詳細的文檔)
(https://www.tensorflow.org)
視訊教程
TF開發者Sherry Moore的教程
(https://www.youtube.com/watch?v=Ejec3ID_h0w&t=2117s)
周莫煩的TF教程
(https://www.youtube.com/watch?v=2FmcHiLCwTU&list=PL2-dafEMk2A7EEME489DsI468AB0wQsMV)
Siraj的TF教程
(https://www.youtube.com/watch?v=Se9ByBnKb0o&list=PLXO45tsB95cJHXaDKpbwr5fC_CCYylw1f)
書
Python Machine Learning(常用機器學習算法講解與實踐 -- Sebastian Raschka)
(https://www.amazon.com/Python-Machine-Learning-Sebastian-Raschka/dp/1783555130/ref=sr_1_1?ie=UTF8&qid=1491489025&sr=8-1&keywords=python+machine+learning)
TensorFlow實戰(TensorFlow實作多種機器學習算法 -- 黃文堅,唐源)
(https://item.jd.com/12125568.html)
文章
深入淺出Tensorflow(一):深度學習及TensorFlow簡介
(http://www.infoq.com/cn/articles/introduction-of-tensorflow-part01)
Programming Models for Deep Learning
(http://mxnet.io/architecture/program_model.html#symbolic-and-imperative-programs)
TensorFlow學習筆記1:入門
(http://www.jeyzhang.com/tensorflow-learning-notes.html)
圖解TensorFlow架構與設計
(https://mp.weixin.qq.com/s?__biz=MzAwNDI4ODcxNA==&mid=2652244394&idx=1&sn=8c66795bc0e0d262f8defd18c07165a3)
原文釋出時間為:2017-10-12
本文作者:李選選
本文來自雲栖社群合作夥伴“資料派THU”,了解相關資訊可以關注“資料派THU”微信公衆号