TensorFlow基礎

一、基礎概念

1. 從Hello World開始

    import tensorflow as tf
    #創建一個常量運算,將作為一個節點加入到默認計算圖中
    hello = tf.constant("Hello, World!")
    #創建一個TF對話
    sess = tf.Session()
    #運行并獲得結果
    print(sess.run(hello))
    # b'Hello, World!'  
    #輸出前面的'b'表示Bytes literals(字節文字)

2. TensorFlow的概念

  • Tensor 張量
    數據結構:多維數組
  • Flow 流
    計算模型:張量之間通過計算而轉換的過程

TensorFlow是一個通過計算圖的形式表述計算的編程系統
每一個計算都是計算圖上的一個節點,節點之間的邊描述了計算之間的關系

3. 計算圖(數據流圖)的概念

計算圖是一個有向圖,由以下內容構成

  • 一組節點,每個節點都代表一個操作,是一種運算
  • 一組有向邊,每條邊代表節點之間的關系( 數據傳遞控制依賴 )

TensorFlow有兩種邊

  • 常規邊(實線):代表數據依賴關系。一個節點的運算輸出成為另一個節點的輸入,兩個節點之間有tensor流動( 值傳遞 )
  • 特殊邊(虛線):不攜帶值,表示兩個節點之間的控制相關性。比如,happens-before關系,源節點必須在目的節點執行前完成執行

4. 計算圖的實例

計算圖節點輸出的結果不是一個具體的數字,而是一個張量的結構

    #一個簡單計算圖
    node1 = tf.constant(3.0, tf.float32, name = "node1")
    node2 = tf.constant(4.0, tf.float32, name = "node2")
    node3 = tf.add(node1, node2)
    print(node3)
    # Tensor("Add:0", shape=(), dtype=float32)

創建計算圖就是建立計算模型,執行對話才能提供數據并獲得結果

    #建立對話并顯示運行結果
    sess = tf.Session()
    #更新變量并返回計算結果
    print("運行sess.run(node3)的結果:", sess.run(node3))
    #關閉session 
    sess.close()
    # 運行sess.run(node3)的結果: 7.0

5. 張量的概念

  • 在TensorFlow中,所有的數據都通過張量的形式來表示
  • 從功能的角度,張量可以簡單理解為多維數組
    零階張量表示標量(scalar),也就是一個
    一階張量向量(vector),也就是 一維數組
    n階張量可以理解為一個n維數組
  • 張量并沒有真正保存數字,它保存的是計算過程

6. 張量的屬性

    Tensor("Add:0", shape=(), dtype=float32)
  • 名字(name)
    "node:src_output":node 節點名稱,src_output 來自節點的第幾個輸出
  • 形狀(shape)
    張量的維度信息,shape=(),表示是標量
  • 類型(type)
    每一個張量會有一個唯一的類型
    TensorFlow會對參與運算的所有張量進行類型檢查,發現類型不匹配時會報錯

7. 張量的形狀

三個術語描述張量的維度,階(rank)、形狀(shape)、維數(dimension number)

形狀 維數 例子
0 () 0-D 4
1 (D0) 1-D [2,3,5]
2 (D0,D1) 2-D [[2,3],[3,4]]
3 (D0,D1,D2) 3-D [[[7],[3]],[[2],[4]]]
N (D0,D1,...,Dn-1) n-D 形為(D0,D1,...,Dn-1的張量)
    tens1 = tf.constant([[[1,2,2],[2,2,3]],
                        [[3,5,6],[5,4,3]],
                        [[7,0,1],[9,1,9]],
                        [[11,12,7],[1,3,14]]], name="tens1")
    print(tens1)
    #Tensor("tens1:0", shape=(4, 2, 3), dtype=int32)
    #shape,4表示最外維有4個元素,2表示中間維度有2個元素,3表示最里維有3個元素
    
    #查看張量的形狀
    scalar = tf.constant(100)
    vector = tf.constant([1, 2, 3, 4, 5])
    matrix = tf.constant([[1, 2, 3],[4, 5, 6]])
    cube_matrix = tf.constant([[[1],[2],[3]], [[4],[5],[6]], [[7],[8],[9]]])
    
    print(scalar.get_shape())
    print(vector.get_shape())
    print(matrix.get_shape())
    print(cube_matrix.get_shape())
    # ()
    # (5,)
    # (2, 3)
    # (3, 3, 1)

8. 獲取張量的元素

  • 階為1的張量等價于向量
  • 階為2的張量等價于矩陣,通過t[i, j]獲取元素
  • 階為3的張量,通過t[i, j, k]獲取元素
    tens2 = tf.constant([[[1,2],[2,3]],[[3,4],[5,6]]])
    sess = tf.Session()
    print(sess.run(tens2)[1, 1, 0])
    sess.close()
    # 5

9. 張量的類型

TensorFlow支持14種不同的類型

  • 實數 tf.float32, tf.float64
  • 整數 tf.int8, tf.int16, tf.int32, tf.int64, tf.uint8
  • 布爾 tf.bool
  • 復數 tf.complex64, tf.complex128
    默認類型:
  • 不帶小數點的數會被默認為int32
  • 帶小數點的會被默認為float32
    import tensorflow as tf
    a = tf.constant([1, 2], name = "a")
    b = tf.constant([2.0, 3.0], name = "b")
    result = a + b
    # 類型不匹配而報錯:Tensor conversion requested dtype int32 for Tensor with dtype float32: 'Tensor("b:0", shape=(2,), dtype=float32)'

10. 操作

  • 計算圖中的節點就是操作
    加減乘除運算、變量初始賦值都是操作
  • 每個運算操作都有屬性,它在構建圖的時候需要確定下來
  • 操作可以和計算設備綁定,指定操作在某個設備上執行
  • 操作之間存在順序關系,這些操作之間的依賴就是“邊”
  • 如果操作A的輸入是操作B執行的結果,那么這個操作A就依賴于操作B
    import tensorflow as tf
    tf.reset_default_graph() #清除default graph和不斷增加的節點
    #定義變量a
    a = tf.Variable(1, name = "a")
    b= tf.add(a, 1, name = "b")
    c = tf.multiply(b, 4, name = "c")
    d = tf.subtract(c, b, name = "d")
    logdir = 'D:\ForPython\log'
    #生成一個寫日志的writer,并將當前的TensorFlow計算圖寫入日志
    writer = tf.summary.FileWriter(logdir, tf.get_default_graph())
    writer.close()

二、基本運算

1. TensorFlow運行模型——會話

會話擁有并管理TensorFlow程序運行時的所有資源,當所有計算完成后需要關閉會話幫助系統回收資源

  • 會話的典型模式1
    #定義計算圖
    tens1 = tf.constant([1, 2, 3])
    #創建一個會話
    sess = tf.Session()
    try:
        #使用這個創建好的會話來得到關心的運算的結果,比如盜用 sess.run(result)
        #來得到張量result的值
        print(sess.run(tens1))
    except:
        print("Exception")
    finally:
        #關閉會話使得本次運行中使用到的資源可以被釋放
        sess.close()
    # [1 2 3]    
  • 會話的典型模式2
    node1 = tf.constant(3.0, tf.float32, name = "node1")
    node2 = tf.constant(4.0, tf.float32, name = "node2")
    result = tf.add(node1, node2)
    #創建一個會話,并通過Python中的上下文管理器來管理這個會話
    with tf.Session() as sess:
        #使用這創建好的會話來計算關心的結果
        print(sess.run(result))
    #不需要再調用Session.close()函數來關閉會話
    #當上下文退出時會話關閉和資源釋放也自動完成了
    # 7.0    
  • 指定默認的會話
    node1 = tf.constant(3.0, tf.float32, name = "node1")
    node2 = tf.constant(4.0, tf.float32, name = "node2")
    result = tf.add(node1, node2)
    sess = tf.Session() 
    with sess.as_default(): #指定sess為默認的會話,故可直接調用result.eval()
        print(result.eval())
    # 7.0    
    #未指定時,result.eval()必須說明會話參數
    print(result.eval(session = sess)
    # 7.0
    #用sess.run()同樣可以完成相同功能
    print(sess.run(result))
    # 7.0
    
  • 交互式環境下設置默認會話
    交互式環境下,Python腳本或者Jupyter編輯器下,通過設置默認會話來獲取張量的取值更加方便,tf.InteractiveSession 使用這個函數會自動將生成的會話注冊為默認會話
    node1 = tf.constant(3.0, tf.float32, name = "node1")
    node2 = tf.constant(4.0, tf.float32, name = "node2")
    result = tf.add(node1, node2)
    #定義交互式的session,同時注冊為默認會話
    sess = tf.InteractiveSession()
    print(result.eval())
    sess.close()
    # 7.0

2. 常量與變量

常量:在運行過程中不會改變的單元,在TensorFlow中無須進行初始化操作

    #創建語句
    constant_name = tf.constant(value)
    #示例
    a = tf.constant(1.0, name = "a")

變量:在運行過程中值會改變的單元,在TensorFlow中須進行初始化操作

    #創建語句
    name_variable = tf.Variable(value, name)  #注意V是大寫字母
    #個別變量初始化
    init_op = name_variable.initializer()
    #所有變量初始化
    init_op = tf.global_variables_initializer()
    
    #示例
    node1 = tf.Variable(3.0, tf.float32, name = "node1")
    node2 = tf.Variable(4.0, tf.float32, name = "node2")
    result = tf.add(node1, node2, name = "add")
    sess = tf.Session()
    #變量初始化
    init = tf.global_variables_initializer()
    sess.run(init)
    print(sess.run(result))
    # 7.0

3. 變量賦值

與傳統編程語言不同,TensorFlow中的變量定義后,一般無需人工賦值,系統會根據算法模型,訓練優化過程中自動調整變量對應的數值

    #如果需要人工賦值,并且不希望訓練模型自動更改它
    epoch = tf.Variable(0, name = 'epoch', trainable = False) #指明不參加訓練
    #特殊情況需要人工更新,可用變量賦值語句
    update_op = tf.assign(variable_to_be_updated, new_value) #被更新變量,新值
    
    #示例:通過變量賦值1、2、3...5
    import TensorFlow as tf
    value = tf.Variable(0, name = "value")
    one = tf.constant(1)
    new_value = tf.add(value, one)
    update_value = tf.assign(value, new_value)
    
    init = tf.global_variables_initializer()
    
    with tf.Session() as sess:
        sess.run(init)
        for _ in range(5):    #執行5次
            sess.run(update_value) #每一次更新值(+1)
            print(sess.run(value))
    # 1
    # 2
    # 3
    # 4
    # 5

4. 占位符、Feed數據填充和Fetch數據獲取

TensorFlow中的Variable變量類型,在定義時需要初始化,但有些變量定義時并不知道其數值,只有當真正開始運行程序時,才由外部輸入,比如訓練數據,這時候需要用到占位符
tf.placeholder占位符,是TensorFlow中特有的一種數據結構,類似動態變量,函數的參數、或者C語言或者Python語言中格式化輸出的“%”占位符。

  • 占位符 placeholder
    #函數接口:先定義一種數據,參數為數據的 Type和 Shape
    tf.placeholder(dtype, shape = None, name = None)
    x = tf.placeholder(tf.float32, [2, 3], name = 'tx')
    #生成一個2x3的二維數組,矩陣中每個元素類型為tf.float32,內部對應的符號名稱是tx
  • Feed數據填充

如果構建了一個包含placeholder操作的計算圖,當在session中調用run方法時,placeholder占用的變量必須通過feed_dict參數傳遞進去

    #定義變量a、b
    a = tf.placeholder(tf.float32, name = 'a')
    b = tf.placeholder(tf.float32, name = 'b')
    #定義a*b的操作 c
    c = tf.multiply(a, b, name ='c')
    #定義初始化所有變量的操作init
    init = tf.global_variables_initializer()
    #創建一個會話,并通過Python中的上下文管理器來管理這個會話
    with tf.Session() as sess:
        sess.run(init) #使用的是占位符,因此這里不進行變量初始化也可以 
        #通過feed_dict 的參數傳遞,按字典格式
        result = sess.run(c, feed_dict = {a : 8.0, b : 3.5})
        print(result)
    # 28.0    
  • 多個操作可以通過一次Feed完成執行
    #定義變量 a、b
    a = tf.placeholder(tf.float32, name = "a")
    b = tf.placeholder(tf.float32, name = "b")
    #定義操作 c、d
    c = tf.multiply(a, b, name ="c")    
    d = tf.subtract(a, b, name = 'd')
    
    init = tf.global_variables_initializer()
    
    with tf.Session() as sess:
        sess.run(init)
        result = sess.run([c,d],feed_dict = {a:[8.0, 2.0, 3.5], b:[1.5, 2.0, 4.]})
        print(result)
        #取結果中的第一個
        print(result[0])    
        # [array([ 12.,   4.,  14.], dtype=float32), array([ 6.5,  0. , -0.5], dtype=float32)]
        # [ 12.   4.  14.] 
        
        #一次返回多個值分別賦給多個變量
        rc, rd = sess.run([c,d],feed_dict = {a:[8.0, 2.0, 3.5], b:[1.5, 2.0, 4.]})
        print("value of c = ", rc, "value of d = ", rd)
        # value of c =  [ 12.   4.  14.] value of d =  [ 6.5  0.  -0.5]

三、TensorBoard 可視化初步

TensorBoard是TensorFlow的可視化工具,通過TensorFlow程序運行過程中輸出的日志文件可視化TensorFlow程序的運行狀態,TensorBoard和TensorFlow程序跑在不同的進程中。

    import tensorflow as tf
    
    #清除default graph 和不斷增加的節點
    tf.reset_default_graph()
    
    #日志
    logdir = 'D:\ForPython\log'
    
    #定義一個簡單的計算圖,實現向量加法的操作
    input1 = tf.constant([1.0, 2.0, 3.0], name = "input1")
    input2 = tf.Variable(tf.random_uniform([3]), name = "input2")
    output = tf.add_n([input1, input2], name = "add")
    
    #生成一個寫日志的writer, 并將當前的TensorFlow計算圖寫入日志
    writer = tf.summary.FileWriter(logdir, tf.get_default_graph())
    writer.close()

啟動TensorBoard

  • 在Anaconda Prompt 中先進入日志存放的目錄
  • 再運行TensorBoard,并將日志的地址指向程序日志輸出的地址
  • 命令:tensorboard --logdir=D:\ForPython\log
  • 啟動服務的端口默認為6006,使用 --port 參數可以改編啟動服務的端口
啟動TensorBoard
計算圖
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • @Deprecated讓我們擁抱tensorflow2.0吧 0. 概述 TensorFlow提供了實現機器學習算...
    音符紙飛機閱讀 747評論 0 11
  • TensorFlow采用聲明式編程范式,其優勢包括: 代碼可讀性強 支持引用透明,聲明式編程沒有內部狀態,不依賴于...
    林逸凡_lyf閱讀 809評論 0 0
  • 之前發過了幾篇關于機器學習的帖子,使用的框架多為TensorFlow。TensorFlow 是一個用于人工智能的開...
    BlackBlog__閱讀 1,082評論 0 4
  • 要事第一,養好身體,才能更好的工作 ! 今天運氣好 用半天的時間完成了一天的工作 開熏......晚安.........
    仙女本仙吖閱讀 140評論 1 1
  • 姓名:葛咪霞 公司:寧波偉大聯盟國際貨運代理有限公司 【日精進打卡第29天】 【知~學習】看書 聽廣播 【經典名句...
    格格8閱讀 281評論 0 0