第七節,TensorFlow編程基礎案例-TensorBoard以及常用函數、共享變量、圖操作(下)


這一節主要來介紹TesorFlow的可視化工具TensorBoard,以及TensorFlow基礎類型定義、函數操作,后面又介紹到了共享變量和圖操作。

一 TesnorBoard可視化操作

TensorFlow提供了可視化操作工具TensorBoard。他可以將訓練過程中的各種數據展示出來,包括標量,圖片,音頻,計算圖,數據分布,直方圖和嵌入式向量。可以通過網頁來觀察模型的結構和訓練過程中各個參數的變化。TensorBoard不會自動把代碼代碼出來,其實它是一個日志展示系統,需要在session中運算圖時,將各種類型的數據匯總並輸出到日志日志文件中。然后啟動TensorBoard服務,讀取這些日志文件,啟動6006端口提供web服務,讓用戶可以在瀏覽器查看數據。

TsensorFlow提供了一下我們常用的API,如下所示:

  • tf.summary.scalar(tags,values,collections=None,name=None):標量數據匯總,輸出protobuf。
  • tf.summary.histogram(tag,values,collections=None,name=None):記錄變量var的直方圖,輸出帶有直方圖的匯總的protobuf。
  • tf.summary.image(tag,tensor,max_images=3,collections=None,name=None):圖像數據匯總,輸出protobuf。
  • tf.summary.merge_all(inputs,collections=None,name=None):合並所有的匯總日志。
  • tf.summary.FileWriter:創建一個SummaryWriter
  • Class SummaryWriter: add_summary(),add_sessionlog(),add_event(),add_graph():將protobuf寫入文件的類。

下面我們通過實例來演示TensorFlow的使用,我們仍然使用線性回歸的模型:

# -*- coding: utf-8 -*-
"""
Created on Wed Apr 18 14:06:16 2018

@author: zy
"""

'''
1 TensorBoard可視化
'''


import tensorflow as tf
import numpy as np
import os
import matplotlib.pyplot as plt

'''
一准備數據
'''

#設定訓練集數據長度
n_train = 100

#生成x數據,[-1,1]之間,均分成n_train個數據
train_x = np.linspace(-1,1,n_train).reshape(n_train,1)

#把x乘以2,在加入(0,0.3)的高斯正太分布
train_y = 2*train_x + np.random.normal(loc=0.0,scale=0.3,size=[n_train,1])

#繪制x,y波形
plt.figure()
plt.plot(train_x,train_y,'ro',label='y=2x')   #o使用圓點標記一個點
plt.legend()
plt.show()

'''
二 搭建模型
'''

'''
前向反饋
'''
#創建占位符
input_x = tf.placeholder(dtype=tf.float32)
input_y = tf.placeholder(dtype=tf.float32)

#模型參數
w = tf.Variable(tf.truncated_normal(shape=[1],mean=0.0,stddev=1),name='w')    #設置正太分布參數  初始化權重
b = tf.Variable(tf.truncated_normal(shape=[1],mean=0.0,stddev=1),name='b')    #設置正太分布參數  初始化偏置

#前向結構
pred = tf.multiply(w,input_x) + b

#將預測值以直方圖形式顯示,給直方圖命名為'pred'
tf.summary.histogram('pred',pred)

'''
反向傳播bp
'''
#定義代價函數  選取二次代價函數
cost = tf.reduce_mean(tf.square(input_y - pred))

#將損失以標量形式顯示 該變量命名為loss_function
tf.summary.scalar('loss_function',cost)


#設置求解器 采用梯度下降法 學習了設置為0.001
train = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(cost)


'''
三 迭代模型
'''
#設置迭代次數
training_epochs = 200
display_step = 20


savedir = './LinearRegression'

with tf.Session() as sess:
    #初始化所有張量
    sess.run(tf.global_variables_initializer())
    
    
    #合並所有的summary
    merged_summary_op = tf.summary.merge_all()
    
    #創建summary_write,用於寫文件
    summary_writer = tf.summary.FileWriter(os.path.join(savedir,'summary_log'),sess.graph)
    
    
    #存放批次值和代價值
    plotdata = {'batch_size':[],'loss':[]}
    
    #開始迭代
    for epoch in range(training_epochs):
        for (x,y) in zip(train_x,train_y):
            #開始執行圖
            sess.run(train,feed_dict={input_x:x,input_y:y})
                                            
        #生成summary
        summary_str = sess.run(merged_summary_op,feed_dict={input_x:x,input_y:y})
        #將summary寫入文件
        summary_writer.add_summary(summary_str,epoch)
        
                
    #輸出最終結果
    print('Finished!')
    print('cost {0}  w {1}   b  {2}'.format(sess.run(cost,feed_dict={input_x:train_x,input_y:train_y}),sess.run(w),sess.run(b)))    

    #預測
    test_x = [2,4,5,7]
    test_y = sess.run(pred,feed_dict={input_x:test_x})
    print('prediction  ',test_y)


    '''
    四 可視化顯示
    '''
    #繪制原數據點,和估計曲線
    plt.figure(figsize=(4.2*2,3.2*1))    
    plt.plot(train_x,train_y,'ro',label='Original data')
    plt.plot(train_x,sess.run(w)*train_x + sess.run(b),label ='Estimate data')
    plt.legend()            
    plt.show()

程序運行后會自動創建文件夾summary_log,並生成如下文件:

 

我們啟動Anaconda Prompt,首先來到summary日志的上級路徑下,這一步是必須的,然后輸入如下命令:

tensorboard --logdir F:\python\LinearRegression\summary_log

接着打開瀏覽器,輸入http://127.0.0.1:6006,這里127.0.0.1是本機地址,6006是端口號。打開后,單擊SCALARS,我們會看到我們在程序中創建的變量loss_function,點擊它,會顯示如下內容:

在左側有個smoothing滾動條,可以用來改變右側標量的曲線,我們還可以勾選上show data download links,然后下載數據。我們點開GRAPHS看一下內部圖結構:

在程序程序中,我們把預測值以直方圖顯示,這里我們可以再HISTOGRAMS中看到:

二 基礎類型定義

1.張量介紹

TensorFlow程序使用tensor數據結構來代表所有的數據,計算圖中,操作間傳遞的數據都是tensor,你可以把TensorFlow tensor看做一個n維的數組或者列表。一個tensor包含一個靜態類型,rank,和一個shape。具體參見Rank, Shape, 和 Type

階(rank)

在TensorFlow系統中,張量的維數來被描述為階.但是張量的階和矩陣的階並不是同一個概念.張量的階(有時是關於如順序或度數或者是n維)是張量維數的一個數量描述.比如,下面的張量(使用Python中list定義的)就是2階(因為它有兩層中括號).然而作為矩陣,我們認為是3階的。

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

你可以認為一個二階張量就是我們平常所說的矩陣,一階張量可以認為是一個向量.對於一個二階張量你可以用語句t[i, j]來訪問其中的任何元素.而對於三階張量你可以用't[i, j, k]'來訪問其中的任何元素.

下面列出標量向量,矩陣的階數:

數學實例 Python 例子
0 標量 (只有大小) s = 4
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階  ....n層中括號

 

 

 

 

 

數據類型

除了維度,Tensors有一個數據類型屬性.你可以為一個張量指定下列數據類型中的任意一個類型:

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 用於量化Ops的32位有符號整型.
DT_QINT8 tf.qint8 用於量化Ops的8位有符號整型.
DT_QUINT8 tf.quint8 用於量化Ops的8位無符號整型.

 

 

 

 

 

 

 

 

 

 

 

 

形狀

TensorFlow文檔中使用了三種記號來方便地描述張量的維度:階,形狀以及維數.下表展示了他們之間的關系:

形狀 維數 實例
0 [ ] 0-D 一個 0維張量. 一個純量.
1 [D0] 1-D 一個1維張量的形式[5].
2 [D0, D1] 2-D 一個2維張量的形式[3, 4].
3 [D0, D1, D2] 3-D 一個3維張量的形式 [1, 4, 3].
n [D0, D1, ... Dn] n-D 一個n維張量的形式 [D0, D1, ... Dn].

 

 

 

 

 

形狀可以通過Python中的整數列表或元祖(int list或tuples)來表示,也或者用TensorShape class.

2.張量相關操作

張量的相關操作包括類型轉換,數字操作,形狀變換和數據操作。

類型轉換的函數主要包括:詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-85v22c69.html

形狀變換

TensorFlow 提供了幾種操作,可用於確定張量的形狀並更改張量的形狀。形狀函數主要包括:詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-85v22c69.html

張量的分割和連接

TensorFlow 提供了幾個操作來分割或提取張量的部分,或者將多個張量連接在一起。詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-85v22c69.html

假量化

用於幫助訓練提高量化准確度的操作。詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-85v22c69.html

常數值傳感器

TensorFlow 提供了幾種可用於生成常量的操作。詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-efts28tw.html

序列

詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-efts28tw.html

隨機張量

TensorFlow 有幾個 ops 用來創建不同分布的隨機張量。隨機操作是有狀態的,並在每次評估時創建新的隨機值。詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-efts28tw.html

seed 這些函數中的關鍵字參數與圖級隨機種子一起作用。使用 tf.set_random_seed 或使用 op 級別的種子更改圖形級別的種子將會更改這些操作的底層種子。設置圖形級別或操作級種子,都會為所有操作生成隨機種子。有關 tf.set_random_seed 操作級和圖級隨機種子之間的交互的詳細信息,請參閱。

3.算數運算函數

 算術運算符

TensorFlow 提供了幾種操作,您可以使用它們將基本算術運算符添加到圖形中。詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-u7wa28vm.html

基本數學函數

TensorFlow 提供了幾種可用於向圖形添加基本數學函數的操作。

詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-u7wa28vm.html

矩陣數學函數

TensorFlow 提供了幾種操作,您可以使用它們將曲線上的線性代數函數添加到圖形中。詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-u7wa28vm.html

張量數學函數

TensorFlow 提供可用於向圖形添加張量函數的操作。詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-u7wa28vm.html

復數函數

TensorFlow 提供了多種操作,您可以使用它們將復數函數添加到圖形中。詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-u7wa28vm.html

規約計算

TensorFlow 提供了幾種操作,您可以使用這些操作來執行減少張量的各種維度的常規數學計算。在所有reduce_xxx系列操作函數中,都是以xxx的手段降維,每個函數都有axis這個參數,即沿某個方向,使xxx方法對輸入的Tensor進行降維。詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-u7wa28vm.html

張量掃描

TensorFlow 提供了幾種操作,您可以使用它們在張量的一個軸上執行掃描(運行總計)。詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-u7wa28vm.html

分段

TensorFlow 提供了幾種可用於在張量片段上執行常規數學計算的操作。這里,分割是沿着第一維度的張量的分割,即它定義從第一維度到的映射 segment_ids。segment_ids 張量應該是第一尺寸的大小,d0與在范圍內的連續的ID 0到k,在那里 k<d0。特別地,矩陣張量的分割是行到段的映射。詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-u7wa28vm.html

序列比較和索引提取

TensorFlow 提供了幾種操作,您可以使用它們將序列比較和索引提取添加到圖形中。您可以使用這些操作來確定序列差異,並確定張量中特定值的索引。

詳情:https://www.w3cschool.cn/tensorflow_python/tensorflow_python-u7wa28vm.html

三 共享變量

共享變量在復雜的網絡中涌出非常廣泛。

1.共享變量用途

在構建模型時,需要使用tf.Variable來創建一個變量。比如創建一個偏置的學習參數,在訓練的時候,這個變量會不斷地更新:

biases = tf.Variable(tf.zeros(shape=[2]),name='biases')

但在某些情況下,一個模型需要使用其它模型創建的變量,兩個模型在一起訓練。比如:對抗網絡中的生成器模型與判別器模型。如果使用tf.Variable始終會生成一個新的變量,這個函數在處理同名的時候,一般會在后面追加_n:0,比如之前已經創建了一個,那么我們第二次調用這個函數,創建的變量的name將是'biases_1:0',而我們需要的是原來的那么biases變量,這時候怎么辦?

我們可以通過引入get_variable方法,實現共享變量來解決這個問題。

2.get_variable

get_variable函數一般會和variable_scope一起使用,以實現共享變量。variable_scope的意思是變量作用域。在某一作用域的變量可以被設置成共享的方式,被其它網絡模型使用。該函數的定義如下:

tf.get_variable( name, shape=None, dtype=None, initializer=None, regularizer=None, trainable=True, collections=None, caching_device=None, partitioner=None, validate_shape=True, use_resource=None, custom_getter=None )

在TensorFlow中,使用get_variable創建的變量是以指定的name屬性為唯一標識符,並不是定義的變量名稱,重復定義name屬性一樣的變量會報錯,但是可以通過reuse參數指定這不是創建一個新的變量,而是查找之前使用該函數定義過得name一致的變量。使用時一般通過name屬性定位到具體變量,並將其共享到其它模型中。

下面我們通過一個案例來直觀的解釋get_variable和Variable的區別:

'''
(1) tf.Variable的使用
'''
var1 = tf.Variable(1.0,name='first_var',dtype=tf.float32)
print('var1:',var1.name)
var1 = tf.Variable(2.0,name='first_var',dtype=tf.float32)
print('var1:',var1.name)
var2 = tf.Variable(3.0,dtype=tf.float32)
print('var2:',var2.name)
var2 = tf.Variable(4.0,dtype=tf.float32)
print('var2:',var2.name)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print('var1=',var1.eval())
    print('var2=',var2.eval())
    

運行結果如下:

上面代碼中我們定義了兩次var1,可以看到在內存中生成了兩個var1(因為這兩個變量的名字不一樣),對於圖來講后面的var1是生效的(var1=2.0)。var2在定義的時候沒有指定name屬性,系統自動給加上一個名字Variable:0.

'''
(2) get_variable的使用
'''
get_var1 = tf.get_variable('first_var',shape=[1],initializer=tf.constant_initializer(0.3))
print('get_var1:',get_var1.name)

get_var1 = tf.get_variable('first_var',shape=[1],initializer=tf.constant_initializer(0.4))
print('get_var1:',get_var1.name)

運行結果如下:

可以看到程序定義第2個get_var1時發生崩潰了。這表明,使用get_variable只能定義一次指定名稱的變量。同時由於變量first_var在前面使用Variable函數生成過一次,所以系統自動變成了firstvar_2:0。

因此我們需要把代碼修改成如下:

'''
(2) get_variable的使用
'''
get_var1 = tf.get_variable('first_var',shape=[1],initializer=tf.constant_initializer(0.3))
print('get_var1:',get_var1.name)

get_var1 = tf.get_variable('first_var1',shape=[1],initializer=tf.constant_initializer(0.4))
print('get_var1:',get_var1.name)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print('get_var1:',get_var1.eval())

可以看到,這次又是定義了一個get_var1,不同的的是我們在程序中指定了不同的name屬性。同樣,新的get_var1會在圖中生效,所以它的輸出值時0.4而不是0.3.

3.variable_scope

在作用域下,使用get_variable以及嵌套使用variable_scope。在上面的例子中,使用get_variable創建兩個同樣名字(name屬性)的變量是錯誤的。但是我們通過配合使用variable_scope就可以將它們隔開。代碼如下:

'''
(3) variable_scope使用
'''
#定義一個作用域'test1'
with tf.variable_scope('test1'):
    var1 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
    
with tf.variable_scope('test2'):
    var2 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
    
print('var1:',var1.name)
print('var2:',var2.name)    

我們可以看到變量的名字前面都加了作用域作為前綴,因此這段程序生成的兩個變量var1和var2是不同的。

 作用域scope是支持嵌套的,效果如下:

#定義一個作用域'test1'
with tf.variable_scope('test1'):
    var1 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
    
    with tf.variable_scope('test2'):
        var2 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
    
print('var1:',var1.name)
print('var2:',var2.name)    

4.共享變量功能的實現

 使用作用域中的reuse參數來實現共享變量的功能。廢了那么大的勁來講解get_variable就是為了要通過它實現共享變量的功能。

variable_scope里面有一個reuse=True屬性,表示使用已經定義過得變量。這時get_varaible將不會創建新的變量,而是取圖中get_variable所創建過得變量中查找與name相同的變量。

'''
(4) 共享變量功能的實現
'''
with tf.variable_scope('test1',reuse=True):
    var3 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
    
with tf.variable_scope('test2',reuse=True):
    var4 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
    
print('var3:',var3.name)
print('var4:',var4.name)    

我們可以看到var3和var1的輸出name是一樣的,var2和var4的輸出name也是一樣的。這表明他們共用一個變量,這也就實現了共享變量的功能。在實際應用中,可以把var1和var2放到一個網絡模型中取訓練,把var3和var4放到另一個網絡模型中訓練,而兩個模型的訓練結果都會作用於一個模型的學習參數上。

注:tf.get_variable在創建變量時,會去檢查圖中是否已經創建過該變量,如果創建過並且本次調用沒有設置為共享模型,則會報錯,因此在spyder中只能運行一次,第二次運行會報錯,我們可以通過重啟內核清空圖。除此之外,我們還可以使用代碼tf.rest_default_graph(),將圖里面的變量清空,就可以解決報錯的問題。

5.初始化共享變量的作用域

variable_scopr和get_varaibel都有初始化的功能。在初始化時,如果沒有對當前變量初始化,則TensorFlow會默認使用作用域的初始化方法對其初始化,並且作用域的初始化方法也有繼承功能。代碼如下:(tf.constant_initializer初始化器用於生成具有常量值的張量,即用來初始化其它張量的初始值。)

'''
(5)初始化共享變量的作用域
'''
with tf.variable_scope('test3',initializer=tf.constant_initializer(0.4)):
    var5 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
    
    with tf.variable_scope('test4'):
        var6 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
        var7 = tf.get_variable('var7',shape=[2],dtype=tf.float32,initializer=tf.constant_initializer(0.3))
    
    
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    #作用域test3下的變量
    print('var5:',var5.eval())
    #作用域test4下面的變量,繼承自test3初始化
    print('var6:',var6.eval())
    #作用域test4下的變量
    print('var7:',var7.eval())

我們從輸出結果可以看到以下過程:

  • 將test3作用域進行初始化為0.4
  • var5沒有初始化,var5的值為0.4,繼承了test3的值。
  • 嵌套的test4作用域也沒有初始化
  • test4下的var6也沒有初始化,var6的值為0.4,也繼承了test3的初始化。
  • test4下的var7進行了初始化,值為0.3.

6.作用域和操作符的受限范圍

variable_scope還可以以with  variable_scope('name') as xxscope的方式定義作用域,當使用這種方式,所定義的作用域變量xxscope將不再受到外圍的scope的限制。

如下代碼:

'''
(6)作用域和操作符的受限范圍
'''
with tf.variable_scope('scope1')  as sp:
    var1 = tf.get_variable('v',shape=[1])
    
    
print('sp',sp.name)
print('var1:',var1.name)

with tf.variable_scope('scope2'):
    var2 = tf.get_variable('v',shape=[1])
    
    with tf.variable_scope(sp)  as sp1:
        var3 = tf.get_variable('v3',shape=[1])
    
print('sp1:',sp1.name)
print('var2:',var2.name)
print('var3:',var3.name)

我們這里主要關注var3的輸出,var3.name輸出是scope1/v3:0,sp1在scope2下,但是輸出的仍然是scope1,這表明了sp1沒有受到外層(scope2)的限制。這主要是因為我們在定義scope1和scope2時,它們之間是並列關系。

 7.name_scope

這里有必要介紹另一個操作符的作用域tf.name_scope,這個作用域和variable_scope有個區別,即Variable定義的變量在這兩個作用域下都需要加上作用域作為前綴。而get_variable在name_scope作用域下並不會加上前綴,這表明name_scope作用域對get_variable生成的變量沒有任何約束作用,只對Variable生成的變量起作用。

'''
(7) name_scope
'''
with tf.variable_scope('scope'):
    with tf.name_scope('bar'):
        t=tf.get_variable('t',shape=[1])
        x= 1.0 + t
        y = tf.Variable('y')
        
print('t:',t.name)
print('x:',x.name)
print('x.op:',x.op.name)
print('y:',y.name)

從上面我們也可以看到,t變量只受限於variable_scope作用域。而name_scope並不能限制get_variable生成的變量,但是可以限制op以及Variable變量。注意這里有必要說一下什么是op:我們可以把其看做是模型中的中間節點,是通過源節點(即tf常量或者變量)計算得到的,是網絡中的結構。

在name_scope函數中,可以使用空字符串將作用域返回到頂層。

with tf.name_scope(''):

然而variable_scope卻是把其作空字符串處理。

with tf.variable_scope(''):

圖操作

 前面我們大概知道圖是什么?圖就是一個計算任務,之前我們寫的程序,都是在默認圖中工作的,除了系統自動構建圖以外,我們還可以手動構建,並做一些其它的操作,這里我們更加詳細的闡述什么是圖。

TensorFlow中與圖相關的函數主要有以下這些:

核心圖數據結構

張量類型

實用功能

圖形集合

定義新操作

對於建立在TensorFlow上的庫

1.構建圖

可以在一個TensorFlow中手動構建其它的圖,也可以根據圖中的變量獲得當前的圖。下面程序展示了tf.Graph構建圖,使用tf.get_default_graph獲得圖,以及使用reset_default_graph重置圖的過程。

'''
(1) 構建圖
'''
c = tf.constant(0.0,dtype=tf.float32)

g = tf.Graph()
with g.as_default():
    c1 = tf.constant(0.0,dtype=tf.float32)
    print(c1.graph)
    print(g)
    print(c.graph)
    
g2 = tf.get_default_graph()
print(g2)

tf.reset_default_graph()
g3 = tf.get_default_graph()
print(g3)

  • c是在剛開始的默認圖中生成的變量,所以圖的打印值就是原始默認圖的打印值。
  • 然后使用tf.Graph()構建一個圖g,並且在新建的圖中添加變量c1,所以c1.graph和g的打印值是一樣的。
  • 在新圖的作用域外,使用tf.get_default_graph()獲取默認圖,所以輸出值和c.graph一樣。
  • 最后使用tf.reset_default_graph()函數重置圖,相當於重新構建一個圖來替代默認的圖。

注意:使用tf.reset_default_graph()函數必須要保證當前圖的資源已經全部釋放,否則會報錯。

 2.獲取張量

在圖里面可以通過名字得到相應的元素,例如get_tensor_by_name可以獲得圖里面的張量。

'''
(2)獲得張量
'''
g = tf.Graph()
with g.as_default():
    c1 = tf.constant(2.0,dtype=tf.float32,shape=[2])
    print(t.name)
    t = g.get_tensor_by_name(name = 'Const:0')    
    print(g.get_tensor_by_name(name = t.name))    
    print(t)    

上面程序將c1的名字放在get_tensor_by_name()里反向得到其張量,通過對t的打印我們可以看到t就是前面定義的張量c1.

 注意:對於張量的命名,我們不需要去研究,一般使用的時候我們會指定固定的名字,如果真不清楚某個張量的名稱,我們可以先打印出來,然后再使用。

3.獲取節點操作

獲取節點操作op的方法和獲取張量的方法類似,使用的方法是get_operation_by_name()

'''
(3)獲取節點的操作
'''
tf.reset_default_graph()
g4 = tf.get_default_graph()
print(g4)

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

#test和tensor1指向同一個張量
tensor1 = tf.multiply(a,b,name='product')
print(tensor1.name,tensor1)
test = g4.get_tensor_by_name('product:0')
print(test)


#獲取節點操作
print(tensor1.op.name)
testop = g4.get_operation_by_name('product')
print(testop)

with tf.Session() as sess:
    #執行圖 得到矩陣乘積
    test = sess.run(test)
    print(test)
    
    #Z再次獲得張量
    test = tf.get_default_graph().get_tensor_by_name('product:0')
    print(test)
    

我們首先把圖g4打印出來,然后將張量tesnor以及名字打印出來,然后通過get_sensor_by_name()獲得該張量,test和tensor1指向同一個張量。為了證明這一點,直接test在session執行,運行后也能得到正確的結果。

程序中,我們通過print(tensor1.op.name)打印出節點操作的name,然后通過get_operation_by_name()獲取相同的op,可以看出op與tensor1之間的關系。

注意:op和張量在定義節點時很容易混淆,上例中tensor1 = tf.multiply(a,b,name='product')並不是op,而是張量。op其實是描述張量中的運算關系,是通過訪問張量的屬性找到的。

4.獲取元素列表

通過get_operations()函數獲取圖中的所有元素。

'''
(4)獲取元素列表
'''
t2 = g4.get_operations()
print(t2)

 5.獲取對象

前面是根據名字來獲取元素,還可以根據對象來獲取元素,使用tf.Graph().as_graph_elment(obj,allow_tensor=True,allow_operation=True)函數,即傳入一個對象,返回一個張量或是一個op。該函數具有驗證和轉換功能,再多線程方面偶爾會用到。

'''
(5)獲取對象
'''
t3=  g4.as_graph_element(a)
print(t3)

通過print(t3)可以看到,函數as_graph_element()獲取了a張量,然后賦值給了變量t3。

這里我們再看一個特殊的例子:

print('\ng4:',g4)
with g4.as_default():
     print(tf.get_default_graph)

我們可以看到就算我們在新建圖的作用域輸出默認圖,其實打印的還是全局的默認圖,並不是我們新建的圖。

全部代碼:

# -*- coding: utf-8 -*-
"""
Created on Wed Apr 18 14:06:16 2018

@author: zy
"""


'''

TensorBoard可視化顯示以及共享變量
'''

'''
1 TensorBoard可視化
'''


import tensorflow as tf
import numpy as np
import os
import matplotlib.pyplot as plt

'''
一准備數據
'''

#設定訓練集數據長度
n_train = 100

#生成x數據,[-1,1]之間,均分成n_train個數據
train_x = np.linspace(-1,1,n_train).reshape(n_train,1)

#把x乘以2,在加入(0,0.3)的高斯正太分布
train_y = 2*train_x + np.random.normal(loc=0.0,scale=0.3,size=[n_train,1])

#繪制x,y波形
plt.figure()
plt.plot(train_x,train_y,'ro',label='y=2x')   #o使用圓點標記一個點
plt.legend()
plt.show()

'''
二 搭建模型
'''

'''
前向反饋
'''
#創建占位符
input_x = tf.placeholder(dtype=tf.float32)
input_y = tf.placeholder(dtype=tf.float32)

#模型參數
w = tf.Variable(tf.truncated_normal(shape=[1],mean=0.0,stddev=1),name='w')    #設置正太分布參數  初始化權重
b = tf.Variable(tf.truncated_normal(shape=[1],mean=0.0,stddev=1),name='b')    #設置正太分布參數  初始化偏置

#前向結構
pred = tf.multiply(w,input_x) + b

#將預測值以直方圖形式顯示,給直方圖命名為'pred'
tf.summary.histogram('pred',pred)

'''
反向傳播bp
'''
#定義代價函數  選取二次代價函數
cost = tf.reduce_mean(tf.square(input_y - pred))

#將損失以標量形式顯示 該變量命名為loss_function
tf.summary.scalar('loss_function',cost)


#設置求解器 采用梯度下降法 學習了設置為0.001
train = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(cost)


'''
三 迭代模型
'''
#設置迭代次數
training_epochs = 200
display_step = 20


savedir = './LinearRegression'

with tf.Session() as sess:
    #初始化所有張量
    sess.run(tf.global_variables_initializer())
    
    
    #合並所有的summary
    merged_summary_op = tf.summary.merge_all()
    
    #創建summary_write,用於寫文件
    summary_writer = tf.summary.FileWriter(os.path.join(savedir,'summary_log'),sess.graph)
    
    
    #存放批次值和代價值
    plotdata = {'batch_size':[],'loss':[]}
    
    #開始迭代
    for epoch in range(training_epochs):
        for (x,y) in zip(train_x,train_y):
            #開始執行圖
            sess.run(train,feed_dict={input_x:x,input_y:y})
                                            
        #生成summary
        summary_str = sess.run(merged_summary_op,feed_dict={input_x:x,input_y:y})
        #將summary寫入文件
        summary_writer.add_summary(summary_str,epoch)
        
                
    #輸出最終結果
    print('Finished!')
    print('cost {0}  w {1}   b  {2}'.format(sess.run(cost,feed_dict={input_x:train_x,input_y:train_y}),sess.run(w),sess.run(b)))    

    #預測
    test_x = [2,4,5,7]
    test_y = sess.run(pred,feed_dict={input_x:test_x})
    print('prediction  ',test_y)


    '''
    四 可視化顯示
    '''
    #繪制原數據點,和估計曲線
    plt.figure(figsize=(4.2*2,3.2*1))    
    plt.plot(train_x,train_y,'ro',label='Original data')
    plt.plot(train_x,sess.run(w)*train_x + sess.run(b),label ='Estimate data')
    plt.legend()            
    plt.show()
    


'''
2. 共享變量
'''
biases = tf.Variable(tf.zeros(shape=[2]),name='biases')
tf.reset_default_graph()

'''
(1) tf.Variable的使用
'''
var1 = tf.Variable(1.0,name='first_var',dtype=tf.float32)
print('var1:',var1.name)
var1 = tf.Variable(2.0,name='first_var',dtype=tf.float32)
print('var1:',var1.name)
var2 = tf.Variable(3.0,dtype=tf.float32)
print('var2:',var2.name)
var2 = tf.Variable(4.0,dtype=tf.float32)
print('var2:',var2.name)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print('var1=',var1.eval())
    print('var2=',var2.eval())
    
'''
(2) get_variable的使用
'''
get_var1 = tf.get_variable('first_var',shape=[1],initializer=tf.constant_initializer(0.3))
print('get_var1:',get_var1.name)

get_var1 = tf.get_variable('first_var1',shape=[1],initializer=tf.constant_initializer(0.4))
print('get_var1:',get_var1.name)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print('get_var1:',get_var1.eval())
    
    
'''
(3) variable_scope使用
'''
#定義一個作用域'test1'
with tf.variable_scope('test1'):
    var1 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
    
with tf.variable_scope('test2'):
    var2 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
    
print('var1:',var1.name)
print('var2:',var2.name)    


'''
(4) 共享變量功能的實現
'''
with tf.variable_scope('test1',reuse=True):
    var3 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
    
with tf.variable_scope('test2',reuse=True):
    var4 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
    
print('var3:',var3.name)
print('var4:',var4.name)    

'''
(5)初始化共享變量的作用域
'''
with tf.variable_scope('test3',initializer=tf.constant_initializer(0.4)):
    var5 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
    
    with tf.variable_scope('test4'):
        var6 = tf.get_variable('testvar',shape=[2],dtype=tf.float32)
        var7 = tf.get_variable('var7',shape=[2],dtype=tf.float32,initializer=tf.constant_initializer(0.3))
    
    
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    #作用域test3下的變量
    print('var5:',var5.eval())
    #作用域test4下面的變量,繼承自test3初始化
    print('var6:',var6.eval())
    #作用域test4下的變量
    print('var7:',var7.eval())
    
    

'''
(6)作用域和操作符的受限范圍
'''
with tf.variable_scope('scope1')  as sp:
    var1 = tf.get_variable('v',shape=[1])
    
    
print('sp',sp.name)
print('var1:',var1.name)

with tf.variable_scope('scope2'):
    var2 = tf.get_variable('v',shape=[1])
    
    with tf.variable_scope(sp)  as sp1:
        var3 = tf.get_variable('v3',shape=[1])
    
print('sp1:',sp1.name)
print('var2:',var2.name)
print('var3:',var3.name)


'''
(7) name_scope
'''
with tf.variable_scope('scope'):
    with tf.name_scope('bar'):
        t=tf.get_variable('t',shape=[1])
        x= 1.0 + t
        y = tf.Variable('y')
        
print('t:',t.name)
print('x:',x.name)
print('x.op:',x.op.name)
print('y:',y.name)



'''
3 圖操作
'''
'''
(1)構建圖
'''
c = tf.constant(0.0,dtype=tf.float32)

g = tf.Graph()
with g.as_default():
    c1 = tf.constant(0.0,dtype=tf.float32)
    print(c1.graph)
    print(g)
    print(c.graph)
    
g2 = tf.get_default_graph()
print(g2)

tf.reset_default_graph()
g3 = tf.get_default_graph()
print(g3)

'''
(2)獲得張量
'''
g = tf.Graph()
with g.as_default():
    c1 = tf.constant(2.0,dtype=tf.float32,shape=[2])
    print(t.name)
    t = g.get_tensor_by_name(name = 'Const:0')    
    print(g.get_tensor_by_name(name = t.name))    
    print(t)    
    

'''
(3)獲取節點的操作
'''
tf.reset_default_graph()
g4 = tf.get_default_graph()
print(g4)

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

#test和tensor1指向同一個張量
tensor1 = tf.multiply(a,b,name='product')
print(tensor1.name,tensor1)
test = g4.get_tensor_by_name('product:0')
print(test)


#獲取節點操作
print(tensor1.op.name)
testop = g4.get_operation_by_name('product')
print(testop)

with tf.Session() as sess:
    #執行圖 得到矩陣乘積
    test = sess.run(test)
    print(test)
    
    #Z再次獲得張量
    test = tf.get_default_graph().get_tensor_by_name('product:0')
    print(test)
    

'''
(4)獲取元素列表
'''
t2 = g4.get_operations()
print(t2)

'''
(5)獲取對象
'''
t3=  g4.as_graph_element(a)
print(t3)


print('\ng4:',g4)
with g4.as_default():
     print(tf.get_default_graph)
     
    
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM