tensorflow學習筆記系列(三):tensorflow入門與基本使用

<u>版權所有,轉載請注明出處</u>


其它相關文章:
tensorflow學習筆記系列(一):前言
tensorflow學習筆記系列(二):tensorflow簡介與安裝
tensorflow學習筆記系列(四):tensorflow實現自動編碼機
tensorflow學習筆記系列(五):tensorflow實現多層感知機
tensorflow學習筆記系列(六):tensorflow實現卷積神經網絡
tensorflow學習筆記系列(七):神經網絡的一些理論知識
tensorflow學習筆記系列(八):TensorBoard介紹
tensorflow學習筆記系列(九):tensorflow源碼解析

  • <u>說明:</u>
  • 目前已完成(一)~(三)
  • 該內容為本人學習tensorflow過程中的筆記,皆為個人理解,難免會存在各種問題,有不當之處請大家批評指正!

基本上每一個語言或者工具都有自己的“hello world” demo,那么學習它們一般都會從這個“hello world”開始。今天我們就來看看tensorflow的“hello world”(非官網)。
在開始編寫“hello world”之前我們先看看tensorflow的編程模型。

一. tensorflow編程模型簡介

這部分的一個很好的教程是官網上的Basic Usage,講解的還是很清晰的。

Tensorflow中的計算可以表示為一個有向圖(directed graph),或稱計算圖(computation graph),其中每一個運算操作將作為一個節點(node),節點與節點之間的連接成為邊(edge),而在計算圖的邊中流動(flow)的數據被稱為張量(tensor),所以形象的看整個操作就好像數據(tensor)在計算圖(computation graphy)中沿著邊(edge)流過(flow)一個個節點(node),這就是tensorflow名字的由來的。

計算圖中的每個節點可以有任意多個輸入和任意多個輸出,每個節點描述了一種運算操作(operation, op),節點可以算作運算操作的實例化(instance)。計算圖描述了數據的計算流程,它也負責維護和更新狀態,用戶可以對計算圖的分支進行條件控制或循環操作。用戶可以使用pyton、C++、Go、Java等語言設計計算圖。tensorflow通過計算圖將所有的運算操作全部運行在python外面,比如通過c++運行在cpu或通過cuda運行在gpu 上,所以實際上python只是一種接口,真正的核心計算過程還是在底層采用c++或cuda在cpu或gpu上運行。

一個 TensorFlow圖描述了計算的過程. 為了進行計算, 圖必須在會話(session)里被啟動. 會話將圖的op分發到諸如CPU或GPU之的備上, 同時提供執行op的方法. 這些方法執行后, 將產生的tensor返回. 在Python語言中, 返回的tensor是numpy ndarray對象; 在C和C++語言中, 返回的tensor是tensorflow::Tensor實例。

從上面的描述中我們可以看到,tensorflow的幾個比較重要的概念:tensor, computation graphy, node, session。正如前面所說,整個操作就好像數據(tensor)在計算圖(computation graphy)中沿著邊(edge)流過(flow)一個個節點(node),然后通過會話(session)啟動計算。所以簡單來說,要完成這整個過程,我們需要的東西是要定義數據、計算圖和計算圖上的節點,以及啟動計算的會話。所以在實際使用中我們要做的大部分工作應該就是定義這些內容了。

二. tensorflow基本使用

正如官方教程里所說:

To use TensorFlow you need to understand how TensorFlow:

  • Represents computations as graphs.
  • Executes graphs in the context of Sessions.
  • Represents data as tensors.
  • Maintains state with Variables.
  • Uses feeds and fetches to get data into and out of arbitrary operations.

我們只有理解了這些概念,明白它們分別是做什么的,才能掌握tensorflow的使用方法。下面簡單介紹下這些概念及使用。

  • 計算圖(computation graphy)
    計算圖是由一個個節點和連接各個節點的邊組成,因此要定義一個計算圖,只需要定義好各個節點以及節點的輸入輸出(對應計算圖的邊)。節點代表各種操作,如加法、乘法、卷積運算等等,輸入輸出主要是各種數據(tensor)。下面是一個簡單的計算圖定義方法示例(來自官網):
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)

當然,我們也可以添加更多更復雜的操作(operation)的節點(node)到計算圖(computation graphy)中,如果增加一些卷積網絡節點、全連接網絡節點等等就可以組建一個神經網絡計算圖了。

  • 節點(node)
    計算圖中的每個節點可以有任意多個輸入和任意多個輸出,每個節點描述了一種運算操作(operation, op),節點可以算作運算操作的實例化(instance)。一種運算操作代表了一種類型的抽象運算,比如矩陣乘法貨響亮加法。tensorflow內建了很多種運算操作,如下表所示:
類型 示例
標量運算 Add、Sub、Mul、Div、Exp、Log、Greater、Less、Equal
向量運算 Concat、Slice、Splot、Constant、Rank、Shape、Shuffle
矩陣運算 Matmul、MatrixInverse、MatrixDeterminant
帶狀態的運算 Variable、Assign、AssignAdd
神經網絡組件 SoftMax、Sigmoid、ReLU、Convolution2D、MaxPooling
存儲、恢復 Save、Restore
隊列及同步運算 Enqueue、Dequeue、MutexAcquire、MutexRelease
控制流 Merge、Switch、Enter、Leave、NextIteration

在tensorflow中,也可以通過注冊機制加入新的運算操作或者運算核,這和torch上的注冊機制類似。

  • 會話(session)
    正如我們前面所說,計算圖里描述的計算并沒有真正執行,只是進行了定義和描述,要實際執行我們就需要在會話(session)里被啟動. 這時session才會將計算圖上的節點操作op分發到諸如CPU或GPU之類的設備上, 同時提供執行op的方法. 這些方法執行后,將產生的tensor返回.
    要啟動計算圖,我們收下需要定義一個session對象:
sess = tf.Session()

啟動操作,最簡單的就是調用函數run:

result = sess.run(product)

tensorflow還支持分布式session,將計算圖布置到多個機器上進行計算。由于我這邊不具備該環境,就不介紹這部分內容了。
另外tensorflow還支持交互環境下采用InteractiveSession定義一個交互session,然后所有的操作都默認在該session上運行,可以直接調用Tensor.eval()Operation.run()兩個方法,如:

# Enter an interactive TensorFlow Session.
import tensorflow as tf
sess = tf.InteractiveSession()

x = tf.Variable([1.0, 2.0])
a = tf.constant([3.0, 3.0])

# Initialize 'x' using the run() method of its initializer op.
x.initializer.run()

# Add an op to subtract 'a' from 'x'.  Run it and print the result
sub = tf.sub(x, a)
print(sub.eval())
# ==> [-2. -1.]

# Close the Session when we're done.
sess.close()
  • 數據(tensor)
    TensorFlow程序使用tensor數據結構來代表所有的數據, 計算圖中的節點間傳遞的數據都是tensor. 你可以把TensorFlow tensor看作是一個n維的數組或列表. 一個 tensor包含一個靜態類型rank, 和一個shape。
  • 變量(Variable)
    在tensorflow里有一類數據比較特殊,那就是我們需要在整個計算圖執行過程中需要保存的狀態。比如我們在進行神經網絡訓練時要時刻保存并更新的網絡參數,這時我們就需要用到Varibale來保存這些參數。其實,我們在前面的示例中已經用到了變量的定義了,它的定義關鍵字為Variable,如上面的x = tf.Variable([1.0, 2.0])
  • feed & fetch
    我們都知道,進行機器學習或者神經網絡訓練時,都需要大量的訓練數據。細心的朋友可能注意到,我們前面一直沒講到訓練數據怎么定義,怎么輸入到網絡里。實際上,tensorflow提供了一個feed機制來將tensor直接放置到計算圖的任意節點操作上去。“feed”這個詞用的很形象啊,就像我們在上課學習時,老師拿課本里的各種例子、習題往我們腦子里喂。那么,這個利用這個feed機制我們就可以把訓練數據“喂”到計算圖的輸入中去。一般我們采用placeholder來指定一個feed操作,這個placeholder就像是一個容器一樣來接收訓練數據,然后在最終進行計算時只需要用placehoder里的數據替換計算圖的輸入量就可以了。一個簡單的例子:
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.mul(input1, input2)

with tf.Session() as sess:
  print(sess.run([output], feed_dict={input1:[7.], input2:[2.]}))

采用兩個placeholder操作來定義兩個輸入,在后面的see.run()里采用feed_dict替換成真正的訓練數據,feed_dict里的才是真正的數據。一般情況,placeholder和feed_dict是搭配使用的。
fetch,正如其字面意思,就是取回數據的意思。我們將計算圖部署到session上進行計算后,需要將計算結果取回,這就是一個fetch。下面是取回多個tensor的例子:

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)
with tf.Session() as sess:
  result = sess.run([mul, intermed])
  print result

上面就是tensorflow編程模型的一些基本概念和內容。通過上面的介紹,我們可以用一句話來總結tensorflow的一個工作流程:

那么我們也可以簡單總結出tensorflow編程的一個基本步驟:

  1. 定義數據
  2. 定義計算圖與變量
  3. 定義會話
  4. 進行計算

三. 用tensorflow搭建神經網絡“hello world”

按照我們上一節介紹的tensorflow編程的基本步驟,我們來搭建我們的第一個神經網絡——基于mnist數據集的手寫數字識別,即基于圖片的10分類問題。
此部分可以參考官網教程MNIST For ML Beginners
MNIST是一個簡單的機器視覺數據集,如下圖所示,它有幾萬張28×28像素的手寫數字組成,這些圖片只包含灰度信息,我們的任務就是對這些手寫數字進行分類,轉成0~9一共10類。

1.定義數據
在神經網絡里我們需要定義的數據就是輸入訓練/測試數據,而變量用來存儲網絡模型里的各種參數。如:

# 輸入數據(包括訓練數據和測試數據)
x = tf.placeholder( tf.float32, [None, 784] ) 
y_ = tf.placeholder( tf.float32, [None, 10] ) 

這里我們把圖片的2828個像素展開成一維列向量(2828-784)
2.定義計算圖與變量
對于神經網絡來說,涉及到的操作主要有三部分:網絡模型定義,損失函數定義、訓練/優化方法定義。那么我們的計算圖基本也由這三部分的定義組成。(當然還可能包括其它部分,如輸入數據初始化操作,網絡參數初始化等等,這里我們不討論)

  • 網絡模型定義
    這里我們定義一個最簡單的單層全連接網絡,計算公式為:y=Wx+b,然后利用softmax來計算預測概率,預測概率最大的對應預測的分類。我需要定義兩個變量來保存網絡參數Wb的狀態。
W = tf.Variable( tf.zeros([784,10]) )   
b = tf.Variable( tf.zeros([10]) )
y = tf.nn.softmax( tf.matmul(x,W) + b )
  • 損失函數定義
    采用cross-entropy作為損失函數,它的公式為:$H_{y'}\left(y\right)=-\underset{i}{{\textstyle \sum}}y'{i}\log\left(y{i}\right)$。(才發現簡書竟然不支持Latex,尷尬。。。)
cross_entropy = tf.reduce_mean( -tf.reduce_sum( y_*tf.log(y), reduction_indices=[1] ) )
  • 訓練/優化方法定義
    神經網絡常采用SGD(Stochastic Gradient Descent)進行網絡的優化訓練。tensorflow會自動根據前面定義的計算圖進行forward和backward計算并更新參數。
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

3.定義會話
按照前面的方法,定義一個session即可。但是還要記住對所有的變量進行全局初始化。

sess = tf.InteractiveSession()
tf.global_variables_initializer().run() #由于是InteractiveSession可以直接run

或者

sess = tf.Session()
init = tf.global_variables_initializer()
sess.run()

4.進行計算
對于神經網絡來說,就是要開始迭代進行訓練和評估,降低損失函數。

# training
for i in range(10000):
        batch_xs, batch_ys = mnist.train.next_batch(100)
        train_step.run( {x:batch_xs, y_:batch_ys} ) #InteractiveSession
#       sess.run(train_step, feed_dict={x:batch_xs, y_:batch_ys}) #非InteractiveSession
# eval
correct_prediction = tf.equal( tf.argmax(y,1), tf.argmax(y_,1) )
accuracy = tf.reduce_mean( tf.cast(correct_prediction, tf.float32) )
print(accuracy.eval( {x:mnist.test.images, y_:mnist.test.labels} ))  #InteractiveSession
print(sess.run(accuracy, feed_dict={x:mnist.test.images, y_:mnist.test.labels})#非InteractiveSession

以上就是整個神經網絡的搭建過程。這里只采用的單層全連接網絡,但是準確率依然達到了92%左右,如果我們采用卷積神經網絡等更復雜的網絡,可以將準確率提高到99%。
以上只是搭建一個神經網絡的基本框架,當然實際中還是數據預處理、參數初始化、超參數設置等問題,這些就需要在實際使用過程中慢慢學習了。
以下是該網絡的全部代碼:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/",one_hot=True)

x = tf.placeholder( tf.float32, [None, 784] )
y_ = tf.placeholder( tf.float32, [None, 10] )

W = tf.Variable( tf.zeros([784,10]) )
b = tf.Variable( tf.zeros([10]) )
y = tf.nn.softmax( tf.matmul(x,W) + b )

cross_entropy = tf.reduce_mean( -tf.reduce_sum( y_*tf.log(y), reduction_indices=[1] ) )

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

session = tf.InteractiveSession()
tf.global_variables_initializer().run()

for i in range(1000):
        batch_xs, batch_ys = mnist.train.next_batch(100)
        train_step.run( {x:batch_xs, y_:batch_ys} )
 #       print(i)

correct_prediction = tf.equal( tf.argmax(y,1), tf.argmax(y_,1) )
accuracy = tf.reduce_mean( tf.cast(correct_prediction, tf.float32) )
print(accuracy.eval( {x:mnist.test.images, y_:mnist.test.labels} )) 

大家也可以在tensorflow.examples.tutorials下找到官方的示例代碼,或者我本人的github上查看

<div align = center>-END-</div>


<u>版權所有,轉載請注明出處</u>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,011評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,323評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,874評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,095評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,605評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,551評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,720評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,961評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,330評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,690評論 2 370

推薦閱讀更多精彩內容

  • 這算什么事?我是一退再退而他是步步為營。經過了那么多的事情,我自己內心相比平靜了許多,今年這一年來發生的事情讓我...
    我說故事你喝酒閱讀 289評論 0 0
  • 哈哈,想起來03年也是有故事的。當時考研,因為非典不用去面試,改電話面試,信號也不太好,隨便聊幾句就過了。[偷笑]...
    南北的海閱讀 212評論 0 0
  • 前言 相信不少人看過《荒野求生》,感嘆于貝爺強大的求生能力之時偶爾會幻想下如果自己在荒無人煙的地方要如何生存,雖然...
    onlinew閱讀 578評論 0 3
  • 昨天父親節,也想過給父親寫封信,想到信,就想到上學時跟父親的一封封通信,父親的字是圓圓的,小小的,人家說字如其人,...
    冠世墨玉yanzi閱讀 164評論 1 1