# 一、TensorFlow 的設置和介紹
TensorFlow 是 Google 創建的開源軟件庫,可讓您構建和執行數據流圖以進行數值計算。 在這些圖中,每個節點表示要執行的某些計算或功能,連接節點的圖邊表示它們之間流動的數據。 在 TensorFlow 中,數據是稱為**張量**的多維數組。 張量圍繞圖流動,因此命名為 TensorFlow。
**機器學習**(**ML**)模型,例如卷積神經網絡,可以用這些圖表示,而這正是 TensorFlow 最初設計的目的。
在本章中,我們將介紹以下主題:
* 了解 TensorFlow 的思維方式
* 設置和安裝 TensorFlow
* TensorFlow API 級別簡介
* 在 TensorFlow 中構建和訓練線性分類器
* 評估訓練好的模型
# TensorFlow 的思維方式
使用 TensorFlow 所需的編程方法與您可能習慣使用的方法略有不同,因此讓我們探究有什么不同之處。
所有 TensorFlow 程序的核心都有兩個主要部分:
* 構造稱為`tf.Graph`的計算圖
* 使用`tf.Session`運行計算圖
在 TensorFlow 中,計算圖是安排成圖結構的一系列 TensorFlow 操作。 TensorFlow 圖包含兩種主要類型的組件:
* **操作**:更通常稱為 **ops**,這些是圖中的節點。 操作執行需要在圖中進行的任何計算。 通常,它們消耗并產生張量。 一些操作很特殊,運行時可能會有某些副作用。
* **張量**:這是圖的邊; 它們將節點連接起來并表示流經節點的數據。 大多數 TensorFlow 操作將產生并消耗這些`tf.Tensors`。
在 TensorFlow 中,您使用的主要對象稱為張量。 張量是向量和矩陣的一般化。 即使向量是一維的,矩陣是二維的,張量也可以是`n`維。 TensorFlow 將張量表示為用戶指定數據類型的`n`維數組,例如`float32`。
TensorFlow 程序通過首先構建計算圖來工作。 該圖將產生一些`tf.Tensor`輸出。 要求值此輸出,您必須通過在輸出張量上調用`tf.Session.run`來在`tf.Session`中運行它。 當您執行此操作時,TensorFlow 將執行圖中需要執行的所有部分,以評估您要求其運行的`tf.Tensor`。
# 設置和安裝 TensorFlow
TensorFlow 在最新版本的 Ubuntu 和 Windows 上受支持。 Windows 上的 TensorFlow 僅支持使用 Python3,而在 Ubuntu 上使用則允許同時使用 Python2 和 3。我們建議使用 Python3,這就是本書中用于代碼示例的內容。
您可以通過多種方式在系統上安裝 TensorFlow,這里我們將介紹兩種主要方式。 最簡單的方法就是使用 PIP 軟件包管理器。 從終端發出以下命令會將 TensorFlow 的僅 CPU 版本安裝到您??的系統 Python 中:
```py
$ pip3 install --upgrade tensorflow
```
要安裝支持使用您的 Nvidia GPU 的 Tensorflow 版本,只需鍵入以下內容:
```py
$ pip3 install --upgrade tensorflow-gpu
```
TensorFlow 的優勢之一是它允許您編寫可以直接在 GPU 上運行的代碼。 除了少數例外,TensorFlow 中的幾乎所有主要操作都可以在 GPU 上運行以加快其執行速度。 我們將看到,這對于訓練本書稍后描述的大型卷積神經網絡將至關重要。
# Conda 環境
使用 PIP 可能是上手最快的方法,但是我發現最方便的方法是使用 conda 環境。
Conda 環境允許您創建隔離的 Python 環境,該環境與系統 Python 或任何其他 Python 程序完全獨立。 這樣一來,您的 TensorFlow 安裝就不會與已經安裝的任何內容發生混亂,反之亦然。
要使用 conda,[您必須從此處下載 Anaconda](https://www.anaconda.com/download/)。 這將包括 conda。 一旦安裝了 Anaconda,即可通過在命令提示符中輸入某些命令來完成 TensorFlow 的安裝。 首先,輸入以下內容:
```py
$ conda create -n tf_env pip python=3.5
```
這將創建名稱為`tf_env`的 conda 環境,該環境將使用 Python 3.5,并且還將安裝`pip`供我們使用。
創建此環境后,您可以通過在 Windows 上輸入以下內容來開始使用它:
```py
$ activate tf_env
```
如果您使用的是 Ubuntu,請輸入以下命令:
```py
$ source activate tf_env
```
現在,它應該在命令提示符旁邊顯示`(tf_env)`。 要安裝 TensorFlow,我們只需像以前一樣進行點安裝,具體取決于您是否僅需要 CPU 還是需要 GPU 支持:
```py
(tf_env)$ pip install --upgrade tensorflow
(tf_env)$ pip install --upgrade tensorflow-gpu
```
# 檢查您的安裝是否正常
現在您已經安裝了 TensorFlow,讓我們檢查一下它是否正常運行。 在命令提示符中,如果尚未激活環境,請再次激活它,然后輸入以下命令來運行 Python:
```py
(tf_env)$ python
```
現在,在 Python 解釋器中輸入以下行以測試 TensorFlow 是否已正確安裝:
```py
>>>> import tensorflow as tf
>>>> x = tf.constant('Tensorflow works!')
>>>> sess = tf.Session()
>>>> sess.run(x)
```
如果一切都正確安裝,您應該看到以下輸出:
`**b'Tensorflow works!'**`
您剛剛輸入的是 TensorFlow 的`Hello World`。 您創建了一個包含單個`tf.constant`的圖,該圖只是一個常數張量。 將字符串傳遞給張量時,推斷其為字符串類型。 然后,您創建了一個 TensorFlow 會話,這是運行圖所必需的,并將您創建的張量上的會話告知`run`。 然后打印出會話運行的結果。 那里有一個額外的`b`,因為它是一個字節流。
如果沒有看到上述內容并且出現一些錯誤,則最好的選擇是檢查以下頁面,以獲取安裝時遇到的常見問題的解決方案:
+ [Ubuntu](https://www.tensorflow.org/install/install_linux#common_installation_problems)
+ [Windows](https://www.tensorflow.org/install/install_windows#common_installation_problems)
# TensorFlow API 級別
在我們開始編寫 TensorFlow 代碼之前,了解 TensorFlow 在 Python 中提供的 API 抽象層次的不同很重要。 這樣,我們可以了解編寫代碼時可以使用的功能,還可以為工作選擇正確的功能或操作。 很多時候,幾乎不需要從頭開始重寫已經可以在 TensorFlow 中使用的東西。
TensorFlow 提供了三層 API 抽象來幫助編寫您的代碼,這些可以在下圖中可視化:

在最低級別上,您具有基本的 TensorFlow 操作,例如`tf.nn.conv2d`和`tf.nn.relu`。 使用 TensorFlow 時,這些低級原語為用戶提供了最大的控制權。 但是,使用它們的代價是在構造圖和編寫更多樣板代碼時必須自己動手做很多事情。
現在不用擔心理解以下任何代碼示例,我保證很快就會出現。 現在只是在這里展示 TensorFlow 中的不同 API 級別。
因此,例如,如果我們想創建一個卷積層以在我們的 ML 模型中使用,那么它可能類似于以下內容:
```py
def my_conv_2d(input, weight_shape, num_filters, strides):
my_weights = tf.get_variable(name="weights", shape=weight_shape)
my_bias = tf.get_variable(name="bias", shape=num_filters)
my_conv = tf.nn.conv2d(input, my_weights, strides=strides, padding='same', name='conv_layer1')
my_conv = tf.nn.bias_add(my_conv, my_bias)
conv_layer_out = tf.nn.relu(my_conv)
return conv_layer_out
```
這個示例比您實際實現的簡單得多,但是您已經可以看到開始建立代碼的行數,以及必須注意的事情,例如構造權重和添加偏置項。 一個模型也將具有許多不同種類的層,而不僅僅是卷積層,所有這些層都必須以與此非常相似的方式來構造。
因此,不僅要為模型中所需的每種新層將這些內容寫出來都非常費力,而且還引入了更多的區域,在這些區域中,錯誤可能會潛入您的代碼中,這從來都不是一件好事。
對我們來說幸運的是,TensorFlow 具有第二層抽象,可以幫助您簡化構建 TensorFlow 圖時的工作。 這種抽象級別的一個示例是層 API。 層 API 使您可以輕松處理許多機器學習任務中常見的許多構建基塊。
層 API 的工作方式是包裝我們在上一個示例中編寫的所有內容并將其抽象出來,因此我們不必再為它擔心。 例如,我們可以壓縮前面的代碼以將卷積層構造為一個函數調用。 與以前建立相同的卷積層現在看起來像這樣:
```py
def my_conv_2d(input, kernel_size, num_filters, strides):
conv_layer_out = tf.layers.conv2d(input, filters=num_filters, kernel_size=kernel_size, strides=strides, padding='same', activation=tf.nn.relu, name='conv_layer1')
return conv_layer_out
```
還有兩個與各層一起工作的 API。 第一個是數據集 API,可輕松將數據加載和饋送到 TensorFlow 圖。 第二個是指標 API,它提供工具來測試您訓練有素的機器學習模型的運行狀況。 我們將在本書的后面部分中學習所有這些內容。
API 棧的最后一層是 TensorFlow 提供的最高抽象層,這稱為估計器 API。 就像使用`tf.layers`來構造權重并為單個層添加偏差一樣,估計器 API 封裝了許多層的結構,以便我們可以將一個由多個不同層組成的整體模型定義為一個函數調用。
本書不會介紹估計器 API 的用法,但是如果讀者希望了解有關估計器的更多信息,可以在 TensorFlow 網站上找到一些有用的教程。
本書將重點介紹如何使用低級 API 以及層,數據集和指標 API 來構建,訓練和評估自己的 ML 模型。 我們相信,通過使用這些較低級別的 API,讀者將對 TensorFlow 的幕后工作方式有更深入的了解,并有能力更好地應對可能需要使用這些較低級別 API 的各種未來問題。
# 急切執行
在撰寫本文時,Google 剛剛將急切的執行 API 引入了 TensorFlow。 急切執行是 TensorFlow 對另一個名為 PyTorch 的深度學習庫的回答。 它允許您繞過通常的 TensorFlow 工作方式,在這種方式下,您必須首先定義計算圖,然后執行該圖以獲得結果。 這稱為靜態圖計算。 相反,現在您可以使用急切執行創建在運行程序時動態定義的所謂動態圖。 使用 TensorFlow 時,這允許使用更傳統的命令式編程方式。 不幸的是,急切的執行仍在開發中,缺少某些功能,因此在本書中不作介紹。 可以在 TensorFlow 網站上找到有關急切執行的更多信息。
# 建立您的第一個 TensorFlow 模型
事不宜遲,讓我們開始在 TensorFlow 中構建您的第一個 ML 模型。
我們將在本章中解決的問題是從四個給定的特征值正確識別鳶尾花的種類。 這是一個非常容易解決的經典 ML 問題,但它將為我們提供一種很好的方式來介紹在 TensorFlow 中構建圖,饋送數據和訓練 ML 模型的基礎知識。
鳶尾數據集由 150 個數據點組成,每個數據點具有四個相應的特征:長度,花瓣寬度,萼片長度和萼片寬度以及目標標簽。 我們的任務是建立一個模型,僅給出這四個特征就可以推斷出任何鳶尾的目標標簽。
讓我們開始加載數據并進行處理。 TensorFlow 具有內置功能,可以為我們導入此特定數據集,因此讓我們繼續使用它。 由于我們的數據集很小,因此將整個數據集加載到內存中是可行的。 但是,不建議將其用于較大的數據集,并且在接下來的章節中,您將學到更好的處理此問題的方法。 以下代碼塊將為我們加載數據,然后對其進行解釋。
```py
import tensorflow as tf
import numpy as np
# Set random seed for reproducibility.
np.random.seed(0)
data, labels = tf.contrib.learn.datasets.load_dataset("iris")
num_elements = len(labels)
# Use shuffled indexing to shuffle dataset.
shuffled_indices = np.arange(len(labels))
np.random.shuffle(shuffled_indices)
shuffled_data = data[shuffled_indices]
shuffled_labels = labels[shuffled_indices]
# Transform labels into one hot vectors.
one_hot_labels = np.zeros([num_elements,3], dtype=int)
one_hot_labels[np.arange(num_elements), shuffled_labels] = 1
# Split data into training and testing sets.
train_data = shuffled_data[0:105]
train_labels = shuffled_labels[0:105]
test_data = shuffled_data[105:]
test_labels = shuffled_labels[105:]
```
讓我們再次看一下這段代碼,看看到目前為止我們做了什么。 導入 TensorFlow 和 Numpy 之后,我們將整個數據集加載到內存中。 我們的數據由表示為向量的四個數值特征組成。 我們總共有 150 個數據點,因此我們的數據將是形狀為`150 x 4`的矩陣,其中每一行代表不同的數據點,每一列代表不同的特征。 每個數據點還具有與之關聯的目標標簽,該目標標簽存儲在單獨的標簽向量中。
接下來,我們重新整理數據集; 這一點很重要,因此,當我們將其分為訓練集和測試集時,我們在這兩個集之間平均分配,并且最終不會在一組集中獲得所有一種類型的數據。
# 單熱向量
改組后,我們對數據標簽進行一些預處理。 隨數據集加載的標簽只是一個 150 長度的整數向量,表示每個數據點所屬的目標類,在這種情況下為 1、2 或 3。 在創建機器學習模型時,我們希望將標簽轉換為一種新的形式,通過執行一種稱為“單熱編碼”的方式可以更輕松地使用它。
不是使用單個數字作為每個數據點的標簽,而是使用向量。 每個向量將與您擁有的不同目標類別的數目一樣長。 因此,例如,如果您有 5 個目標類,則每個向量將有 5 個元素;例如, 如果您有 1,000 個目標類別,則每個向量將具有 1,000 個元素。 向量中的每一列代表我們的目標類別之一,我們可以使用二進制值來確定向量是其標簽的類別。 可以通過將所有值設置為 0 并將 1 放入我們希望向量標簽表示的類的列中來完成。
用一個例子很容易理解。 對于這個特定問題的標簽,轉換后的向量將如下所示:
```py
1 = [1,0,0]
2 = [0,1,0]
3 = [0,0,1]
```
# 分為訓練和測試集
最后,我們將數據集的一部分放到一邊。 這就是我們的測試集,在我們訓練模型之后我們才接觸它。 該集合用于評估我們訓練有素的模型對從未見過的新數據的表現。 有許多方法可以將數據分為訓練集和測試集,我們將在本書的后面詳細介紹它們。
但就目前而言,我們將進行一個簡單的 70:30 拆分,因此我們僅使用總數據的 70% 來訓練我們的模型,然后對剩余的 30% 進行測試。
# 創建 TensorFlow 圖
現在我們的數據都已經設置好了,我們可以構建模型來學習如何對鳶尾花進行分類。 我們將構建最簡單的機器學習模型之一-線性分類器,如下所示:

線性分類器通過計算輸入特征向量`x`和權重向量`w`之間的點積來工作。 在計算出點積之后,我們向結果添加一個值,稱為偏差項`b`。 在我們的例子中,我們有三種可能的類別,任何輸入特征向量都可能屬于該類別,因此我們需要使用`w[1]`,`w[2]`計算三種不同的點積,`w[3]`以查看其屬于哪個類別。 但是,我們不必寫出三個單獨的點積,而只需在形狀`[3, 4]`的權重矩陣與輸入向量之間做一個矩陣乘法。 在下圖中,我們可以更清楚地看到它的外觀:

我們還可以將該方程簡化為更緊湊的形式,如下所示,其中我們的權重矩陣為`W`,偏差為`b`,`x`是我們的輸入特征向量,結果輸出為`s`:

# 變量
我們如何在 TensorFlow 代碼中全部寫出來? 讓我們開始創建權重和偏置。 在 TensorFlow 中,如果我們想創建一些可以被我們的代碼操縱的張量,那么我們需要使用 TensorFlow 變量。 TensorFlow 變量是`tf.Variable`類的實例。 `tf.Variable`類表示`tf.Tensor`對象,可以通過在其上運行 TensorFlow 操作來更改其值。 變量是類似于張量的對象,因此它們可以以與張量相同的方式傳遞,并且可以與張量一起使用的任何操作都可以與變量一起使用。
要創建變量,我們可以使用`tf.get_variable()`。 調用此函數時,必須提供變量的名稱。 此函數將首先檢查圖上是否沒有其他具有相同名稱的變量,如果沒有,則它將創建新變量并將其添加到 TensorFlow 圖。
您還必須指定變量要具有的形狀,或者,可以使用`tf.constant`張量來初始化變量。 變量將采用您的常數張量的值,并且形狀將自動推斷。 例如,以下代碼將產生一個包含值 21 和 25 的`1x2`張量:
```py
my_variable = tf.get_variable(name= "my_variable", initializer=tf.constant([21, 25]))
```
# 工作方式
在圖中有變量很好,但我們也想對它們做點什么。 我們可以使用 TensorFlow 操作來操作我們的變量。
如前所述,我們的線性分類器只是一個矩陣乘法運算,因此您將要使用的第一個運算很有趣地成為矩陣乘法運算。 只需在您要相乘的兩個張量上調用`tf.matmul()`,結果將是您傳入的兩個張量的矩陣相乘。簡單!
在整本書中,您將了解需要使用的許多不同的 TensorFlow 操作。
現在,您希望對變量和操作有所了解,讓我們構建線性模型。 我們將在函數中定義模型。 該函數將以 N 個特征向量為輸入,或更準確地說,以 N 個大小為一批。由于我們的特征向量的長度為 4,所以我們的批次將是`[N, 4]`形狀張量。 然后該函數將返回線性模型的輸出。 在下面的代碼中,我們編寫了線性模型函數,該函數應該可以自我解釋,但是如果您還沒有完全理解它,請繼續閱讀。
```py
def linear_model(input):
# Create variables for our weights and biases
my_weights = tf.get_variable(name="weights", shape=[4,3])
my_bias = tf.get_variable(name="bias", shape=[3])
# Create a linear classifier.
linear_layer = tf.matmul(input, my_weights)
linear_layer_out = tf.nn.bias_add(value=linear_layer, bias=my_bias)
return linear_layer_out
```
在此處的代碼中,我們創建了將存儲權重和偏差的變量。 我們給他們起名字并提供所需的形狀。 請記住,我們使用變量是因為我們想通過操作來操縱它們的值。
接下來,我們創建一個`tf.matmul`節點,將我們的輸入特征矩陣和權重矩陣作為參數。 可以通過我們的`linear_layer` Python 變量訪問此操作的結果。 然后將該結果傳遞給另一個運算符`tf.nn.bias_add`。 該運算來自 **NN**(**神經網絡**)模塊,在我們希望向計算結果中添加偏差向量時使用。 偏差必須是一維張量。
# 使用占位符饋送數據
占位符是類似張量的對象。 它們是您與 TensorFlow 之間的合同,該合同規定,當您在會話中運行計算圖時,您將提供*數據*或將數據饋入該占位符,以便您的圖可以成功運行。
它們就像張量一樣,就像張量一樣,意味著您可以將它們傳遞到放置張量的地方。
通過使用占位符,我們可以向圖中提供外部輸入,這些輸入可能會在每次運行圖時更改。 它們的自然用法是將數據和標簽提供到模型中的一種方式,因為每次我們要運行圖時,我們提供的數據和標簽通常都會有所不同。
創建占位符時,我們必須提供將要填充的數據類型。
我們將使用兩個占位符將數據和標簽提供到圖中。 我們還提供了饋入這些占位符的任何數據都必須采用的形狀。 我們使用`None`表示該特定尺寸的大小可以為任何值。 這樣,我們就可以批量輸入大小不同的數據。 接下來,我們將看到如何在 TensorFlow 中為我們的問題定義占位符。
```py
x = tf.placeholder(tf.float32, shape=[None, 4], name="data_in")
y = tf.placeholder(tf.int32, shape=[None, 3], name="target_labels")
```
現在,我們在圖中創建了占位符,因此我們也可以在圖上構造線性模型。 我們調用之前定義的函數,并提供數據占位符`x`作為輸入。 請記住,占位符的行為類似于張量,因此它們也可以像它們一樣被傳遞。 在以下代碼中,我們使用占位符作為輸入參數來調用`linear_model`函數。
```py
model_out = linear_model(x)
```
當我們調用函數時,函數中的所有內容都會執行,所有操作和變量都將添加到 TensorFlow 圖中。 我們只需要這樣做一次。 如果我們再次嘗試調用函數,則會收到一條錯誤消息,說明我們已嘗試向圖添加變量,但變量已經存在。
占位符是向我們的圖中提供外部數據的最簡單,最快的方法,因此很高興了解它們。 稍后,我們將看到使用數據集 API 提供數據的更好方法,但是就目前而言,占位符是一個不錯的起點。
# 初始化變量
在我們能夠在圖中使用變量之前,我們必須對其進行初始化。 我們需要創建一個圖節點來為我們做到這一點。 使用`tf.global_variables_initializer`將向我們的圖添加一個初始化器節點。 如果我們在會話中運行該節點,那么圖中的所有變量都將被初始化,以便我們可以使用它們。 因此,現在,讓我們創建一個初始化器節點,如下所示:
```py
initializer = tf.global_variables_initializer()
```
正如我們沒有明確說明要對變量使用哪種初始化一樣,TensorFlow 將使用默認的一種稱為 Glorot 正態初始化的方法,也稱為 Xavier 初始化。
# 訓練我們的模型
我們已經構建了線性模型的圖,并且可以向其中提供數據。 如果我們創建一個會話并在提供一些輸入數據的同時運行`model_out`張量,那么我們將得到一個結果。 但是,我們得到的輸出將完全是垃圾。 我們的模型尚未訓練! 當我們使用初始化節點初始化變量時,權重和偏差的值僅具有默認值。
# 損失函數
要訓??練我們的模型,我們必須定義一些稱為損失函數的函數。 損失函數將告訴我們我們的模型目前做得如何好壞。
損失可在`tf.losses`模塊中找到。 對于此模型,我們將使用鉸鏈損失。 鉸鏈損失是創建**支持向量機**(**SVM**)時使用的損失函數。 鉸鏈損失嚴重懲罰了錯誤的預測。 對于一個給定的示例`(x[i], y[i])`,其中`x[i]`是數據點的特征向量,`y[i]`是其標記,其鉸鏈損失如下:

為此,以下內容將適用:

簡而言之,該方程式采用分類器的原始輸出。 在我們的模型中,這是三個輸出分數,并確保目標類別的分數至少比其他類別的分數大至少 1。 對于每個分數(目標類別除外),如果滿足此限制,則將損失加 0,否則,將增加罰款:

這個概念實際上是非常直觀的,因為如果我們的權重和偏置得到了正確的訓練,那么所產生的三個得分中的最高得分就可以自信地表明輸入示例所屬的正確類別。
由于在訓練期間,我們會一次輸入許多訓練示例,因此,我們將獲得多個需要平均的損失。 因此,需要最小化的總損失方程如下:

在我們的代碼中,損失函數將帶有兩個參數:`logits`和`label`。 在 TensorFlow 中,`logits`是我們的模型產生的原始值的名稱。 在我們的例子中,這是`model_out`,因為這是我們模型的輸出。 對于標簽,我們使用標簽占位符`y`。 請記住,占位符將在運行時為我們填充:
```py
loss = tf.reduce_mean(tf.losses.hinge_loss(logits=model_out, labels=y))
```
由于我們也想對整個輸入數據的損失進行平均,因此我們使用`tf.reduce_mean`將所有損失平均為一個損失值,將其最小化。
有許多不同類型的損失函數可供我們使用,這些函數對于不同的機器學習任務都是有益的。 在閱讀本書時,我們將學習更多這些內容以及何時使用不同的損失函數。
# 優化
現在我們定義了要使用的損失函數; 我們可以使用這個損失函數來訓練我們的模型。 如前面的方程式所示,損失函數是權重和偏差的函數。 因此,我們要做的就是詳盡地搜索權重和偏差的空間,并查看哪種組合最大程度地減少了損失。 當我們具有一維或二維權向量時,此過程可能還可以,但是當權向量空間太大時,我們需要一個更有效的解決方案。 為此,我們將使用一種名為**梯度下降**的優化技術。
通過使用損失函數和演算,梯度下降法可以看到如何調整模型權重和偏差的值,以使損失值減小。 這是一個迭代過程,需要多次迭代才能針對我們的訓練數據對權重和偏差的值進行適當調整。 這個想法是,通過相對于目標函數`?[w]L(w)`的梯度的相反方向更新參數,可以最小化由權重`w`參數化的損失函數`L`。 權重和偏差的更新功能如下所示:


在這里,`t`是迭代次數,`α`是稱為學習率的超參數。
由兩個變量`w1`和`w2`參數化的損失函數將如下圖所示:

上圖顯示了橢圓拋物面的水平曲線。 這是一個碗形的表面,碗的底部位于中心。 從圖中可以看出,在點`a`(黑色直箭頭)處的梯度向量垂直于通過`a`的水平曲線。 實際上,梯度向量指向損失函數最大增加率的方向。
因此,如果我們從*點*開始并朝與相反的*方向*將權重更新為梯度向量,那么我們將下降至`b`點,然后在下一次迭代到`c`,依此類推,直到達到最小值。 選擇使損失函數最小的參數來表示最終的訓練線性模型。
TensorFlow 的好處在于,它使用其內置的優化器(稱為**自動微分**)為我們計算了所有所需的梯度。 我們要做的就是選擇一個梯度下降優化器,并告訴它最小化我們的損失函數。 TensorFlow 將自動計算所有梯度,然后使用這些梯度為我們更新權重。
我們可以在`tf.train`模塊中找到優化程序類。 現在,我們將使用`GradientDescentOptimizer`類,它只是基本的梯度下降優化算法。 創建優化器時,我們必須提供學習率。 學習率的值是`hyperparameter`,用戶必須通過反復試驗和實驗來對其進行調整。 0.5 的值應該可以很好地解決此問題。
優化器節點具有一種稱為`minimize`的方法。 在您提供的損失函數上調用此方法會做兩件事。 首先,針對您的整個圖計算與該損失有關的梯度。 其次,這些梯度用于更新所有相關變量。
創建我們的優化器節點將如下所示:
```py
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.5).minimize(loss)
```
與損失函數一樣,有很多不同的梯度下降優化器需要學習。 這里介紹的是最基本的一種,但是再次,我們將在以后的章節中學習和使用不同的類型。
# 評估訓練好的模型
我們匯總了訓練模型所需的所有零件。 開始訓練之前的最后一件事是,我們想在圖中創建一些節點,這些節點將使我們能夠在完成訓練后測試模型的執行情況。
我們將創建一個節點來計算模型的準確率。
`Tf.equal`將返回一個布爾列表,指示兩個提供的列表在哪里相等。 在找到最大值的索引之后,在這種情況下,我們的兩個列表將是模型的標簽和輸出:
```py
correct_prediction = tf.equal(tf.argmax(model_out,1), tf.argmax(y,1))
```
然后,我們可以再次使用`reduce_mean`來獲得正確預測的平均數量。 不要忘記將我們的`boolean correct_prediction`列表投射回`float32`:
```py
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
```
# 會話
現在,我們已經構造了計算圖的所有部分。 我們需要做的最后一件事是創建一個`tf.Session`并運行我們的圖。 TensorFlow 會話是一種將用 Python 編寫的 TensorFlow 程序與為 TensorFlow 供電的 C++ 運行時連接的一種方式。 該會話還使 TensorFlow 可以訪問本地或遠程計算機上存在的設備,例如 CPU 和 GPU。 另外,該會話將緩存有關構造圖的信息,因此可以有效地多次運行計算。
創建會話的標準方法是使用 Python 上下文管理器:`with`語句塊:
```py
with tf.Session() as sess:.
```
原因是創建會話時,它可以控制計算機上的 CPU,內存和 GPU 資源。 使用完會話后,您希望再次釋放所有這些資源,最簡單的方法是使用`with`語句來確保這一點。
創建會話后,我們要做的第一件事是運行初始化器操作。 通過在要評估的圖對象上調用`tf.Session.run`,可以使用會話來求值圖中的節點和張量。 當您將圖的一部分提供給`session.run`時,TensorFlow 將在整個圖中進行工作,求值所提供的圖部分所依賴的所有內容以產生結果。
因此,在我們的示例中,調用`sess.run(initializer)`將在圖中進行搜索,查找執行初始化器所需的所有內容,然后按順序執行這些節點。 在這種情況下,初始化器節點沒有任何連接,因此它將簡單地執行一個初始化所有變量的節點。
現在我們的變量已初始化,我們開始訓練循環。 我們將訓練 1000 個步驟或迭代,因此我們將在其中創建訓練步驟的`for`循環。 訓練的步驟數是`hyperparameter`。 這是我們在訓練模型時需要決定的事情。 您可以選擇與您選擇的值進行權衡,這將在以后的章節中進行討論。 對于此問題,1000 個步驟將足以獲得所需的結果。
我們獲取了一批訓練數據和標簽,并將它們輸入到圖中。 接下來,我們再次調用`session.run`。 這次,我們將其稱為損失和優化器兩件事。 通過將它們放在我們提供給`session.run`的列表中,我們可以提供想要求值的事物。 TensorFlow 將足夠聰明,如果不需要,它不會多次求值圖,并且它將重用已經計算出的結果。 我們提供的這個列表稱為我們的提取; 它是我們要求值和獲取的圖中的節點。
在提取列表之后,我們提供了`feed_dict`或饋送字典。 這是一個字典,其中的每個鍵都是圖中的張量,我們將向該張量輸入值(在本例中為占位符),而對應的值就是將被輸入到它的值。
`session.run`的返回值對應于我們的提取列表中的每個值。 我們的第一個獲取是圖中的損失張量,因此第一個`return`參數來自此。 第二個獲取是優化器節點。 我們不在乎從該節點返回什么,因為我們只在乎優化器節點的計算結果,因此我們將其對應的返回值留空:
```py
with tf.Session() as sess:
sess.run(initializer)
for i in range(1000):
batch_x, batch_y = train_data[:,:], train_labels[:,:]
loss_val, _ = sess.run([loss, optimizer], feed_dict={x : batch_x, y: batch_y})
print("Train Accuracy:", sess.run(accuracy, feed_dict={x: train_data, y: train_labels}))
print("Test Accuracy:", sess.run(accuracy, feed_dict={x: test_data, y: test_labels}))
```
運行 1000 次迭代后,我們使用另一個`session.run`調用來獲取精度節點的輸出。 我們執行兩次,一次輸入我們的訓練數據以獲取訓練集的準確率,一次輸入我們保留的測試數據以獲取測試集的準確率。 您應該從`0.977778`中打印出測試精度,這意味著我們的模型可以正確分類 45 個測試集中的 44 個,一點也不差!
# 總結
在本章中,我們已經說明了使用 TensorFlow 進行編程的方式以及如何為使用 TensorFlow 設置工作環境。 我們還研究了如何使用 TensorFlow 對鳶尾花朵進行分類來構建,訓練和評估自己的線性模型。 在此過程中,我們簡要介紹了損失函數和梯度下降優化器。
在下一章中,我們將更多地了解一些關鍵的深度學習概念,包括卷積神經網絡。 我們還將研究如何使用 TensorFlow 來構建和訓練深度神經網絡。
- TensorFlow 1.x 深度學習秘籍
- 零、前言
- 一、TensorFlow 簡介
- 二、回歸
- 三、神經網絡:感知器
- 四、卷積神經網絡
- 五、高級卷積神經網絡
- 六、循環神經網絡
- 七、無監督學習
- 八、自編碼器
- 九、強化學習
- 十、移動計算
- 十一、生成模型和 CapsNet
- 十二、分布式 TensorFlow 和云深度學習
- 十三、AutoML 和學習如何學習(元學習)
- 十四、TensorFlow 處理單元
- 使用 TensorFlow 構建機器學習項目中文版
- 一、探索和轉換數據
- 二、聚類
- 三、線性回歸
- 四、邏輯回歸
- 五、簡單的前饋神經網絡
- 六、卷積神經網絡
- 七、循環神經網絡和 LSTM
- 八、深度神經網絡
- 九、大規模運行模型 -- GPU 和服務
- 十、庫安裝和其他提示
- TensorFlow 深度學習中文第二版
- 一、人工神經網絡
- 二、TensorFlow v1.6 的新功能是什么?
- 三、實現前饋神經網絡
- 四、CNN 實戰
- 五、使用 TensorFlow 實現自編碼器
- 六、RNN 和梯度消失或爆炸問題
- 七、TensorFlow GPU 配置
- 八、TFLearn
- 九、使用協同過濾的電影推薦
- 十、OpenAI Gym
- TensorFlow 深度學習實戰指南中文版
- 一、入門
- 二、深度神經網絡
- 三、卷積神經網絡
- 四、循環神經網絡介紹
- 五、總結
- 精通 TensorFlow 1.x
- 一、TensorFlow 101
- 二、TensorFlow 的高級庫
- 三、Keras 101
- 四、TensorFlow 中的經典機器學習
- 五、TensorFlow 和 Keras 中的神經網絡和 MLP
- 六、TensorFlow 和 Keras 中的 RNN
- 七、TensorFlow 和 Keras 中的用于時間序列數據的 RNN
- 八、TensorFlow 和 Keras 中的用于文本數據的 RNN
- 九、TensorFlow 和 Keras 中的 CNN
- 十、TensorFlow 和 Keras 中的自編碼器
- 十一、TF 服務:生產中的 TensorFlow 模型
- 十二、遷移學習和預訓練模型
- 十三、深度強化學習
- 十四、生成對抗網絡
- 十五、TensorFlow 集群的分布式模型
- 十六、移動和嵌入式平臺上的 TensorFlow 模型
- 十七、R 中的 TensorFlow 和 Keras
- 十八、調試 TensorFlow 模型
- 十九、張量處理單元
- TensorFlow 機器學習秘籍中文第二版
- 一、TensorFlow 入門
- 二、TensorFlow 的方式
- 三、線性回歸
- 四、支持向量機
- 五、最近鄰方法
- 六、神經網絡
- 七、自然語言處理
- 八、卷積神經網絡
- 九、循環神經網絡
- 十、將 TensorFlow 投入生產
- 十一、更多 TensorFlow
- 與 TensorFlow 的初次接觸
- 前言
- 1.?TensorFlow 基礎知識
- 2. TensorFlow 中的線性回歸
- 3. TensorFlow 中的聚類
- 4. TensorFlow 中的單層神經網絡
- 5. TensorFlow 中的多層神經網絡
- 6. 并行
- 后記
- TensorFlow 學習指南
- 一、基礎
- 二、線性模型
- 三、學習
- 四、分布式
- TensorFlow Rager 教程
- 一、如何使用 TensorFlow Eager 構建簡單的神經網絡
- 二、在 Eager 模式中使用指標
- 三、如何保存和恢復訓練模型
- 四、文本序列到 TFRecords
- 五、如何將原始圖片數據轉換為 TFRecords
- 六、如何使用 TensorFlow Eager 從 TFRecords 批量讀取數據
- 七、使用 TensorFlow Eager 構建用于情感識別的卷積神經網絡(CNN)
- 八、用于 TensorFlow Eager 序列分類的動態循壞神經網絡
- 九、用于 TensorFlow Eager 時間序列回歸的遞歸神經網絡
- TensorFlow 高效編程
- 圖嵌入綜述:問題,技術與應用
- 一、引言
- 三、圖嵌入的問題設定
- 四、圖嵌入技術
- 基于邊重構的優化問題
- 應用
- 基于深度學習的推薦系統:綜述和新視角
- 引言
- 基于深度學習的推薦:最先進的技術
- 基于卷積神經網絡的推薦
- 關于卷積神經網絡我們理解了什么
- 第1章概論
- 第2章多層網絡
- 2.1.4生成對抗網絡
- 2.2.1最近ConvNets演變中的關鍵架構
- 2.2.2走向ConvNet不變性
- 2.3時空卷積網絡
- 第3章了解ConvNets構建塊
- 3.2整改
- 3.3規范化
- 3.4匯集
- 第四章現狀
- 4.2打開問題
- 參考
- 機器學習超級復習筆記
- Python 遷移學習實用指南
- 零、前言
- 一、機器學習基礎
- 二、深度學習基礎
- 三、了解深度學習架構
- 四、遷移學習基礎
- 五、釋放遷移學習的力量
- 六、圖像識別與分類
- 七、文本文件分類
- 八、音頻事件識別與分類
- 九、DeepDream
- 十、自動圖像字幕生成器
- 十一、圖像著色
- 面向計算機視覺的深度學習
- 零、前言
- 一、入門
- 二、圖像分類
- 三、圖像檢索
- 四、對象檢測
- 五、語義分割
- 六、相似性學習
- 七、圖像字幕
- 八、生成模型
- 九、視頻分類
- 十、部署
- 深度學習快速參考
- 零、前言
- 一、深度學習的基礎
- 二、使用深度學習解決回歸問題
- 三、使用 TensorBoard 監控網絡訓練
- 四、使用深度學習解決二分類問題
- 五、使用 Keras 解決多分類問題
- 六、超參數優化
- 七、從頭開始訓練 CNN
- 八、將預訓練的 CNN 用于遷移學習
- 九、從頭開始訓練 RNN
- 十、使用詞嵌入從頭開始訓練 LSTM
- 十一、訓練 Seq2Seq 模型
- 十二、深度強化學習
- 十三、生成對抗網絡
- TensorFlow 2.0 快速入門指南
- 零、前言
- 第 1 部分:TensorFlow 2.00 Alpha 簡介
- 一、TensorFlow 2 簡介
- 二、Keras:TensorFlow 2 的高級 API
- 三、TensorFlow 2 和 ANN 技術
- 第 2 部分:TensorFlow 2.00 Alpha 中的監督和無監督學習
- 四、TensorFlow 2 和監督機器學習
- 五、TensorFlow 2 和無監督學習
- 第 3 部分:TensorFlow 2.00 Alpha 的神經網絡應用
- 六、使用 TensorFlow 2 識別圖像
- 七、TensorFlow 2 和神經風格遷移
- 八、TensorFlow 2 和循環神經網絡
- 九、TensorFlow 估計器和 TensorFlow HUB
- 十、從 tf1.12 轉換為 tf2
- TensorFlow 入門
- 零、前言
- 一、TensorFlow 基本概念
- 二、TensorFlow 數學運算
- 三、機器學習入門
- 四、神經網絡簡介
- 五、深度學習
- 六、TensorFlow GPU 編程和服務
- TensorFlow 卷積神經網絡實用指南
- 零、前言
- 一、TensorFlow 的設置和介紹
- 二、深度學習和卷積神經網絡
- 三、TensorFlow 中的圖像分類
- 四、目標檢測與分割
- 五、VGG,Inception,ResNet 和 MobileNets
- 六、自編碼器,變分自編碼器和生成對抗網絡
- 七、遷移學習
- 八、機器學習最佳實踐和故障排除
- 九、大規模訓練
- 十、參考文獻