TensorFlow是目前最流行的深度學習框架。咱們先引用一段官網對於TensorFlow的介紹,來看一下Google對於它這個產品的定位。node
TensorFlow™ is an open source software library for numerical computation using data flow graphs. Nodes in the graph represent mathematical operations, while the graph edges represent the multidimensional data arrays (tensors) communicated between them. The flexible architecture allows you to deploy computation to one or more CPUs or GPUs in a desktop, server, or mobile device with a single API.python
上文並無提到大紅大紫的Deep Learning,而是聚焦在一個更普遍的科學計算應用領域。引文的關鍵詞有:算法
Numerical Computation:應用領域是數值計算,因此TensorFlow不只能支持Deep Learning,還支持其餘機器學習算法,甚至包括更通常的數值計算任務(如求導、積分、變換等)。segmentfault
Data Flow Graph:用graph來描述一個計算任務。數組
Node:表明一個數學運算(mathmatical operations,簡稱ops),這裏麪包括了深度學習模型常常須要使用的ops。網絡
Edge:指向node的edge表明這個node的輸入,從node引出來的edge表明這個node的輸出,輸入和輸出都是multidimensional data arrays,即多維數組,在數學上又稱之爲tensor。這也是TensorFlow名字的由來,表示多維數組在graph中流動。session
CPUs/GPUs:支持CPU和GPU兩種設備,支持單機和分佈式計算。框架
TensorFlow提供多種語言的支持,其中支持最完善的是Python語言,所以本文將聚焦於Python API。dom
下面這段代碼來自於TensorFlow官網的Get Started,展現了TensorFlow訓練線性迴歸模型的能力。機器學習
import tensorflow as tf import numpy as np # Create 100 phony x, y data points in NumPy, y = x * 0.1 + 0.3 x_data = np.random.rand(100).astype(np.float32) y_data = x_data * 0.1 + 0.3 # Try to find values for W and b that compute y_data = W * x_data + b # (We know that W should be 0.1 and b 0.3, but TensorFlow will # figure that out for us.) W = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) b = tf.Variable(tf.zeros([1])) y = W * x_data + b # Minimize the mean squared errors. loss = tf.reduce_mean(tf.square(y - y_data)) optimizer = tf.train.GradientDescentOptimizer(0.5) train = optimizer.minimize(loss) # Before starting, initialize the variables. We will 'run' this first. init = tf.global_variables_initializer() # Launch the graph. sess = tf.Session() sess.run(init) # Fit the line. for step in range(201): sess.run(train) if step % 20 == 0: print(step, sess.run(W), sess.run(b)) # Learns best fit is W: [0.1], b: [0.3]
下面咱們來剖析一下關鍵代碼。TensorFlow的代碼每每由兩個部分組成:
A construction phase, that assembles a graph, and an execution phase that uses a session to execute ops in the graph.
Session是一個類,做用是把graph ops部署到Devices(CPUs/GPUs),並提供具體執行這些op的方法。
爲何要這麼設計呢?考慮到Python運行性能較低,咱們在執行numerical computing的時候,都會盡可能使用非python語言編寫的代碼,好比使用NumPy這種預編譯好的C代碼來作矩陣運算。在Python內部計算環境和外部計算環境(如NumPy)切換須要花費的時間稱爲overhead cost。對於一個簡單運算,好比矩陣運算,從Python環境切換到Numpy,Numpy運算獲得結果,再從Numpy切回Python,這個成本,比純粹在Python內部作同類運算的成本要低不少。可是,一個複雜數值運算由多個基本運算組合而成,若是每一個基本運算來一次這種環境切換,overhead cost就不可忽視了。爲了減小來回的環境切換,TensorFlow的作法是,先在Python內定義好整個Graph,而後在Python外運行整個完整的Graph。所以TensorFlow的代碼結構也就對應爲兩個階段了。
W = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) b = tf.Variable(tf.zeros([1]))
tf.Variable
是TensorFlow的一個類,是取值可變的Tensor
,構造函數的第一個參數是初始值initial_value
。
initial_value: A Tensor, or Python object convertible to a Tensor, which is the initial value for the Variable.
tf.zeros(shape, dtype=tf.float32, name=None)
是一個op,用於生成取值全是0的Constant Value Tensor
。
tf.random_uniform(shape, minval=0, maxval=None, dtype=tf.float32, seed=None, name=None)
是一個op,用於生成服從uniform distribution的Random Tensor
。
y = W * x_data + b
y是線性迴歸運算產生的Tensor。運算符*
和+
,等價爲tf.multiple()
和tf.add()
這兩個TensorFlow提供的數學類ops。tf.multiple()
的輸入是W和x_data;W是Variable,屬於Tensor,能夠直接做爲op的輸入;x_data是numpy的多維數組ndarray
,TensorFlow的ops接收到ndarray的輸入時,會將其轉化爲tensor。tf.multiple()
的輸出是一個tensor,和b一塊兒交給optf.add()
,獲得輸出結果y。
至此,線性迴歸的模型已經創建好,但這只是Graph的一部分,還須要定義損失。
loss = tf.reduce_mean(tf.square(y - y_data))
loss是最小二乘法須要的目標函數,是一個Tensor,具體的op再也不贅述。
optimizer = tf.train.GradientDescentOptimizer(0.5) train = optimizer.minimize(loss)
這一步指定求解器,並設定求解器的最小化目標爲損失。train表明了求解器執行一次的輸出Tensor。這裏咱們使用了梯度降低求解器,每一步會對輸入loss求一次梯度,而後將loss裏Variable
類型的Tensor按照梯度更新取值。
init = tf.global_variables_initializer()
Build Graph階段的代碼,只是在Python內定義了Graph的結構,並不會真正執行。在Launch Graph階段,全部的變量要先進行初始化。每一個變量能夠單獨初始化,但這樣作有些繁瑣,因此TensorFlow提供了一個方便的函數global_variables_initializer()
能夠在graph中添加一個初始化全部變量的op。
When you launch the graph, variables have to be explicitly initialized before you can run Ops that use their value. All variables are automatically collected in the graph where they are created. By default, the constructor adds the new variable to the graph collection GraphKeys.GLOBAL_VARIABLES. The convenience function global_variables() returns the contents of that collection. The most common initialization pattern is to use the convenience function global_variables_initializer() to add an Op to the graph that initializes all the variables.
sess.run(init)
在進行任何計算之前,先給Variable賦初始值。
for step in range(201): sess.run(train)
train操做對應梯度降低法的一步迭代。當step爲0時,train裏的variable取值爲初始值,根據初始值能夠計算出梯度,而後將初始值根據梯度更新爲更好的取值;當step爲1時,train裏的variable爲上一步更新的值,根據這一步的值能夠計算出一個新的梯度,而後將variable的取值更新爲更好的取值;以此類推,直到達到最大迭代次數。
print(step, sess.run(W), sess.run(b))
若是咱們將sess.run()
賦值給Python環境的變量,或者傳給Python環境的print
,能夠fetch執行op的輸出Tensor取值,這些取值會轉化爲numpy的ndarray結構。所以,這就須要一次環境的切換,會增長overhead cost。因此咱們通常會每隔必定步驟才fetch一下計算結果,以減小時間開銷。
TensorFlow是一個面向數值計算的通用平臺,能夠方便地訓練線性模型。下面這幾篇文章採用TensorFlow完成Andrew Ng主講的Deep Learning課程練習題,提供了整套源碼。
TensorFlow雖然是面向通用的數值計算,可是對深度學習的支持是它最大的特點,也是它可以引爆業界得到目前這麼大的流行度的主要緣由。下面這幾篇文章採用TensorFlow對MNIST進行建模,涵蓋了Deep Learning中最重要的兩類模型:卷積神經網絡CNN和循環神經網絡RNN。
TensorFlow安裝時自帶了一個TensorBoard,能夠對數據集進行可視化地探索分析,能夠對學習過程進行可視化,能夠對Graph進行可視化,對於咱們分析問題和改進模型有極大的幫助。