lesson2 : Tensorflow 入門(mén)

2.1 Tensorflow的計(jì)算模型——計(jì)算圖

??根據(jù)lesson1中所講,Tensorflow實(shí)際原理是張量的流動(dòng),講述輸入的多維數(shù)組(張量)通過(guò)不同節(jié)點(diǎn)進(jìn)行不同的運(yùn)算進(jìn)行轉(zhuǎn)化的一個(gè)過(guò)程,Tensorflow的每一個(gè)計(jì)算都是計(jì)算圖的一個(gè)節(jié)點(diǎn),涉及到一次張量的轉(zhuǎn)化。多個(gè)節(jié)點(diǎn)構(gòu)成一個(gè)神經(jīng)元。Tensorflow如果不定義計(jì)算圖,會(huì)自動(dòng)生成一個(gè)默認(rèn)的計(jì)算圖,并將定義的計(jì)算全部加入默認(rèn)圖。

??如果說(shuō)類比的話,計(jì)算圖就像是我們?cè)诿嫦驅(qū)ο缶幊汤锏念悾聪率龃a可以理解),在一個(gè)計(jì)算圖里,每個(gè)數(shù)據(jù)都像是類中的變量,每個(gè)計(jì)算節(jié)點(diǎn)都像是一個(gè)成員函數(shù),兩個(gè)圖里的變量名字可以相同但是在指定運(yùn)行不同的圖時(shí),得到結(jié)果根據(jù)各自圖運(yùn)算過(guò)程而定。

??計(jì)算圖有隔離張量和計(jì)算的作用,并對(duì)張量和計(jì)算進(jìn)行管理,例如限定計(jì)算所使用的GPU等,這個(gè)后續(xù)學(xué)到再說(shuō),我現(xiàn)在也不太會(huì)??,而且我前面介紹的安裝是CPU版本。自定義圖的示例代碼如下(python 的縮進(jìn)很重要,不要漏掉):

import tensorflow as tf

g1 = tf.Graph()
with g1.as_default():
      # 在計(jì)算圖g1中定義變量“v”,初始化為0
      v = tf.get_variable("v",initializer=tf.zeros_initializer(shape=[1]))

 g2 = tf.Graph()
with g2.as_default():
      # 在計(jì)算圖g2中定義變量“v”,初始化為1
      v = tf.get_variable("v",initializer=tf.ones_initializer(shape=[1]))

# 在計(jì)算圖g1中讀取變量“v”的值
with tf.Session(graph = g1) as sess:
     tf.initialize_all_variables().run()
     with tf.variable_scope("",reuse=True):
           # 在計(jì)算圖g1中,“v”為0,所以下述語(yǔ)句應(yīng)該輸出0
           print(sets.run(tf.get_variable("v")))

# 在計(jì)算圖g2中讀取變量“v”的值
with tf.Session(graph = g2) as sess:
     tf.initialize_all_variables().run()
     with tf.variable_scope("",reuse=True):
           # 在計(jì)算圖g1中,“v”為1,所以下述語(yǔ)句應(yīng)該輸出1
           print(sets.run(tf.get_variable("v")))

??使用圖限定計(jì)算用的GPU

g = tf.Graph()
# 指定計(jì)算運(yùn)行的設(shè)備
with g.device('/gpu:0'):
        result = a + b



2.2 Tensorflow的數(shù)據(jù)模型——張量

2.2.1 概念

??張量是Tensorflow管理數(shù)據(jù)的形式,可以簡(jiǎn)單理解為多維數(shù)組,不過(guò)Tensor的存儲(chǔ)和Numpy的多維數(shù)組有所不同,Numpy簡(jiǎn)介參見(jiàn)這里,觀察如下代碼:

import tensorflow as tf

#. td.constant 是一個(gè)計(jì)算,個(gè)人感覺(jué)和申請(qǐng)const變量差不多,不過(guò)結(jié)果是一個(gè)張量,存儲(chǔ)在變量a中
a = tf.constant([1.0,2.0],name="a")
b = tf.constant([2.0,3.0],name="b")
c = tf.constant([2.0,3.0])
d = tf.constant([2.0,3.0])
result = tf.add(a,b,name="add")

print(result) # output : Tensor("add:0",shape=(2,),dtype=float32)
print(a)  # output: Tensor("a:0", shape=(2,), dtype=float32)
print(c) # output: Tensor("Const:0", shape=(2,), dtype=float32)
print(d) # output: Tensor("Const_1:0", shape=(2,), dtype=float32)

sess = tf.Session()
sess.run(result) # output : array([3., 5.], dtype=float32)
less.run(a) # output : array([1., 2.], dtype=float32)

??從上述代碼可以發(fā)現(xiàn)張量中主要保存了三個(gè)屬性:名字(name),維度(shape)和類型(type),其中名字遵循“node:src_output”,比如result為add計(jì)算節(jié)點(diǎn)的第0個(gè)輸出,所以命名為add:0,因?yàn)橛械挠?jì)算節(jié)點(diǎn)并不一定輸出一個(gè)張量,所以src_output為輸出序號(hào),node為計(jì)算節(jié)點(diǎn)名稱,tf.constant()和tf.add()均為計(jì)算,所以a為a:0,其中節(jié)點(diǎn)的名稱可以由我們定義,如果我們不自己定義,Tensorflow有自己的默認(rèn)命名,比如c的"Const:0" 以及d的“Const_1:0”

??所以,我感覺(jué)Tensor不能單純的理解為多維數(shù)組,它包含了他是從哪個(gè)計(jì)算節(jié)點(diǎn)計(jì)算而來(lái)的,以及它的大小,我們可以理解為T(mén)ensorflow分為兩部分工作,第一部分工作是定義計(jì)算圖,也就是定義張量是如何流動(dòng)的,但是每一步運(yùn)算都并沒(méi)有實(shí)質(zhì)上的運(yùn)行,張量就是這樣而存在的。第二部分是對(duì)計(jì)算圖進(jìn)行實(shí)質(zhì)上的通過(guò)CPU或者GPU進(jìn)行計(jì)算,這就需要運(yùn)行Session,Session的使用會(huì)在后面小節(jié)具體描述,從上述代碼可以看到運(yùn)行sess.run()就會(huì)輸出運(yùn)算結(jié)果


2.2.2 張量的使用

??觀察下列代碼的運(yùn)行

import tensorflow as tf

a = tf.constant([1,2],name="a")
b = tf.constant([2.0,3.0],name="b")
c =  tf.constant([1,2],name="c",dtype=tf.float32)

result = a + b # Get ERROR bellow
# ValueError: Tensor conversion requested dtype int32 for Tensor with dtype float32: 'Tensor("b:0", shape=(2,), dtype=float32)'

result = b+c # no error

??對(duì)于Tensorflow,如果不聲明類型dtype,那么沒(méi)有小數(shù)點(diǎn)默認(rèn)類型為int32,有小數(shù)點(diǎn)默認(rèn)為float32,這個(gè)和我們編程不一樣,不存在強(qiáng)制類型轉(zhuǎn)換,需要注意。Tensorflow所支持的數(shù)據(jù)類型:

  • 浮點(diǎn)數(shù)(tf.float32、tf.float64)
  • 整數(shù)(tf.int8、tf.int16、tf.int32、tf.int64、 tf.unit8)
  • 布爾型(tf.bool)
  • 復(fù)數(shù)(tf.complex64、tf.complex128)
import tensorflow as tf

a = tf.constant([1.0,2.0],name="a")
b = tf.constant([2.0,3.0],name="b")

result = a + b; # 和tf.add()效果相同,根據(jù)需要選擇,使用tf.add()可以自定義節(jié)點(diǎn)的其他屬性,比如計(jì)算節(jié)點(diǎn)的名字

# 和上述代碼效果一樣,但可讀性差
result_1 = tf.constant([1.0,2.0],name="a") + 
           tf.constant([2.0,3.0],name="b")

??從上述代碼可以看到,中間變量a和b只是為了存儲(chǔ)中間張量,可以不寫(xiě),但是為了可讀性應(yīng)該使用類似的中間變量增加代碼可讀性,優(yōu)點(diǎn)如下:

  • 對(duì)于python:由于python的靈活的類型轉(zhuǎn)化無(wú)需聲明數(shù)據(jù)類型,設(shè)置必要中間變量方便調(diào)試
  • 對(duì)于Tensorflow: 由于有的網(wǎng)絡(luò)巨大,在設(shè)計(jì)計(jì)算圖時(shí)需要考慮張量的大小問(wèn)題,設(shè)置中間變量可以方便的獲取中間步驟張量的大小,省去人為計(jì)算



2.3 Tensorflow運(yùn)行模型——會(huì)話

??前面兩節(jié)介紹了Tensorflow如何組織數(shù)據(jù)和運(yùn)算,可以認(rèn)為是計(jì)算圖的設(shè)計(jì)部分,而會(huì)話(session)是對(duì)前面兩個(gè)部分設(shè)計(jì)結(jié)果的執(zhí)行。會(huì)話可以管理Tensorflow程序運(yùn)行時(shí)的所有資源。計(jì)算完成后需要關(guān)閉繪畫(huà)幫助系統(tǒng)回收資源,可以理解為一個(gè)指針,這個(gè)指針指向計(jì)算圖的某個(gè)節(jié)點(diǎn),該節(jié)點(diǎn)就被激活并執(zhí)行計(jì)算,當(dāng)所有運(yùn)算執(zhí)行完,關(guān)閉會(huì)話,類似于指針的free。

??Tensorflow的會(huì)話的使用一般有兩種,如下所示,所有計(jì)算完成后關(guān)閉資源,但是這種方法有一個(gè)問(wèn)題就是當(dāng)在session.close()執(zhí)行之前,程序出現(xiàn)異常而退出,那么會(huì)造成資源泄漏。不過(guò)我喜歡。。??

# 創(chuàng)建一個(gè)會(huì)話
sess = tf.Session()
# 使用這個(gè)會(huì)話得到關(guān)心的運(yùn)算結(jié)果,比如上節(jié)使用的sess.run(result)
session.run(...)
#關(guān)閉會(huì)話釋放資源
session.close()

??還有一種寫(xiě)法如下,不會(huì)泄漏資源,但是我感覺(jué)寫(xiě)起來(lái)很麻煩

# 創(chuàng)建一個(gè)會(huì)話,通過(guò)Python的上下文管理器來(lái)管理這個(gè)會(huì)話。
with tf.Session() as session:
     # 使用創(chuàng)建的會(huì)話計(jì)算關(guān)心的結(jié)果
     session.run(...)
# 不需要調(diào)用Session.close()函數(shù)
# 當(dāng)上下文退出后會(huì)話關(guān)閉并進(jìn)行資源釋放

??以上兩種介紹的是Session的簡(jiǎn)單的也是常用的寫(xiě)法,其實(shí)會(huì)話的使用很靈活,主要表現(xiàn)在默認(rèn)會(huì)話的設(shè)置和使用上。Session和計(jì)算圖Graph類似存在默認(rèn)會(huì)話,在默認(rèn)的會(huì)話下,無(wú)需調(diào)用sess.run(),使用方法如下所示

sess = tf.Session()
#設(shè)置為默認(rèn)會(huì)話
with sess.as_default():
     print(result.eval())

??同樣效果的等價(jià)寫(xiě)法還有如下兩種:

sess = tf.Session()

# 如下兩行等價(jià),均未設(shè)置默認(rèn)會(huì)話
print(sess.run(result))
print(result.eval(session=sess))

??如果Session設(shè)置為每一步計(jì)算節(jié)點(diǎn)的默認(rèn)會(huì)話,僅需調(diào)用運(yùn)算節(jié)點(diǎn)的eval()成員函數(shù)即可得到運(yùn)算結(jié)果,Tensorflow提供一個(gè)將自動(dòng)生成的會(huì)話直接注冊(cè)為默認(rèn)會(huì)話的函數(shù),作用于全局,用法如下:

# 生成一個(gè)注冊(cè)為默認(rèn)會(huì)話的會(huì)話sess
sess = tf.InteractiveSession()
print(result.eval())
sess.close()



??至此,Tensorflow的基本思想已經(jīng)簡(jiǎn)單介紹完畢,下一部分將根據(jù)一些網(wǎng)絡(luò)的設(shè)計(jì)和使用展開(kāi)對(duì)Tensorflow展開(kāi)進(jìn)階介紹

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • TF API數(shù)學(xué)計(jì)算tf...... :math(1)剛開(kāi)始先給一個(gè)運(yùn)行實(shí)例。tf是基于圖(Graph)的計(jì)算系統(tǒng)...
    MachineLP閱讀 4,053評(píng)論 0 1
  • 很多時(shí)候,急切會(huì)讓我們忘記忽略許多,就是這樣,一念之間的決定現(xiàn)在的結(jié)果。
    妖樹(shù)閱讀 307評(píng)論 0 0
  • 雨下著下著 停了 再也找不回曾經(jīng)的那個(gè)你
    太平洋深海的魚(yú)閱讀 299評(píng)論 0 1
  • 從今天起,做自己的英雄。 有些事,一旦養(yǎng)成習(xí)慣是很難改變的。就好比你習(xí)慣了有人每天跟你說(shuō)晚安,恍然間他不在問(wèn)候了,...
    山頂洞人小茶閱讀 289評(píng)論 0 0
  • 去浙江圖書(shū)館了,還不錯(cuò) 吃了好多零食 吃了韓國(guó)料理,其實(shí),我有點(diǎn)介意每次都我付錢(qián)。。
    英子_b3c9閱讀 198評(píng)論 0 0

友情鏈接更多精彩內(nèi)容