只有光頭才能變強。python
文本已收錄至個人GitHub倉庫,歡迎Star:github.com/ZhongFuChen…git
回顧前面:github
TensorFlow是什麼意思?Tensor?Flow?這篇文章介紹TensorFlow一些最基礎的知識。算法
在介紹以前,首先要記住一個結論:TensorFlow使用Tensor來表示數據編程
接着咱們來看看什麼是Tensor,在官網的文檔中,Tensor被翻譯成」張量「。其中也給出了一個定義:api
張量是對矢量和矩陣向潛在的更高維度的泛化,TensorFlow 在內部將張量表示爲基本數據類型的n維數組。數組
不知道大家看完這句話有啥感覺,反正我當時就看不懂,啥是」張量「?。因而,我就跑去知乎裏邊用關鍵字搜了一下:」張量是什麼「。果然給我搜到了相關的問題:《怎麼通俗地理解張量?》session
我本覺得經過知乎,就能夠通俗易懂地理解什麼是張量,能給我一個清晰的認識。卻不知,大多數答主都在回答在物理和數學中張量的定義,隨後貼出了一堆我看不懂的公式。其中,也看到了一種相對通俗易懂的定義:數據結構
一個量, 在不一樣的參考系下按照某種特定的法則進行變換, 就是張量.dom
把全部答主的回答都閱讀了一遍,看完就更加抽象了。再回到官方文檔中,看看官方介紹張量的例子,貌似有點懂了。
目前爲止咱們有兩個結論:
我再翻譯一下上面的兩句話:在TensorFlow全部的數據都是一個n維的數組,只是咱們給它起了個名字叫作張量(Tensor)
中間折騰了一大堆,實際上仍是將最開頭的結論和官方的定義再翻譯成本身以爲好理解的話...但不少時候,學習就這麼一個過程。
從上面咱們已經得知,Tensor(張量)實際上就是一個n維的數組。這就延伸了幾個的術語:
其實上,階就是平時咱們所說的維數。
之前在寫Java的時候,可能通常接觸到的都是二維的,但在機器學習上就極可能有很高的維度,那維數咱們怎麼數?很簡單,咱們數括號就好了。舉個例子,咱們可能會看到有下面的一個數組輸出形式:
[[[9 6]
[6 9]
[8 8]
[7 9]]
[[6 1]
[3 5]
[1 7]
[9 4]]]
複製代碼
咱們直接看第一個括號到第一個數字,有多少個括號就知道了。[[[9
能夠發現有3個括號,那這個就是一個三維的數組,它的階(秩)就是3
張量的形狀可讓咱們看到每一個維度中元素的數量。
好比咱們在Java中建立出一個二維的數組:int [][] array = new int[3][4]
,咱們就能夠知道這個數組有三行有四列。但若是咱們建立出一個多維的數組,單單隻用行和列就描述不清了。因此,在TensorFlow通常咱們會這樣描述:
若是咱們要打印上面數組的形狀時,咱們能夠獲得這樣的結果:shape = (3,4)
。咱們再看看第一篇寫」機器學習HelloWorld「的時候,再來看看當時打印的結果:shape = (60000, 28, 28)
。經過shape咱們就能夠獲得一些信息:
那咱們若是拿到一個數組,怎麼經過肉眼看他的shape呢?
好比說:m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
,這個很簡單,一眼就能夠看出這個是一個二維數組(矩陣),有三行三列。因此shape的結果應該是(3,3)
再來看一個:t = [[[2], [4], [6]], [[8], [10], [12]], [[14], [16], [18]]]
,從多個括號上咱們能夠看出,這是三維的。咱們先把最外層括號去掉獲得的結果是[[2], [4], [6]], [[8], [10], [12]], [[14], [16], [18]]
Ok,到這一步,咱們能夠理解成有三個子數組,因而咱們的shape能夠先寫成shape(3,?,?)
(?,?,?)
的。從「子數組」的個數咱們將第一個「?」號填充爲3隨後,咱們繼續把外層的括號去除,獲得這樣的結果:[2], [4], [6]
,也是有三個元素,因而咱們的shape就能夠填成shape(3,3,?)
最後,再把括號去掉,咱們能夠發現只有一個元素,因而最後的結果就是shape(3,3,1)
咱們能夠看下圖來鞏固一下上面所說的概念:
TensorFlow 在內部將張量表示爲基本數據類型的 n維數組,沒錯的。在一個數組裏邊,咱們總得知道咱們的存進去的數據到底是什麼類型。
Tensor的數據類型以下所示:
特殊的張量由一下幾種:
tf.Variable
— 變量tf.constant
— 常量tf.placeholder
—佔位符tf.SparseTensor
—稀疏張量此次,咱們先來說講前三種(比較好理解),分別是變量、常量和佔位符。
常量就是常量的意思,一經建立就不會被改變。(相信你們仍是可以理解的)
在TensorFlow中,建立常量的方式十分簡單:
a = tf.constant(2)
b = tf.constant(3)
複製代碼
變量也挺好理解的(就將編程語言的概念跟這裏類比就行了)。通常來講,咱們在訓練過程當中的參數通常用變量進行存儲起來,由於咱們的參數會不停的變化。
在TensorFlow建立變量有兩種方式:
# 1.使用Variable類來建立
# tf.random_normal 方法返回形狀爲(1,4)的張量。它的4個元素符合均值爲100、標準差爲0.35的正態分佈。
W = tf.Variable(initial_value=tf.random_normal(shape=(1, 4), mean=100, stddev=0.35), name="W")
b = tf.Variable(tf.zeros([4]), name="b")
# 2.使用get_variable的方式來建立
my_int_variable = tf.get_variable("my_int_variable", [1, 2, 3], dtype=tf.int32,
initializer=tf.zeros_initializer)
複製代碼
值得注意的是:當咱們建立完變量之後,咱們每次使用以前,都須要爲其進行初始化!
tf.global_variables_initializer()
複製代碼
我最先接觸佔位符這個概念的時候是在JDBC的時候。由於SQL須要傳入的參數才能肯定下來,因此咱們可能會寫出這樣的SQL語句:select * from user where id =?
一樣地,在TensorFlow佔位符也是這麼一個概念,可能須要等到運行的時候才把某些變量肯定下來,因而咱們就有了佔位符。
在TensorFlow使用佔位符也很簡單:
# 文件名須要等到運行的時候才肯定下來
train_filenames = tf.placeholder(tf.string, shape=[None])
# ..省略一堆細節
# 運行的時候,經過feed_dict將佔位符具體的值給肯定下來
feed_dict={train_filenames: training_filenames}
複製代碼
上面的東西說白了在編程語言中都是有的,只是語法變了而已。
咱們將Flow翻譯成中文:流,因此如今是Tensor流?
其實,在TensorFlow中,使用圖 (graph) 來表示計算任務。其實TensorFlow默認會給咱們一張空白的圖,通常咱們會叫這個爲」數據流圖「。數據流圖由有向邊和節點組成,在使用TensorFlow的時候咱們會在圖中建立各類的節點,而Tensor會在這些節點中流通。因此,就叫作TensorFlow
那有人就會好奇,咱們執行什麼操做會建立節點呢?在TensorFlow中,節點的類型能夠分爲三種:
看到這裏的同窗,可能就反應過來了:原來在上面建立的變量、常量和佔位符在TensorFlow中都會生成一個節點!對於這類的操做Operation(行爲)通常你們會簡說成op
因此,op就是在TensorFlow中所執行的一個操做統稱而已(有多是建立變量的操做、也有多是計算的操做)。在TensorFlow的常見的op有如下:
其實說白了就是TensorFlow會給咱們一張空白的數據流圖,咱們往這張數據流圖填充(建立節點),從而實現想要效果。
咱們來看看官方的給出數據流圖的gif,加深下印象。
TensorFlow程序一般被組織成一個構建階段和執行階段. 在構建階段, op的執行步驟被描述成一個圖. 在執行階段, 使用會話執行執行圖中的op。
說白了,就是當咱們在編寫代碼的時候,實際上就是在將TensorFlow給咱們的空白圖描述成一張咱們想要的圖。但咱們想要運行出圖的結果,那就必須經過session來執行。
舉個小例子:
import tensorflow as tf
# 建立數據流圖:y = W * x + b,其中W和b爲存儲節點,x爲數據節點。
x = tf.placeholder(tf.float32)
W = tf.Variable(1.0)
b = tf.Variable(1.0)
y = W * x + b
# =========若是不使用session來運行,那上面的代碼只是一張圖。咱們經過session運行這張圖,獲得想要的結果
with tf.Session() as sess:
tf.global_variables_initializer().run() # Operation.run
fetch = y.eval(feed_dict={x: 3.0}) # Tensor.eval
print(fetch) # fetch = 1.0 * 3.0 + 1.0
複製代碼
Fetch就時候能夠在session.run
的時候傳入多個op(tensor),而後返回多個tensor(若是隻傳入一個tensor的話,那就是返回一個tensor)
有的同窗在查閱資料的時候,發現可能調用的不是session.run
,而是tensor.eval()和Operation.run()
。其實,他們最後的調用的仍是session.run
。不一樣的是session.run
能夠一次返回多個tensor(經過Fetch)。
曾經看到一段話總結得不錯:
變量 (Variable)
維護狀態.TensorFlow 是一個編程系統, 使用圖來表示計算任務. 圖中的節點被稱之爲 op (operation 的縮寫). 一個 op 得到 0 個或多個
Tensor
, 執行計算, 產生 0 個或多個Tensor
. 每一個 Tensor 是一個類型化的多維數組.
這篇文章簡單講了TensorFlow是啥意思以及一些基礎的概念。但我也只是簡單以個人理解方式來講了一些常見概念。裏頭的知識點仍是比較多的(好比建立變量的時候通常咱們會指定哪些參數….),這些就交由你們去官網、博客、書籍去學習了。
我相信,只要瞭解了這些概念,那學習必定能夠事半功倍!
下一篇TensorFlow文章敬請期待~
參考資料:
樂於輸出乾貨的Java技術公衆號:Java3y。公衆號內有200多篇原創技術文章、海量視頻資源、精美腦圖,不妨來關注一下!
以爲個人文章寫得不錯,不妨點一下贊!