1. 程式人生 > 程式設計 >Python Tensor FLow簡單使用方法例項詳解

Python Tensor FLow簡單使用方法例項詳解

本文例項講述了Python Tensor FLow簡單使用方法。分享給大家供大家參考,具體如下:

1、基礎概念

Tensor表示張量,是一種多維陣列的資料結構。Flow代表流,是指張量之間通過計算而轉換的過程。TensorFLow通過一個計算圖的形式表示程式設計過程,資料在每個節點之間流動,經過節點加工之後流向下一個節點。

計算圖是一個有向圖,其組成如下:節點:代表一個操作。邊:代表節點之間的資料傳遞和控制依賴,其中實線代表兩個節點之間的資料傳遞關係,虛線代表兩個節點之間存在控制相關。

張量是所有資料的表示形式,可以將其理解為一個多維陣列。零階張量就是標量(scalar),表示一個數,一階張量為一維陣列,即向量(vector)。n階張量也就是n維陣列。張量並不儲存具體數字,它儲存的是計算過程。

下面的例子是將節點1、2的值相加得到節點3。

import tensorflow as tf 
node1=tf.constant(3.0,tf.float32,name='node1')  #建立浮點數節點
node2=tf.constant(4.0,name='node2')
node3=tf.add(node1,node2)       #節點三進行相加操作,源於節點1、2
ses=tf.Session()
print(node3)      #輸出張量:Tensor("Add_3:0",shape=(),dtype=float32)
print(ses.run(node3))    #通過會話執行節點三,將節點1、2相加,輸出:7.0
ses.close()           #不使用時,關閉會話

直接print(node3)輸出的結果不是具體的值,而是張量結構。因為建立計算圖只是建立了計算模型,只有會話執行run()才能獲得具體結果。

Tensor("Add_3:0",dtype=float32)中,Add表示節點名稱,3表示這是該節點的第3個輸出。shape表示張量的維度資訊,()代表標量。dtype表示張量的型別,每個張量的型別唯一,如果不匹配會報錯,不帶小數點的預設型別為int32,帶小數點預設為float35。下面的例子為更復雜的張量型別:

tensor1=tf.constant([[[1,1,1],[1,2,1]],[[2,[2,[[3,[3,[[4,[4,1]]],name='tensor1')
print(tensor1)
ss=tf.Session()
print(ss.run(tensor1)[3,0])     #訪問tensor1的具體元素
#輸出:Tensor("tensor1:0",shape=(4,3),dtype=int32) 4

其中shape=(4,3)表示tensor1的最外層有4個數組,每個陣列內有2個子陣列,子陣列由3個數字構成。可以通過多維陣列的方式訪問其中的具體元素,[3,0]即為第四個陣列中第一個子陣列的第一個元素,4。

計算圖中還有的節點表示操作,例如加減乘除、賦初值等,操作有自己的屬性,需要在建立圖的時候就確定,操作之間有先後等依賴關係,通過圖的邊可以直觀地看出來。

2、運算

會話

會話(Session)擁有並管理TensorFLow的所有資源,通過Session執行計算才能得到結果,計算完成後記得關閉會話回收資源。下面是使用Session的流程:

#定義計算圖
tensor1=tf.constant([1,3])
#建立會話
ss=tf.Session()
#利用會話進行計算操作
print(ss.run(tensor1))
#關閉會話
ss.close()

也可以通過python上下文管理器來使用Session,當退出上下文時會自動關閉Session並釋放資源

tensor1=tf.constant([1,3])
with tf.Session() as ss:    #上下文管理器
 print(ss.run(tensor1))

還可以通過指定預設會話,使用eval()獲取張量的值:

tensor1=tf.constant([1,3])
ss=tf.Session()
with ss.as_default():     #指定預設會話
 print(tensor1.eval())

在互動式環境下通過InteractiveSession()自動將生成的會話設為預設:

tensor1=tf.constant([1,3])
ss=tf.InteractiveSession()     #自動註冊預設會話
print(tensor1.eval())
ss.close()

變數、常量

TensorFLow通過constant函式完成對常量的定義,可以為其賦初值與命名

a=tf.constant(10,'int_a')

而變數不僅需要定義,還需要經過初始化後才可以使用,初始化操作不僅需要定義,還需要執行

node1=tf.Variable(3.0,name='node1')    #定義變數
node2=tf.Variable(4.0,name='node2')
res=tf.add(node1,node2,name='res')
 
ss=tf.Session()        
init=tf.global_variables_initializer()   #定義全部變數的初始化操作
ss.run(init)         #執行初始化操作
 
print(ss.run(res))
ss.close()

TensorFLow的變數一般不需要手動賦值,因為系統會在訓練過程中自動調整。如果不希望由模型自動賦值,可以在定義時指定屬性trainable=False,並通過assign函式來手動賦值

var1=tf.Variable(0,name='var')
one=tf.constant(1)
var2=tf.add(var1,one)       #變數1加1得到變數2
update=tf.assign(var1,var2)     #定義update操作,將變數2賦值給變數1
 
init=tf.global_variables_initializer()
ss=tf.Session()
ss.run(init)
for _ in range(10):
 ss.run(update)        #執行update操作
 print(ss.run(var1))
 
ss.close()
 
#輸出:1 2 3 4 5 6 7 8 9 10

在執行ss.run(update)操作時,由於update需要var1和var2依賴,而得到var2需要執行add操作,因此只需要run一個update就會觸發整個計算網路。

佔位符

有時在定義變數的時候,並不知道它的具體值,只有在執行的時候才輸入對應數值,而tensorflow中變數的定義需要賦初值,這時就需要使用佔位符placeholder來進行定義,並在計算時傳入具體數值。一個簡單的使用例子:

node1=tf.placeholder(tf.float32,name='node1')  #定義佔位符,規定其型別、結構、名字
node2=tf.placeholder(tf.float32,name='node2') 
m=tf.multiply(node1,'multinode')
 
ss=tf.Session()
res=ss.run(m,feed_dict={node1:1.2,node2:3.4})  #在執行時通過feed_dict為佔位符賦值 
print(res)
ss.close()

也可以把多個操作放到一次feed操作完成

node1=tf.placeholder(tf.float32,[3],name='node1')  #第二個引數規定佔位符的型別為3維陣列
node2=tf.placeholder(tf.float32,'multinode')
s=tf.subtract(node1,'subnode')
 
ss=tf.Session()
#將m,s兩個操作放到一起,並返回兩個結果
resm,ress=ss.run([m,s],feed_dict={node1:[1.0,2.0,4.0],node2:[3.0,5.0,6.0]})
print(resm)           #輸出:[ 3. 10. 24.]
ss.close()

3、TensorBoard

TensorBoard是TensorFLow的視覺化工具,通過程式執行中輸出的日誌檔案視覺化地表示TensorFLow的執行狀態。其程式設計如下:

node1=tf.Variable(3.0,name='node1')    
node2=tf.Variable(4.0,name='res')
ss=tf.Session()        
init=tf.global_variables_initializer()   
ss.run(init)         
print(ss.run(res))
ss.close()
 
#清除default graph和其他節點
tf.reset_default_graph()
#定義日誌存放的預設路徑
logdir='D:\Temp\TensorLog'
#生成writer將當前的計算圖寫入日誌
writer=tf.summary.FileWriter(logdir,tf.get_default_graph())
writer.close()

TensorBoard已經隨Anaconda安裝完成,首先通過Anaconda Prompt進入日誌檔案的存放目錄,然後輸入tensorboard --logdir=D:\Temp\TensorLog,設定日誌的存放路徑,完成之後在瀏覽器的localhost:6006埠就可以看到TensorBoard,也可以通過--port命令修改預設埠。

利用TensorBoard顯示圖片,通過summary.image()將格式化的圖片資料顯示,其中輸入的image_imput資料是四維格式,第一維表示一次輸入幾行資料,-1表示不確定。28,28,1表示圖片資料為28×28大小,且其色彩通道為1。

通過summary.histogram()可以顯示直方圖資料。通過summary.scalar()可以顯示標量資料。在所有summary定義完成後,可以通過summary.merge_all()函式定義一個彙總操作,將所有summary聚合起來。

在建立session後定義writer用於日誌檔案的寫入,在進行訓練時,每批次訓練都將執行一次merge操作,並將結果寫入日誌。

如下為通過多層神經網路解決MNIST手寫識別問題的例子,將其中的一些資料通過TensorBoard顯示出來:

#TensorBoard使用
#定義日誌儲存位置
log_dir='D:\Temp\MachineLearning\TensorLog'
#顯示圖片
image_input=tf.reshape(x,[-1,28,1])
tf.summary.image('input',image_input,10)  #一次最多顯示圖片數:10
#顯示直方圖
tf.summary.histogram('Y',Y3)
#顯示標量loss
tf.summary.scalar('loss',loss_function)
tf.summary.scalar('accurancy',accuracy)
#定義彙總summary操作
merge_op=tf.summary.merge_all()
 
ss=tf.Session()
ss.run(tf.global_variables_initializer())
#定義writer
writer=tf.summary.FileWriter(log_dir,ss.graph)
 
for epoch in range(train_epochs):
 for batch in range(batch_num): #分批次讀取資料進行訓練
  xs,ys=mnist.train.next_batch(batch_size)
  ss.run(optimizer,feed_dict={x:xs,y:ys})
  #執行summary操作並將結果寫入日誌檔案
  summary_str=ss.run(merge_op,y:ys})
  writer.add_summary(summary_str,epoch)
  
 loss,acc=ss.run([loss_function,accuracy],\
     feed_dict={x:mnist.validation.images,y:mnist.validation.labels})
 print('第%2d輪訓練:損失為:%9f,準確率:%.4f'%(epoch+1,loss,acc))

執行結果如下圖所示分別為圖片、accuracy、loss標量圖、Y1直方圖以及隨之生成的分佈圖:

更多關於Python相關內容感興趣的讀者可檢視本站專題:《Python資料結構與演算法教程》、《Python加密解密演算法與技巧總結》、《Python編碼操作技巧總結》、《Python函式使用技巧總結》、《Python字串操作技巧彙總》及《Python入門與進階經典教程》

希望本文所述對大家Python程式設計有所幫助。