TensorFlow框架(1)之Computational Graph詳解

1. Getting Start

1.1 import

  TensorFlow應用程序須要引入編程架包,才能訪問TensorFlow的類、方法和符號。以下所示的方法:node

import tensorflow as tf編程

2. Tensor

  TensorFlow用Tensor這種數據結構來表示全部的數據。能夠把一個Tensor想象成一個n維的數組或列表。Tensor有一個靜態的類型和動態的維數。Tensor能夠在圖中的節點之間流通。數組

2.1 秩(Rank)

  Tensor對象由原始數據組成的多維的數組,Tensor的rank(秩)實際上是表示數組的維數,以下所示的tensor例子:session

Rank數據結構

數學實例函數

Python 例子oop

0性能

常量 (只有大小)優化

s = 483ui

1

向量(大小和方向)

v = [1.1, 2.2, 3.3]

2

矩陣(數據表)

m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

3

3階張量 (數據立體)

t = [[[2], [4], [6]], [[8], [10], [12]], [[14], [16], [18]]]

n

n (本身想一想看)

2.2 形狀(Shape)

  TensorFlow爲了描述Tensor每一維的長度,至關於描述每一維數組的長度,因此定義了Shape概念。其能夠描述Tensor的維數,又能夠描述每一維的長度。

Rank

Shape

Dimension number

Example

0

[]

0-D

一個常量.

1

[D0]

1-D

[5]:表示一個向量有5個元素

2

[D0, D1]

2-D

[3, 4]:表示一個矩陣,共有3*4個元素

3

[D0, D1, D2]

3-D

[2, 4, 3]:總共有2*4*3個元素

n

[D0, D1, D2,… DN-1]

n-D

….

2.3 類型(Data type)

  除了維度,Tensor有一個數據類型屬性,你能夠爲一個張量指定下列數據類型中的任意一個類型,可是一個Tensor全部元素的類型必須相同。

數據類型

Python 類型

描述

DT_FLOAT

tf.float32

32 位浮點數.

DT_DOUBLE

tf.float64

64 位浮點數.

DT_INT64

tf.int64

64 位有符號整型.

DT_INT32

tf.int32

32 位有符號整型.

DT_INT16

tf.int16

16 位有符號整型.

DT_INT8

tf.int8

8 位有符號整型.

DT_UINT8

tf.uint8

8 位無符號整型.

DT_STRING

tf.string

可變長度的字節數組.每個張量元素都是一個字節數組.

DT_BOOL

tf.bool

布爾型.

DT_COMPLEX64

tf.complex64

由兩個32位浮點數組成的複數:實數和虛數.

DT_QINT32

tf.qint32

用於量化Ops32位有符號整型.

DT_QINT8

tf.qint8

用於量化Ops8位有符號整型.

DT_QUINT8

tf.quint8

用於量化Ops8位無符號整型.

 

3. Computational graph

3.1 定義

  Computational graph 是由一系列邊(Tensor)和節點(operation)組成的數據流圖。每一個節點都是一種操做,其有0個或多個Tensor做爲輸入邊,且每一個節點都會產生0個或多個Tensor做爲輸出邊。即節點是將多條輸入邊做爲操做的數據,而後經過操做產生新的數據。能夠將這種操做理解爲模型,或一個函數,如加減乘除等操做。

  簡單地說,能夠將Computational graph理解爲UML的活動圖,活動圖和Computational graph都是一種動態圖形。TensorFlow的節點(操做)相似活動圖的節點(動做),TensorFlow每一個節點都有輸入(Tensor),能夠將用戶建立的起始Tensor看作是活動圖的起始節點,而TensorFlow最終產生的Tensor看作是活動圖的終止節點,如圖 31所示。

 

圖 31

  圖 31所示,常量3和常量4.5兩個起始Tensor經過add操做後產生了一個新Tensor(值7.5);接着新Tensor(值7.5)和常量3經multi操做後產生一個新Tensor(值22.5),由於22.5是TensorFlow最後產生的Tensor,因此其是終止節點。

3.2 Session

  TensorFlow經過一個對象(Session)來管理Computational graph 節點動態變換。因爲Tensor是一種數據結構,爲了獲取Tensor存儲的數據,須要手動調用Session對象的run方法得到。

  實現一個TensorFlow應用程序,用戶須要進行兩個步驟:

  1) 創建計算圖(Building the computational graph

    Computational Graph創建實際上是創建節點和邊的一些依賴關係,這個過程是創建一種靜態結構。

  2) 執行計算圖(Running the computational graph

    Computational Graph執行其實就是調用session.run()方法。因爲Computational Graph是有邊和節點組成,因此能夠向run方法傳遞的兩種參數:

  • 邊( Tensor ):若傳遞的是 Tensor 對象,則是獲取 Tensor 對象的數據;
  • 節點:若傳遞的是節點,則會先獲取節點返回的 Tensor 對象,而後再獲取 Tensor 對象的數據。

  綜上所述執行Computational Graph實際上是獲取Tensor的數據。在執行Tensor對象數據時,會根據節點的依賴關係進行計算,直至初始節點。

以下創建兩個TensorFlow節點,節點的類型是constant,而後經過add操做後產生一個新節點,以下所示:

##1.創建computational graph

node1 = tf.constant(3., tf.float32)

node2 = tf.constant(4.5)

tensor = tf.add(node1, node2)

 

print(node1)

print(node2)

 

##2.執行computational graph

session = tf.Session()

print(session.run(node1))

print(session.run(node2))

print(session.run(tensor))

輸出:

Tensor("Const:0", shape=(), dtype=float32)

Tensor("Const_1:0", shape=(), dtype=float32)

3.0

4.5

7.5

圖 32

注意:

  • 在執行 computational graph 以前, TensorFlow 節點是一種靜態結構,因此輸出的並非 3.0 4.0 ,而是 tensor 對象;
  • 在執行 computational graph 以後,才輸出了節點的值,即爲了讓某個節點從初始節點開始變換,須要經過 Session 對象的 run 方法手動變換。

3.3 InteractiveSession

  文檔中的 Python 示例使用一個會話 Session 來 啓動圖, 並調用 Session.run() 方法執行操做.爲了便於使用諸如 IPython 之類的 Python 交互環境, 可使用 InteractiveSession 代替 Session 類, 使用 Tensor.eval() 和 Operation.run() 方法代替 Session.run(). 這樣能夠避免使用一個變量來持有會話.

# 進入一個交互式 TensorFlow 會話.

import tensorflow as tf

sess = tf.InteractiveSession()

 

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

a = tf.constant([3.0, 3.0])

 

# 使用初始化器 initializer op run() 方法初始化 'x'

x.initializer.run()

 

# 增長一個減法 sub op, 'x' 減去 'a'. 運行減法 op, 輸出結果

sub = tf.sub(x, a)

print sub.eval()

# ==> [-2. -1.]

4. 起始節點

  目前瞭解的,TensorFlow有三種類型的起始節點:constant(常量)、placeholder(佔位符)、Variable(變量)。

4.1 常量 (constant)

  TensorFlow的常量節點是經過constant方法建立,其是Computational Graph中的起始節點,在圖中以一個圓點表示,如圖 32所示。

以下述程序中所示,直接建立,但建立的節點不會開始執行,須要由Session對象的run方法開始啓動。

tensor1 = tf.constant(3., tf.float32)

print(tensor1)

 

tensor2 = tf.constant([1, 2, 3, 4, 5, 6, 7])

print(tensor2)

 

tensor3 = tf.constant(-1.0, shape=[2, 3])

print(tensor3)

 

session = tf.Session()

print(session.run(tensor1))

print(session.run(tensor2))

print(session.run(tensor3))

輸出:

Tensor("Const:0", shape=(), dtype=float32)

Tensor("Const_1:0", shape=(7,), dtype=int32)

Tensor("Const_2:0", shape=(2, 3), dtype=float32)

3.0

[1 2 3 4 5 6 7]

[[-1. -1. -1.]

[-1. -1. -1.]]

4.2 佔位符 (placeholder)

  TensorFlow的placeholder節點是由placeholder方法建立,其也是一種常量,可是由用戶在調用run方法是傳遞的,也能夠將placeholder理解爲一種形參。即其不像constant那樣直接可使用,須要用戶傳遞常數值。

以下所示在執行node3:

import tensorflow as tf

 

node1 = tf.placeholder(tf.float32)

node2 = tf.placeholder(tf.float32)

tensor = tf.add(node1, node2)

 

print(node1)

print(node2)

 

session = tf.Session()

print(session.run(tensor, {node1:3,node2:4} ))

輸出:

Tensor("Placeholder:0", dtype=float32)

Tensor("Placeholder_1:0", dtype=float32)

7.0

注意:

    因爲在執行node3節點時,須要node1和node2做爲輸入節點,因此此時須要傳遞"實參",即3和4.

圖 41

4.3 變量 (Variable)

  TensorFlow的Variable節點是經過Variable方法建立,而且須要傳遞初始值。常量在執行過程當中沒法修改值,變量能夠在執行過程修改其值。可是TensorFlow的變量在建立以後須要再進行手動初始化操做,而TensorFlow常量在建立時就已進行了初始化,無需再進行手動初始化。

以下示例,建立兩個變量,分別初始化爲0.3和-0.3,而後傳入一個向量值,最後計算出一個新的向量:

from __future__ import print_function

import tensorflow as tf

 

w = tf.Variable([.3], tf.float32)

b = tf.Variable([-.3], tf.float32)

x = tf.placeholder(tf.float32)

 

linear = w * x + b

 

session = tf.Session()

init = tf.global_variables_initializer()

session.run(init)

 

print(session.run(linear, {x: [1, 2, 3, 4]}))

輸出:

[ 0. 0.30000001 0.60000002 0.90000004]

圖 42

從W展開細節看,變量其實只是一個命名空間,其內部由一系列的節點和邊組成。同時有一個常量節點,即初始值節點。

5. 模型評估

  模型評估是指比較指望值和模型產生值之間的差別,若差別越大,則性能越差;差別越小,性能越好。模型評估有不少種方法,如均分偏差或交差熵。

以下以經常使用的"均分偏差"法舉例說明,其等式爲:

Y爲指望向量,X爲輸入向量,f(X)爲計算向量,以下所示:

from __future__ import print_function

import tensorflow as tf

#1. 構建計算流圖

w = tf.Variable([.3], tf.float32)

b = tf.Variable([-.3], tf.float32)

x = tf.placeholder(tf.float32)

y = tf.placeholder(tf.float32) #指望向量

linear_model = w * x + b

 

squared_deltas = tf.square(linear_model - y) #對兩個向量的每一個元素取差並平方,最後得出一個新的向量

loss = tf.reduce_sum(squared_deltas) #對向量取總和

 

#2. 執行計算流圖

session = tf.Session()

init = tf.global_variables_initializer()

session.run(init)

 

print(session.run(loss, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]}))

輸出:

          23.66

注意:

loss的值是依賴W、B和Y三個向量的值,因此計算loss Tensor會根據依賴關係獲取W、B和Y三個Tensor的值,其計算流程圖如圖 51所示:

圖 51

6. 優化

  優化是指減小指望值與模型產生值之間的差別,即減小均分偏差或交差熵的計算結果,如減小上述的loss變量值。

6.1 手動優化

  咱們能夠經過修改上述的w和b的變量值,來手動優化上述的模型。因爲TensorFlow的變量是經過tf.Variable方法建立,而從新賦值是經過tf.assign方法來實現。注意修改變量的動做須要執行Session.run方法來開始執行。

好比能夠修改w=-1,b=1參數來優化模型,以下

from __future__ import print_function

import tensorflow as tf

 

w = tf.Variable([.3], tf.float32)

b = tf.Variable([-.3], tf.float32)

x = tf.placeholder(tf.float32)

y = tf.placeholder(tf.float32 ")

linear_model = w * x + b

 

squared_deltas = tf.square(linear_model - y)

loss = tf.reduce_sum(squared_deltas)

 

session = tf.Session()

init = tf.global_variables_initializer()

session.run(init)

 

#1.變量wb初始值爲3-3時,計算loss

print(session.run(loss, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]}))

 

#2.重置變量wb值爲-11時,再計算loss

fixw = tf.assign(w,[-1.])

fixb = tf.assign(b,[1.])

session.run(fixw)

session.run(fixb)

print(session.run(loss, {x:[1,2,3,4],y:[0,-1,-2,-3]}))

輸出:

23.66

0.0

注意:

    loss的值是依賴W、B和Y三個向量的值來計算,即每次計算loss都須要上述三個變量的值進行計算。因爲經過調用Session.run()方法來執行某個節點(Computational graph的節點爲操做)時,會自動根據節點先後依賴關係,自動從初始節點開始計算到該節點。在第一次執行session.run(loss)時,W和B的值是3和-3;第二次執行session.run(loss)時,W和B的值被修改成-1和1後。因此session.run(loss)時會自動根據W和B的不一樣進行計算。

 

圖 61

6.2 自動優化

  上述經過手動調整變量w和b的值來改善模型的執行性能,雖然也行的通,可是很是單調且工做量太大。因此TensorFlow提供一些優化器(optimizers)來提升用戶的工做效率,能夠自動完成優化,便可以自動更新相關變量的值。

以下所示,以最簡單的優化器gradient descent爲例,其能夠根據執行loss值逐漸修改每一個變量值,:

import numpy as np

import tensorflow as tf

w = tf.Variable([.3], tf.float32)

b = tf.Variable([-.3], tf.float32)

x = tf.placeholder(tf.float32)

linear_model = w * x + b

y = tf.placeholder(tf.float32)

 

squared_deltas = tf.square(linear_model - y)

loss = tf.reduce_sum(squared_deltas)

 

#1. optimizer

optimizer = tf.train.GradientDescentOptimizer(0.01)

train = optimizer.minimize(loss)

 

#2. training loop

init = tf.global_variables_initializer()

session = tf.Session()

session.run(init)

 

for i in range(1000):

session.run(train, {x:[1,2,3,4], y:[0, -1, -2, -3]})

 

#3. evaluate training accuracy

curr_w, curr_b, curr_loss = session.run([w,b,loss], {x:[1, 2, 3, 4], y:[0, -1, -2, -3]})

print("w:%s b:%s loss:%s"%(curr_w,curr_b,curr_loss))

輸出:

w:[-0.9999969] b:[ 0.99999082] loss:5.69997e-11

注意:

  1) optimizer :建立一個優化器,並指定優化的方向;優化器的優化過程是:對於方程中的權值( w )和偏置( b )對跟進 loss 值進行調整, v 是泛指 w b 參數,則每趟優化過程都會按以下方程更改 w b 的值:

則dV是參數調整數幅度,如若v是權值w,則

  2) training :執行優化器,在執行過程當中會不斷更新涉及的變量,即會更新 W B 兩個 Tensor 值;
  3) evaluate W B 在優化前就有初始值;在優化後會更新兩個值;因此再執行 loss 時,會根據 W B Y 三個 Tensor 值來計算。

如圖 62所示是產生的Computational graph圖變換:

圖 62

圖中帶有箭頭的邊緣是指依賴,如節點b有一個指向tain_min節點,代表b的值依賴tain_min節點。

相關文章
相關標籤/搜索