最近看到一份不錯的深度學習資源——Stanford中的CS20SI:《TensorFlow for Deep Learning Research》,正好跟着學習一下TensorFlow的基礎,還是收獲頗豐,隨手整理成博客隨時翻閱。
為什么選擇TensorFlow?
自從12年AlexNet獲得ImageNet大賽的冠軍后,深度學習開始流行起來,也因為硬件的快速發展GPU並行計算配合易用的API,讓深度學習以及神經網絡大放光彩。
深度學習的框架其實有很多,目前來說最火的還要數Pytorch、TensorFlow以及Keras。其中Pytorch比較適合學術研究,自己搞着玩,如果工業實踐就不太適合了。TensorFlow由於時間比較久,學起來比較困難,不過有完整的開發、部署方案,還有大量的github項目可供參考。Keras則是TensorFlow的一個高級API,同類的還有TensorFlow的TFLearn等等。
總結來說,如果你是學生,只是為了論文或者學習,那么推薦Pytorch;如果你是公司的開發者,想要在業務中使用深度學習,推薦直接使用TensorFlow,如果使用最新的1.12,那么官方的示例里面就已經是Keras了;如果你是從github上面下載了源碼想要學習,那就得去學習對應版本的TensorFlow API了。
在總結一下Tensoflow的優點:
- 易用性:有對應Python的API
- 可移植性:一套代碼就可以適應單個或者多個CPU、GPU、移動設備等
- 靈活性:可以部署在樹莓派、安卓、windows、ios、linux等上
- 可視化:有tensorboard提供開發的可視化界面,方便跟蹤調參
- 檢查點:可以通過檢查點記錄保存實驗數據
- 自動微積分:自動求解梯度
- 龐大的社區:一年內擁有10000+的開發者,3000+的項目
- 大量基於TensorFlow的項目代碼
使用TensorFlow的公司包括:Google,OpenAI,DeepMind,SnapChat,Airbus,eBay等
基於TensorFlow可以做很多事情,比如圖像CV、自然語言處理NLP、語音識別等等。
基礎知識
1. 簡化的API
下面就來學習下TensorFlow的基礎知識,TensorFlow不僅提供了基礎的語法,還提供了一些簡化的API:
- TF Learn,tf.contrib.learn,基於scikit-learn風格的API
- TF Slim,tf.contrib.slim,輕量級的tf構建API,可以自動配置默認值,簡化使用
- Keras,更高級更抽象的API,使用Keras之后,就像疊積木一樣創建模型,不過對於背后的原理隱藏的太深太深...
2. 數據流圖
如果做過大數據或者接觸過java8的流計算,對這種數據流圖應該比較了解。就是我們在程序執行前,先構建好計算的流程框架,然后執行的時候現去讀取數據分配資源執行計算。這樣一方面把構建與計算分離,另一方面也可以代碼自己做更深的優化。
比如上面的數據流圖中,事先定義好整個網絡的結構,然后計算的時候直接傳入5和3,就能得到結果23了。
3. Tensor張量
張量,不是張亮,更不是麻辣燙,它是一種高維數據的統稱。比如:
- 0維的張量,我們也叫做標量scalar或者數字,
- 1維的張量,叫做向量vector
- 2維的張量,叫做矩陣matrix
因此TensorFlow,可以理解為Tensor+Flow,即張量的數據流。
4. 數據流圖的例子
import tensorflow as tf
# 第一個例子,計算兩個數的加法
a = tf.constant(2)
b = tf.constant(3)
x = tf.add(a, b)
with tf.Session() as sess:
print(sess.run(x))
在上面的代碼中,就構建了一個最基本的數據流圖的計算例子。
其中
a = tf.constant(2)
b = tf.constant(3)
x = tf.add(a, b)
就是在構建圖。而想要拿到x的值,就必須新建一個session(這個時候才會分配資源),執行run方法(這個時候才會執行)。
5. tensorboard的使用
為了方便查看構建圖,需要學會怎么使用TensorBoard。在上面的代碼中,只需要增加Tensorboard的聲明即可:
import tensorflow as tf
# 第一個例子,計算兩個數的加法
a = tf.constant(2)
b = tf.constant(3)
x = tf.add(a, b)
with tf.Session() as sess:
writer = tf.summary.FileWriter('./graphs', sess.graph)
print(sess.run(x))
writer.close()
然后在命令行中輸入
tensorboard --logdir=/Users/xingoo/PycharmProjects/xxx/graphs
登錄localhost:6006
就可以看到下面的內容。
可以看到左邊有描述每個節點的意思,點擊add后,可以到關於add節點的描述。由於構建的圖很簡單,就是兩個數相加,因此整個圖只有三個圈圈。並且按照默認的操作進行了命名。
6. 更復雜點的例子
增加以下圖的復雜度,並且同時對兩個結果計算:
import tensorflow as tf
# tf.constant(value, dtype=None, shape=None, name='Const', verify_shape=False)
a = tf.constant([1, 3], name="a")
b = tf.constant([[0, 1], [2, 3]], name="b")
x = tf.add(a, b, name="add")
y = tf.multiply(a, b, name="mul")
with tf.Session() as sess:
writer = tf.summary.FileWriter('./graphs', sess.graph)
x, y = sess.run([x, y])
print(x)
print(y)
writer.close()
由於x、y是獨立運算沒有什么交集,因此在圖中,他們是獨立的兩個操作。
7. 關於圖
回頭再來看看tensorFlow中的圖到底是什么呢?當使用第5部分中的代碼構建graph時,可以直接輸出graph的定義:
import tensorflow as tf
a = tf.constant(2)
b = tf.constant(3)
x = tf.add(a, b)
with tf.Session() as sess:
print(sess.graph.as_graph_def())
得到如下的內容:
node {
name: "Const"
op: "Const"
attr {
key: "dtype"
value {
type: DT_INT32
}
}
attr {
key: "value"
value {
tensor {
dtype: DT_INT32
tensor_shape {
}
int_val: 2
}
}
}
}
node {
name: "Const_1"
op: "Const"
attr {
key: "dtype"
value {
type: DT_INT32
}
}
attr {
key: "value"
value {
tensor {
dtype: DT_INT32
tensor_shape {
}
int_val: 3
}
}
}
}
node {
name: "Add"
op: "Add"
input: "Const"
input: "Const_1"
attr {
key: "T"
value {
type: DT_INT32
}
}
}
versions {
producer: 26
}
每個node基本都包含下面你的內容:
{
name:我們自己起的名字,如果沒有則是op+自增的數,
op:操作
attr: 類型
attr:值 {
形狀、初始值
}
}
通過上面的json,就能完美的組合出web中看到的圖了。
至於graph到底怎么用,就看后面一節課的內容吧。