Tensorflow是一種計算圖模型,即用圖的形式來表示運算過程的一種模型。Tensorflow程序通常分爲圖的構建和圖的執行兩個階段。圖的構建階段也稱爲圖的定義階段,該過程會在圖模型中定義所需的運算,每次運算的的結果以及原始的輸入數據均可稱爲一個節點(operation ,縮寫爲op)。咱們經過如下程序來講明圖的構建過程:python
程序2-1:編程
程序2-1定義了圖的構建過程,「import tensorflow as tf」,是在python中導入tensorflow模塊,並另起名爲「tf」;接着定義了兩個常量op,m1和m2,均爲1*2的矩陣;最後將m1和m2的值做爲輸入建立一個矩陣加法op,並輸出最後的結果result。api
咱們分析最終的輸出結果可知,其並無輸出矩陣相加的結果,而是輸出了一個包含三個屬性的Tensor(Tensor的概念咱們會在下一節中詳細講解,這裏就再也不贅述)。數組
以上過程即是圖模型的構建階段:只在圖中定義所須要的運算,而沒有去執行運算。咱們能夠用圖2-1來表示:session
圖2-1 圖的構建階段數據結構
咱們經過程序2-2來解釋圖的執行階段:dom
程序2-2:機器學習
程序2-2描述了圖的執行過程,首先經過「tf.session()」啓動默認圖模型,再調用run()方法啓動、運行圖模型,傳入上述參數result,執行矩陣的加法,並打印出相加的結果,最後在任務完成時,要記得調用close()方法,關閉會話。分佈式
除了上述的session寫法外,咱們更建議你們,把session寫成如程序2-4所示「with」代碼塊的形式,這樣就無需顯示的調用close釋放資源,而是自動地關閉會話。ide
程序2-3:
此外,咱們還能夠利用CPU或GPU等計算資源分佈式執行圖的運算過程。通常咱們無需顯示的指定計算資源,Tensorflow能夠自動地進行識別,若是檢測到咱們的GPU環境,會優先的利用GPU環境執行咱們的程序。但若是咱們的計算機中有多於一個可用的GPU,這就須要咱們手動的指派GPU去執行特定的op。以下程序2-4所示,Tensorflow中使用with...device語句來指定GPU或CPU資源執行操做。
程序2-4:
上述程序中的「tf.device(「/gpu:2」)」是指定了第二個GPU資源來運行下面的op。依次類推,咱們還能夠經過「/gpu:3」、「/gpu:4」、「/gpu:5」...來指定第N個GPU執行操做。
關於GPU的具體使用方法,咱們會在下面的章節結合案例的形式具體描述。
Tensorflow中還提供了默認會話的機制,如程序2-5所示,咱們經過調用函數as_default()生成默認會話。
程序2-5:
咱們能夠看到程序2-5和程序2-2有相同的輸出結果。咱們在啓動默認會話後,能夠經過調用eval()函數,直接輸出變量的內容。
有時,咱們須要在Jupyter或IPython等python交互式環境開發。Tensorflow爲了知足用戶的這一需求,提供了一種專門針對交互式環境開發的方法InteractiveSession(),具體用法如程序2-6所示:
程序2-6:
程序2-6就是交互式環境中常常會使用的InteractiveSession()方法,其建立sess對象後,能夠直接輸出運算結果。
綜上所述,咱們介紹了Tensorflow的核心概念——計算圖模型,以及定義圖模型和運行圖模型的幾種方式。接下來,咱們思考一個問題,爲何Tensorflow要使用圖模型?圖模型有什麼優點呢?
首先,圖模型的最大好處是節約系統開銷,提升資源的利用率,能夠更加高效的進行運算。由於咱們在圖的執行階段,只須要運行咱們須要的op,這樣就大大的提升了資源的利用率;其次,這種結構有利於咱們提取中間某些節點的結果,方便之後利用中間的節點去進行其它運算;還有就是這種結構對分佈式運算更加友好,運算的過程能夠分配給多個CPU或是GPU同時進行,提升運算效率;最後,由於圖模型把運算分解成了不少個子環節,因此這種結構也讓咱們的求導變得更加方便。
2.3.2 Tensor介紹
Tensor(張量)是Tensorflow中最重要的數據結構,用來表示Tensorflow程序中的全部數據。Tensor本是普遍應用在物理、數學領域中的一個物理量。那麼在Tensorflow中該如何理解Tensor的概念呢?
實際上,咱們能夠把Tensor理解成N維矩陣(N維數組)。其中零維張量表示的是一個標量,也就是一個數;一維張量表示的是一個向量,也能夠看做是一個一維數組;二維張量表示的是一個矩陣;同理,N維張量也就是N維矩陣。
在計算圖模型中,操做間所傳遞的數據均可以看作是Tensor。那Tensor的結構究竟是怎樣的呢?咱們能夠經過程序2-7更深刻的瞭解一下Tensor。
程序2-7:
程序2-7的輸出結果代表:構建圖的運算過程輸出的結果是一個Tensor,且其主要由三個屬性構成:Name、Shape和Type。Name表明的是張量的名字,也是張量的惟一標識符,咱們能夠在每一個op上添加name屬性來對節點進行命名,Name的值表示的是該張量來自於第幾個輸出結果(編號從0開始),上例中的「mul_3:0」說明是第一個結果的輸出。Shape表明的是張量的維度,上例中shape的輸出結果(1,1)說明該張量result是一個二維數組,且每一個維度數組的長度是1。最後一個屬性表示的是張量的類型,每一個張量都會有惟一的類型,常見的張量類型如圖2-2所示。
圖2-2 經常使用的張量類型
程序2-8:
正如程序的報錯所示:m1是int32的數據類型,而m2是float32的數據類型,二者的數據類型不匹配,因此發生了錯誤。因此咱們在實際編程時,必定注意參與運算的張量數據類型要相同。
2.3.3 常量、變量及佔位符
Tensorflow中對常量的初始化,不論是對數值、向量仍是對矩陣的初始化,都是經過調用constant()函數實現的。由於constant()函數在Tensorflow中的使用很是頻繁,常常被用於構建圖模型中常量的定義,因此接下來,咱們經過程序2-9瞭解一下constant()的相關屬性:
程序2-9:
如程序2-9所示,函數constant有五個參數,分別爲value,name,dtype,shape和verify_shape。其中value爲必選參數,其它均爲可選參數。Value爲常量的具體值,能夠是一個數字,一維向量或是多維矩陣。Name是常量的名字,用於區別其它常量。Dtype是常量的類型,具體類型可參見圖2-2。Shape是指常量的維度,咱們能夠自行定義常量的維度。
verify_shape是驗證shape是否正確,默認值爲關閉狀態(False)。也就是說當該參數true狀態時,就會檢測咱們所寫的參數shape是否與value的真實shape一致,若不一致就會報TypeError錯誤。如:上例中的實際shape爲(2,0),若咱們將參數中的shape屬性改成(2,1),程序就會報以下錯誤:
TypeError: Expected Tensor's shape: (2, 1), got (2,).
Tensorflow還提供了一些常見常量的初始化,如:tf.zeros、tf.ones、tf.fill、tf.linspace、tf.range等,都可以快速初始化一些常量。例如:咱們想要快速初始化N維全0的矩陣,咱們能夠利用tf.zeros進行初始化,如程序2-10所示:
程序2-10:
程序2-10向咱們展現了tf.zeros和tf.zeros_like的用法。其它常見常量的具體初始化用法能夠參考Tensorflow官方手冊:https://www.tensorflow.org/api_guides/python/constant_op。
此外,Tensorflow還能夠生成一些隨機的張量,方便快速初始化一些隨機值。如:tf.random_normal()、tf.truncated_normal()、tf.random_uniform()、tf.random_shuffle()等。如程序2-11所示,咱們以tf.random_normal()爲例,來看一下隨機張量的具體用法:
程序2-11:
隨機張量random_normal()有shape、mean、stddev、dtype、seed、name六個屬性。 shape是指張量的形狀,如上述程序是生成一個2行3列的tensor;mean是指正態分佈的均值;stddev是指正太分佈的標準差;dtype是指生成tensor的數據類型;seed是分發建立的一個隨機種子;而name是給生成的隨機張量命名。
Tensorflow中的其它隨機張量的具體使用方法和屬性介紹,能夠參見Tensorflow官方手冊:https://www.tensorflow.org/api_guides/python/constant_op。這裏將不在一一贅述。
除了常量constant(),變量variable()也是在Tensorflow中常常會被用到的函數。變量的做用是保存和更新參數。執行圖模型時,必定要對變量進行初始化,通過初始化後的變量才能拿來使用。變量的使用包括建立、初始化、保存、加載等操做。首先,咱們經過程序2-12瞭解一下變量是如何被建立的:
程序2-12:
程序2-12展現了建立變量的多種方式。咱們能夠把函數variable()理解爲構造函數,構造函數的使用須要初始值,而這個初始值是一個任何形狀、類型的Tensor。也就是說,咱們
既能夠經過建立數字變量、一維向量、二維矩陣初始化Tensor,也可使用常量或是隨機常量初始化Tensor,來完成變量的建立。
當咱們完成了變量的建立,接下來,咱們要對變量進行初始化。變量在使用前必定要進行初始化,且變量的初始化必須在模型的其它操做運行以前完成。一般,變量的初始化有三種方式,如程序2-13所示:
程序2-13:
程序2-13說明了初始化變量的三種方式:初始化所有變量、初始化變量的子集以及初始化單個變量。首先,global_variables_initializer()方法是無論全局有多少個變量,所有進行初始化,是最簡單也是最經常使用的一種方式;variables_initializer()是初始化變量的子集,相比於所有初始化化的方式更加節約內存;Variable()是初始化單個變量,函數的參數即是要初始化的變量內容。經過上述的三種方式,咱們即可以實現變量的初始化,放心的使用變量了。
咱們常常在訓練模型後,但願保存訓練的結果,以便下次再使用或是方便往後查看,這時就用到了Tensorflow變量的保存。變量的保存是經過tf.train.Saver()方法建立一個Saver管理器,來保存計算圖模型中的全部變量。具體代碼如程序2-14所示:
程序2-14:
咱們要注意,咱們的存儲文件save.ckpt是一個二進制文件,Saver存儲器提供了向該二進制文件保存變量和恢復變量的方法。保存變量的方法就是程序中的save()方法,保存的內容是從變量名到tensor值的映射關係。完成該存儲操做後,會在對應目錄下生成如圖2-3所示的文件:
圖2-3 保存變量生成的相應文件
那如何才能恢復變量呢?首先,咱們要知道必定要用和保存變量相同的Saver對象來恢復變量。其次,不須要事先對變量進行初始化。具體代碼如程序2-15所示:
程序2-15:
本程序示例中,咱們要注意:變量的獲取是經過restore()方法,該方法有兩個參數,分別是session和獲取變量文件的位置。咱們還能夠經過latest_checkpoint()方法,獲取到該目錄下最近一次保存的模型。
以上就是對變量建立、初始化、保存、加載等操做的介紹。此外,還有一些與變量相關的重要函數,如:eval()等。
認識了常量和變量,Tensorflow中還有一個很是重要的經常使用函數——placeholder。placeholder是一個數據初始化的容器,它與變量最大的不一樣在於placeholder定義的是一個模板,這樣咱們就能夠session運行階段,利用feed_dict的字典結構給placeholder填充具體的內容,而無需每次都提早定義好變量的值,大大提升了代碼的利用率。Placeholder的具體用法如程序2-16所示:
程序序2-16:
程序2-16演示了placeholder佔位符的使用過程。Placeholder()方法有dtype,shape和name三個參數構成。dtype是必填參數,表明傳入value的數據類型;shape是選填參數,表明傳入value的維度;name也是選填參數,表明傳入value的名字。咱們能夠把這三個參數看做爲形參,在使用時傳入具體的常量值。這也是placeholder不一樣於常量的地方,它不能夠直接拿來使用,而是須要用戶傳遞常數值。
最後,Tensorflow中還有一個重要的概念——fetch。Fetch的含義是指能夠在一個會話中同時運行多個op。這就方便咱們在實際的建模過程當中,輸出一些中間的op,取回多個tensor。Fetch的具體用法如程序2-17所示:
程序2-17:
程序2-17展現了fetch的用法,即咱們利用session的run()方法同時取回多個tensor值,方便咱們查看運行過程當中每一步op的輸出結果。
程序2-18:
小結:本節旨在讓你們學會Tensorflow的基礎知識,爲後邊實戰的章節打下基礎。主要講了Tensorflow的核心——計算圖模型,如何定義圖模型和計算圖模型;還介紹了Tensor的概念,以及Tensorflow中的常量、變量、佔位符、feed等知識點。你們都掌握了嗎?