tensorflow入門教程02-tensorflow基本概念(數據流圖,張量,tensorboard)


TensorFlow程序一般分爲兩個階段。

  • 第一階段:定義計算圖中所有的計算,張量計算只是構造了一個靜態 圖;
  • 第二階段:執行計算,使用session.run纔開始對圖開始有向計算。

1 計算圖————TensorFlow的計算模型

1.1 計算圖的概念

TensorFlow這個單詞由兩部分組成:tensor代表張量,是數據模型;flow代表流,是計算模型。下面就引出Flow的具體內涵。

流動的事務具有有向性,計算圖就是一個具有 “每一個節點都是計算圖上的一個節點,而節點之間的邊描述了計算之間的依賴關係” 性質的有向圖。(計算圖和數據結構這門課程中的有向圖具有高度的相似性,現在可以回憶一下這段記憶)

計算圖由邊(表示依賴關係,又被叫做“張量”)和節點(又被叫做“神經元”、“算子”)組成。如果tensorflow程序只定義了一個Graph,那其內部包含了所有的op和tensor

1.2 計算圖的使用

在TensorFlow程序中,系統會自動維護一個默認的計算圖,通過tf.get_default_graph()函數可以獲取這個默認的計算圖。

import tensorflow as tf
a = tf.constant([1.0, 2.0], name='a')
b = tf.constant([1.0, 2.0], name='b')
result = a + b

aa
通過a.graph屬性可以查看這個張量所屬的計算圖。因爲沒有特意指定,所以這個計算圖應該等於當前默認的計算圖
print(a.graph is tf.get_default_graph())

import tensorflow as tf
a = tf.constant([1.0, 2.0], name='a')
b = tf.constant([1.0, 2.0], name='b')
result = a + b
#任何一個圖中張量的graph都在同一個默認圖中
print(a.graph is tf.get_default_graph())
#True
print(result.graph is tf.get_default_graph())
#True

Tensorflow通過計算圖把張量和算子等組合在一起,而在很多TensorFlow程序中,看不到Graph,這是爲何?這是因爲TensorFlow有個默認缺省的graph
(即Graph.as_default()),我們添加的tensor和op等都會自動添加到這個缺省計算圖中,如果沒有特別要求,使用這個默認缺省的Graph即可。當然,如果需要一些更復雜的計算,比如需要創建兩個相互之間沒有交互的模型,就需要自定義計算圖。
除了使用默認的計算圖,TensorFlow支持通過tf.Graph函數來生成新的計算圖。TensorFlow中的計算圖不僅可以隔絕張量和計算,它還提供了管理張量和計算的機制,不同計算圖上的張量和運算不會共享。
以下代碼示意瞭如何通過在不同的計算圖上定義和使用變量。

import tensorflow as tf

g1 = tf.Graph()
with g1.as_default():
    v = tf.get_variable('v', shape=[1], initializer=tf.zeros_initializer)

g2 = tf.Graph()
with g2.as_default():
    v = tf.get_variable('v', shape=[1], initializer=tf.ones_initializer)
'''
tf.Graph()沒有實現__enter__()方法,做不到下面那優雅pythonic的寫法。
with tf.Graph() as g2:
    v = tf.get_variable('v', shape=[1], initializer=tf.ones_initializer)
    
這樣寫了就會拋出AttributeError異常

Traceback (most recent call last):
  File "D:/bb/TensorFlow/Untitled1.py", line 7, in <module>
    with tf.Graph() as g2:
AttributeError: __enter__
'''

with tf.Session(graph=g1) as sess:
    tf.global_variables_initializer().run()
    with tf.variable_scope("", reuse=True):
        print(sess.run(tf.get_variable('v')))

with tf.Session(graph=g2) as sess:
    tf.global_variables_initializer().run()
    with tf.variable_scope("", reuse=True):
        print(sess.run(tf.get_variable('v')))


輸出>>>
[0.]
[1.]
注:先不要管代碼是什麼含義,繼續往下看

如果有多個Graph,建議不使用默認的Graph,直接無視或者爲其分配一個句柄,避免發生混亂

import tensorflow as tf

graph1 = tf.Graph()
graph2 = tf.Graph()  # 直接無視默認缺省的Graph
# graph2 = tf.get_default_graph() 爲其分配一個句柄

with graph1.as_default():
    pass

with graph2.as_default():
    pass

2 張量————TensorFlow數據類型

2.1 張量的概念

在TensorFlow的程序中,所有的數據都通過張量(tensor)的形式表示。

張量(tensor)理解爲多維數組(multidimensional array),0階張量是標量(scalar),1階是向量(vector)(即一維數組),2階是二維數組,n階爲n維數組。

TensorFlow的運算結果不是一個數,而是一個張量結構。(運算和運行在tensorflow語境中不同,運算就是用過運算符操作,運行就和會話有關,3.3會提到)

import tensorflow as tf

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

result = tf.add(a, b, name='add')

print(result)

輸出>>>
Tensor("add:0", shape=(2,), dtype=float32)

一個張量保存了三個屬性:名字(name)、維度(shape)和類型(type)

  1. 名字name:一個張量的唯一標識符以及這個張量是如何計算出來的。
    張量的命名形式:“node:src_output”,node爲節點的名稱,src_output表示當前張量來自來自節點的第幾個輸出。
    比如上面的代碼的輸出"add:0"說明張量result是計算節點“add”輸出的第一個結果(編號從0開始)
    張量和計算圖上節點的計算結果是一一對應的。

  2. 維度shape:描述了一個張量的維度信息。
    上面樣例的shape(2,)表示一個一維數組,這個數組的長度是2。

  3. 類型type:每一個張量都有一個唯一的類型,常用的是tf.int32,tf.float32。參與運算的張量需要保持數據類型相同,不然會報錯。
    TensorFlow支持的14種數據類型:

有符號整型

  • tf.int8:8位整數
  • tf.int16:16位整數
  • tf.int32:32位整數
  • tf.int64:64位整數
    無符號整型
  • tf.uint8:8位無符號整數
  • tf.uint16:16位無符號整數
    浮點型
  • tf.float16:16位浮點數
  • tf.float32:32位浮點數
  • tf.float64:64位浮點數
  • tf.double:等同於tf.float64
    字符串型
  • tf.string:字符串
    布爾型
  • tf.bool:布爾型
    複數型
    tf.complex64:64位複數
    tf.complex128:128位複數
    TensorFlow數據類型和Python原生數據類型的關係

TensorFlow接受了Python自己的原生數據類型,例如Python中的布爾值類型,數值數據類型(整數,浮點數)和字符串類型。單一值將轉換爲0維張量(標量),列表值將轉換爲1維張量(向量),列表套列表將被轉換成2維張量(矩陣)

TensorFlow數據類型和Numpy數據類型的關係

你可能已經注意到了Numpy和TensorFlow有很多相似之處。TensorFlow在設計之初就希望能夠與Numpy有着很好的集成效果。Numpy軟件包現在已經成爲數據科學的通用語言。

TensorFlow數據類型很多也是基於Numpy的,事實上,如果你令 np.int32==tf.int32將會返回True.你也可以直接傳遞Numpy數據類型直接給TensorFlow中的ops。

tf.ones([2, 2], np.float32) ==> [[1.0 1.0], [1.0 1.0]]
請記得,我們的好朋友會話tf.Session.run(),要求的輸入對象是一個Tensor但是它的輸出是一個Numpy數組。事實上,在絕大多數場合,你可以同時混合使用TensorFlow類型和Numpy類型。

2.2 張量的使用

張量使用可以歸結爲兩大類。

  1. 第一類對中間計算結果的引用,提升代碼的可讀性

使用張量和不使用張量的對比

import tensorflow as tf

#使用張量記錄

a = tf.constant([1.0, 2.0], name='a')
b = tf.constant([1.0, 2.0], name='b')
result1 = a + b

不使用張量,簡潔但是可讀性降低

result2 = tf.constant([1.0, 2.0], name='a') + tf.constant([1.0, 2.0], name='b')

#jie'guo'xiang't
print(result1)
print(result2)

輸出>>>
Tensor("add:0", shape=(2,), dtype=float32)
Tensor("add_1:0", shape=(2,), dtype=float32)
  1. 第二類情況是計算圖構造完成後,張量可以用來獲取計算結果
    使用tf.Session().run(result)語句可以得到計算結果

3 會話————TensorFlow運行模型

3.1會話的概念

計算圖描述計算
張量是組織數據
會話執行定義好的運算

會話管理TensorFlow程序運行時的所有資源,並在運行結束後釋放所有的資源。

會話機制類似於計算圖機制:
計算圖:在一開始就有一個默認的計算圖存在,並且沒有特別指定,運算會自動加入到這個默認的計算圖中
會話:會要手動創建,張量自動添加。

3.2會話的使用

TensorFlow使用會話模式有兩種方式

1.普通模式

import tensorflow as tf

加入了一個異常處理機制,確保釋放資源

try:
    sess = tf.Session()  # 創建一個會話
    sess.run(...)  # 運行,得到計算結果
except Exception:
    pass
finally:
    sess.close()  # 關閉會話,釋放資源

2.上下文模式
這纔是pythonic的寫法,極力推薦

import tensorflow as tf

with tf.Session as sess:
   sess.run()

運行到這個位置會自動釋放sess的資源,優雅尼克
這是2.2程序的引用,會話的寫法多種多樣,我們應用最優雅、最pythinc的代碼去闡述。

import tensorflow as tf

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

result = tf.add(a, b, name='add')

with tf.Session() as sess:
   # tf.Session.run(),要求的輸入對象是一個Tensor但是它的輸出是一個Numpy數組
   print(sess.run(result))

輸出>>>
[2. 4.]

4 其他基本概念——常量、變量、佔位符

4.1 常量

Python中使用常量很簡單,如a=123,b=‘python’。TensorFlow表示常量稍微麻煩一點,需要使用tf.constant這個類,具體格式如下:

tf.constant(value, dtype=None, shape=None, name="Const", verify_shape=False)

其中各參數說明如下:

  • value : 一個dtype類型(如果指定了)的常量值(列表)。要注意的是,若value是一個列表,那麼列表的長度不能夠超過形狀參數指定的大小(如果指定了)。如果列表長度小於指定的大小,那麼多餘的空間由列表的最後一個元素來填充。
  • dtype : 返回的tensor的類型
  • shape : 返回的tensorflow的形狀
  • name : tensor的名字
  • verify_shape : 布爾值,用於驗證值的形狀。
    示例如下:
import tensorflow as tf

構建計算圖
a = tf.constant('something', name='a')

print(a)

with tf.Session() as sess:  # 創造會話
   result = sess.run(a)  # 在會話中執行張量a
   print(result)


輸出>>>
Tensor("a:0", shape=(2,), dtype=float32)
b'something'

4.2 變量

變量是TensorFlow中的核心概念,創建一個類使用tf.Variable,具體格式如下:

tf.Variable(initial_value=None,trainable=None,collections=None,validate_shape=True,caching_device=None,name=None,variable_def=None,dtype=None,expected_shape=None,import_scope=None,constraint=None,use_resource=None,synchronization=VariableSynchronization.AUTO, aggregation=VariableAggregation.NONE,shape=None)

主要參數說明:

  • initial_value :一個 Tensor類型或者是能夠轉化爲Tensor的python對象類型。它是這個變量的初始值。這個初始值必須指定形狀信息,不然後面的參數validate_shape需要設置爲False。當然,也能夠傳入一個無參數可調用並且返回指定初始值的對象,在這種情況下,dtype必須指定。
  • trainable :如果設置爲True (默認也爲True),這個變量可以被優化器類(optimizer)自動修改Variable的值;如果設置爲False,則說明Variable 只能手工修改,不允許使用優化器類自動修改。
  • collections :圖的collection鍵列表,新的變量被添加到這些collection 中。默認是
  • validate_shape :如果是False的話,就允許變量能夠被一個形狀未知的值初始化,默認是True,表示必須知道形狀。
  • caching_device :可選,描述設備的字符串,表示哪個設備用來爲讀取緩存。默認是變量的device。
  • name :可選,變量的名稱。
  • dtype :如果被設置,初始化的值就會按照這裏的類型來定。

4.2.1.創建變量

1.現在讓我們使用tf.Variable()創建變量,這是最簡單的、最常用的變量創建方法。用的最多的兩個參數initial_value和name

import tensorflow as tf

girl = tf.Variable('安靜宇', name='big')  # 這個name大有作用,後面會講到,需要注意的是,name的值不可以是中文,中文會報錯

god = tf.Variable('安靜宇', name='big')  # 使用tf.Variable()創建的實例,實例名是唯一標識符( Variable()內的參數都可以重複 )

寫作girl = tf.Variable('安靜宇', name='big'),就會覆蓋第一個girl

print('initializer', girl.initializer)
print('initial_value', girl.initial_value)
print('graph', girl.graph)
print('shape', girl.shape)
print('name', girl.name)
print('dtype', girl.dtype)
print('value', girl.value())

'''
輸出>>>
initializer name: "big/Assign"
op: "Assign"
input: "big"
input: "big/initial_value"
attr {
 key: "T"
 value {
   type: DT_STRING
 }
}
attr {
 key: "_class"
 value {
   list {
     s: "loc:@big"
   }
 }
}
attr {
 key: "use_locking"
 value {
   b: true
 }
}
attr {
 key: "validate_shape"
 value {
   b: true
 }
}

initial_value Tensor("big/initial_value:0", shape=(), dtype=string)
graph <tensorflow.python.framework.ops.Graph object at 0x000001DF1B542EF0>
shape ()
name big:0
dtype <dtype: 'string_ref'>
value Tensor("big/read:0", shape=(), dtype=string)

2.除了使用tf.Variable()創建變量,還有一個孿生兄弟,tf.get_variable(),他兩的業務邏輯還是很不一樣的,使用的唯一標識符不一樣,前者使用實例名作爲唯一標誌,後者使用name參數作爲唯一標誌。

具體用法可以參考這篇博客Variable和get_variable的用法以及區別

按照習慣,get開頭的函數都是“查詢”、“獲取”的意思,但是tf.get_variable()是創建變量,get取的是“創建”的意思

4.2.2.初始化變量

tensorflow中,程序存在變量,在使用前必須初始化

初始化變量有兩個方法

一個一個手動初始化
一次性全局初始化
手動初始化就是

ses.run(var1.initializer)
ses.run(var2.initializer)
ses.run(var3.initializer)
一次性全局初始化只要使用一個函數 tf.global_variables_initializer()

init_op = tf.global_variables_initializer()
sess.run(init_op)
貼一個完整代碼

import tensorflow as tf

girl = tf.Variable('aa', name='cute')

god = tf.Variable('aa', name='pretty')

with tf.Session() as sess:
   # 必須先初始化變量才能使用,tf.global_variables_initializer()可以初始化所有的變量
   sess.run(girl.initializer)
   sess.run(god.initializer)
   # 等價於 sess.run(tf.global_variables_initializer())
   print(sess.run(girl).decode())
   print(sess.run(god).decode())

輸出>>>
aa
aa

4.3 placeholder佔位符

在tensorflow中,有一個機制叫做placeholder,首先創建變量但是不進行賦值,在最後sess.run(op,feed_dict={ } )用feed_dict進行賦值操作,

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

5 tensorboard

tensorflow強大功能之一可以將數據整個靜態圖運行之後的過程用圖像方式 展現出來,可以更加直觀分析整個數據流圖。

5.1 簡介

Tensorflow,簡單的說,就是tensor(張量)數據在圖中flow(流動)計算(op)的過程。
官方數據流圖:

在這裏插入圖片描述

5.2 案例

模擬使用幾個數計算獲取結果的圖

import tensorflow as tf
#可以將一組操作定義一個scope 會合併到一個圓方形中。
with tf.name_scope('graph') as scope:
    a = tf.constant(11.8, name='a')  # 這裏定義名字都會顯示在對應快圖中 方便定位
    b = tf.constant(12.8, name='b')
    x= tf.placeholder(dtype=tf.float32,name="x")
    result = tf.add(tf.multiply(a,x) , b)
with tf.Session() as session:
    writer=tf.summary.FileWriter("./graph",session.graph)
    session.run(tf.global_variables_initializer())
    result=session.run(result,feed_dict={x:10})
    print(result)
    writer.close() # 關閉時寫入內存,否則它每隔120s寫入一次

運行完成 後 在當前目錄graph目錄下生成日誌文件 ,使用命令 tensorboard --logdir ./graph

E:\workspace\machinelearn\tensor_base\教程記錄>tensorboard --logdir ./graph
TensorBoard 1.11.0 at http://jiaozi-PC:6006 (Press CTRL+C to quit)

瀏覽器訪問localhost:6006
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章