# 二、TensorFlow 的方式
在本章中,我們將介紹 TensorFlow 如何運作的關鍵組件。然后,我們將它們組合在一起以創建一個簡單的分類器并評估結果。到本章結束時,您應該了解以下內容:
* 計算圖中的操作
* 分層嵌套操作
* 使用多個層
* 實現損失函數
* 實現反向傳播
* 使用批量和隨機訓練
* 把所有東西結合在一起
* 評估模型
# 介紹
現在我們已經介紹了 TensorFlow 如何創建張量,并使用變量和占位符,我們將介紹如何在計算圖中對這些對象進行操作。由此,我們可以設置一個簡單的分類器,看看它的表現如何。
> 此外,請記住,[本書中的當前和更新代碼可以在 GitHub 上在線獲取](https://github.com/nfmcclure/tensorflow_cookbook)。
# 計算圖中的操作
現在我們可以將對象放入計算圖中,我們將介紹對這些對象起作用的操作。
## 準備
要啟動圖,我們加載 TensorFlow 并創建一個會話,如下所示:
```py
import tensorflow as tf
sess = tf.Session()
```
## 操作步驟
在這個例子中,我們將結合我們學到的東西并將列表中的每個數字提供給圖中的操作并打印輸出:
首先,我們宣布我們的張量和占位符。在這里,我們將創建一個 NumPy 數組來提供給我們的操作:
```py
import numpy as np
x_vals = np.array([1., 3., 5., 7., 9.])
x_data = tf.placeholder(tf.float32)
m_const = tf.constant(3.)
my_product = tf.multiply(x_data, m_const)
for x_val in x_vals:
print(sess.run(my_product, feed_dict={x_data: x_val}))
```
上述代碼的輸出如下:
```py
3.0
9.0
15.0
21.0
27.0
```
## 工作原理
本節中的代碼在計算圖上創建數據和操作。下圖是計算圖的樣子:

圖 1:`x_data`占位符以及乘法常數輸入到乘法運算中
# 對嵌套操作分層
在本文中,我們將學習如何在同一計算圖上放置多個操作。
## 準備
了解如何將操作鏈接在一起非常重要。這將在計算圖中設置分層操作。對于演示,我們將占位符乘以兩個矩陣,然后執行加法。我們將以三維 NumPy 數組的形式提供兩個矩陣:
```py
import tensorflow as tf
sess = tf.Session()
```
## 操作步驟
同樣重要的是要注意數據在通過時如何改變形狀。我們將輸入兩個大小為`3 x 5`的 NumPy 數組。我們將每個矩陣乘以一個大小常數`5 x 1,`,這將產生一個大小為`3 x 1`的矩陣。然后我們將其乘以`1 x 1`矩陣,再次產生`3 x 1`矩陣。最后,我們在最后添加`3 x 1`矩陣,如下所示:
1. 首先,我們創建要輸入的數據和相應的占位符:
```py
my_array = np.array([[1., 3., 5., 7., 9.],
[-2., 0., 2., 4., 6.],
[-6., -3., 0., 3., 6.]])
x_vals = np.array([my_array, my_array + 1])
x_data = tf.placeholder(tf.float32, shape=(3, 5))
```
1. 接下來,我們創建將用于矩陣乘法和加法的常量:
```py
m1 = tf.constant([[1.], [0.], [-1.], [2.], [4.]])
m2 = tf.constant([[2.]])
a1 = tf.constant([[10.]])
```
1. 現在,我們聲明操作并將它們添加到圖中:
```py
prod1 = tf.matmul(x_data, m1)
prod2 = tf.matmul(prod1, m2)
add1 = tf.add(prod2, a1)
```
1. 最后,我們為圖提供數據:
```py
for x_val in x_vals:
print(sess.run(add1, feed_dict={x_data: x_val}))
[[ 102.]
[ 66.]
[ 58.]]
[[ 114.]
[ 78.]
[ 70.]]
```
## 工作原理
我們剛剛創建的計算圖可以使用 TensorBoard 進行可視化。 TensorBoard 是 TensorFlow 的一個功能,它允許我們可視化計算圖和這些圖中的值。與其他機器學習框架不同,這些功能是本機提供的。要了解如何完成此操作,請參閱第 11 章中的 TensorBoard 秘籍中的可視化圖,更多內容使用 TensorFlow。以下是我們的分層圖如下所示:

圖 2:向上傳播到圖時的數據大小
## 更多
在通過圖運行數據之前,我們必須聲明數據形狀并知道操作的結果形狀。這并非總是如此。可能有一兩個我們事先不知道的維度,或者一些可能變化的維度。為實現此目的,我們將可以改變(或未知)的維度或維度指定為值`None`。例如,要使先前的數據占位符具有未知數量的列,我們將編寫以下行:
```py
x_data = tf.placeholder(tf.float32, shape=(3,None))
```
這允許我們打破矩陣乘法規則,但我們仍然必須遵守乘法常數必須具有相同行數的事實。當我們將數據輸入圖時,我們可以動態生成或重新整形`x_data`。當我們以不同批次大小的多批次提供數據時,這將在后面的章節中派上用場。
> 雖然使用`None`作為大小允許我們使用可變大小的大小,但在填充大小時始終建議盡可能明確。如果我們將大小標準化為固定大小,那么我們應該明確地將該大小寫為大小。建議將`None`用作維度,以限制數據的批量大小(或我們一次計算的數據點數)。
# 使用多個層
現在我們已經介紹了多個操作,我們將介紹如何連接具有通過它們傳播的數據的各個層。
## 準備
在本文中,我們將介紹如何最好地連接各種層,包括自定義層。我們將生成和使用的數據將代表小型隨機圖像。最好通過一個簡單的例子來理解這種類型的操作,看看我們如何使用一些內置層來執行計算。我們將探索的第一層稱為移動窗口。我們將在 2D 圖像上執行小的移動窗口平均值,然后第二層將是自定義操作層。
在本節中,我們將看到計算圖可能變得龐大且難以查看。為了解決這個問題,我們還將介紹命名操作和創建層范圍的方法。首先,加載`numpy`和`tensorflow`,然后使用以下命令創建圖:
```py
import tensorflow as tf
import numpy as np
sess = tf.Session()
```
## 操作步驟
我們按如下方式處理秘籍:
1. 首先,我們使用 NumPy 創建示例 2D 圖像。該圖像將是`4 x 4`像素圖像。我們將在四個方面創建它;第一個和最后一個維度的大小為 1。請注意,某些 TensorFlow 圖像函數將在四維圖像上運行。這四個維度是圖像編號,高度,寬度和通道,為了使其成為一個具有一個通道的圖像,我們將兩個維度設置為`1`,如下所示:
```py
x_shape = [1, 4, 4, 1]
x_val = np.random.uniform(size=x_shape)
```
1. 現在,我們必須在圖中創建占位符,我們可以在其中提供示例圖像,如下所示:
```py
x_data = tf.placeholder(tf.float32, shape=x_shape)
```
1. 為了在我們的`4 x 4`圖像上創建一個移動窗口平均值,我們將使用一個內置函數,它將在形狀窗口`2 x 2`上收斂一個常量。我們將使用的函數是`conv2d()`;此函數在圖像處理和 TensorFlow 中非常常用。此函數采用窗口的分段產品和我們指定的過濾器。我們還必須在兩個方向上指定移動窗口的步幅。在這里,我們將計算四個移動窗口平均值:左上角,右上角,左下角和右下角四個像素。我們通過創建`2 x 2`窗口并在每個方向上具有長度`2`的步幅來實現這一點。為取平均值,我們將`2 x 2`窗口用`0.25`的常數卷積,如下:
```py
my_filter = tf.constant(0.25, shape=[2, 2, 1, 1])
my_strides = [1, 2, 2, 1]
mov_avg_layer= tf.nn.conv2d(x_data, my_filter, my_strides,
padding='SAME', name='Moving_Avg_Window')
```
> 請注意,我們還使用函數的`name`參數命名此層`Moving_Avg_Window`。 為了計算卷積層的輸出大小,我們可以使用下面的公式`: Output = (W - F + 2P) / S + 1`,其中`W`是輸入大小,`F`是過濾器大小,`P`是零填充,并且`S`是步幅。
1. 現在,我們定義一個自定義層,它將在移動窗口平均值的`2 x 2`輸出上運行。自定義函數將首先將輸入乘以另一個`2 x 2`矩陣張量,然后為每個條目添加 1。在此之后,我們取每個元素的 sigmoid 并返回`2 x 2`矩陣。由于矩陣乘法僅對二維矩陣進行操作,因此我們需要刪除大小為`1`的圖像的額外維度。 TensorFlow 可以使用內置的`squeeze()`函數執行此操作。在這里,我們定義新層:
```py
def custom_layer(input_matrix):
input_matrix_sqeezed = tf.squeeze(input_matrix)
A = tf.constant([[1., 2.], [-1., 3.]])
b = tf.constant(1., shape=[2, 2])
temp1 = tf.matmul(A, input_matrix_sqeezed)
temp = tf.add(temp1, b) # Ax + b
return tf.sigmoid(temp)
```
1. 現在,我們必須將新層放在圖上。我們將使用命名范圍執行此操作,以便它在計算圖上可識別和可折疊/可擴展,如下所示:
```py
with tf.name_scope('Custom_Layer') as scope:
custom_layer1 = custom_layer(mov_avg_layer)
```
1. 現在,我們只需輸入`4 x 4`圖像來替換占位符并告訴 TensorFlow 運行圖,如下所示:
```py
print(sess.run(custom_layer1, feed_dict={x_data: x_val}))
[[ 0.91914582 0.96025133]
[ 0.87262219 0.9469803 ]]
```
## 工作原理
通過命名操作和層范圍,可視化繪圖看起來更好。我們可以折疊和展開自定義層,因為我們在命名范圍內創建了它。在下圖中,請參閱左側的折疊版本和右側的展開版本:

圖 3:具有兩層的計算圖
第一層名為`Moving_Avg_Window`。第二個是名為`Custom_Layer`的操作集合。它在左側折疊并在右側展開。
# 實現損失函數
損失函數對于機器學習算法非常重要。它們測量模型輸出與目標(真值)值之間的距離。在這個秘籍中,我們在 TensorFlow 中展示了各種損失函數實現。
## 準備
為了優化我們的機器學習算法,我們需要評估結果。評估 TensorFlow 中的結果取決于指定損失函數。損失函數告訴 TensorFlow 預測與期望結果相比有多好或多壞。在大多數情況下,我們將有一組數據和一個目標來訓練我們的算法。損失函數將目標與預測進行比較,并給出兩者之間的數值距離。
對于這個秘籍,我們將介紹我們可以在 TensorFlow 中實現的主要損失函數。
要了解不同損失函數的運行方式,我們將在此秘籍中繪制它們。我們將首先啟動一個計算圖并加載`matplotlib`,一個 Python 繪圖庫,如下所示:
```py
import matplotlib.pyplot as plt
import tensorflow as tf
```
## 操作步驟
1. 首先,我們將討論回歸的損失函數,這意味著預測連續的因變量。首先,我們將創建一個預測序列和一個作為張量的目標。我們將在 -1 和 1 之間輸出 500 個值的結果。有關輸出的繪圖,請參閱“工作原理”部分。使用以下代碼:
```py
x_vals = tf.linspace(-1., 1., 500)
target = tf.constant(0.)
```
1. L2 范數損失也稱為歐幾里德損失函數。它只是到目標的距離的平方。在這里,我們將計算損失函數,就像目標為零一樣。 L2 范數是一個很大的損失函數,因為它在目標附近非常彎曲,并且算法可以使用這個事實來越慢地收斂到目標,越接近零。我們可以按如下方式實現:
```py
l2_y_vals = tf.square(target - x_vals)
l2_y_out = sess.run(l2_y_vals)
```
> TensorFlow 具有 L2 范數的內置形式,稱為`nn.l2_loss()`。這個函數實際上是 L2 范數的一半。換句話說,它與前一個相同,但除以 2。
1. L1 范數損失也稱為絕對損失函數。我們不是平衡差異,而是取絕對值。 L1 范數對于異常值比 L2 范數更好,因為對于較大的值,它不是那么陡峭。需要注意的一個問題是 L1 范數在目標處不平滑,這可能導致算法收斂不好。它看起來如下:
```py
l1_y_vals = tf.abs(target - x_vals)
l1_y_out = sess.run(l1_y_vals)
```
1. 偽 Huber 損失是 Huber 損失函數的連續且平滑的近似。這種損失函數試圖通過在目標附近凸起并且對于極值不太陡峭來充分利用 L1 和 L2 范數。表格取決于額外的參數`delta`,它決定了它的陡峭程度。我們將繪制兩種形式,`delta1 = 0.25`和`delta2 = 5`,以顯示差異,如下所示:
```py
delta1 = tf.constant(0.25)
phuber1_y_vals = tf.multiply(tf.square(delta1), tf.sqrt(1\. +
tf.square((target - x_vals)/delta1)) - 1.)
phuber1_y_out = sess.run(phuber1_y_vals)
delta2 = tf.constant(5.)
phuber2_y_vals = tf.multiply(tf.square(delta2), tf.sqrt(1\. +
tf.square((target - x_vals)/delta2)) - 1.)
phuber2_y_out = sess.run(phuber2_y_vals)
```
現在,我們繼續討論分類問題的損失函數。分類損失函數用于在預測分類結果時評估損失。通常,我們的類別類型的輸出是 0 到 1 之間的實數值。然后,我們選擇截止值(通常選擇 0.5)并且如果數字高于截止值,則將結果分類為該類別。在這里,我們考慮分類輸出的各種損失函數:
1. 首先,我們需要重新定義我們的預測(`x_vals`)和`target`。我們將保存輸出并在下一節中繪制它們。使用以下內容:
```py
x_vals = tf.linspace(-3., 5., 500)
target = tf.constant(1.)
targets = tf.fill([500,], 1.)
```
1. 鉸鏈損失主要用于支持向量機,但也可用于神經網絡。它旨在計算兩個目標類 1 和 -1 之間的損失。在下面的代碼中,我們使用目標值`1`,因此我們的預測越接近 1,損失值越低:
```py
hinge_y_vals = tf.maximum(0., 1\. - tf.multiply(target, x_vals))
hinge_y_out = sess.run(hinge_y_vals)
```
1. 二元情形的交叉熵損失有時也稱為邏輯損失函數。它是在我們預測兩個 0 或 1 類時出現的。我們希望測量從實際類(0 或 1)到預測值的距離,預測值通常是介于 0 和 1 之間的實數。為了測量這個距離,我們可以使用信息論中的交叉熵公式,如下:
```py
xentropy_y_vals = - tf.multiply(target, tf.log(x_vals)) - tf.multiply((1\. - target), tf.log(1\. - x_vals))
xentropy_y_out = sess.run(xentropy_y_vals)
```
1. Sigmoid 交叉熵損失與之前的損失函數非常相似,除了我們在將它們置于交叉熵損失之前使用 sigmoid 函數轉換 x 值,如下所示:
```py
xentropy_sigmoid_y_vals = tf.nn.sigmoid_cross_entropy_with_logits_v2(logits=x_vals, labels=targets)
xentropy_sigmoid_y_out = sess.run(xentropy_sigmoid_y_vals)
```
1. 加權交叉熵損失是 Sigmoid 交叉熵損失的加權版本。我們對積極目標給予了重視。舉個例子,我們將正面目標加權 0.5,如下:
```py
weight = tf.constant(0.5)
xentropy_weighted_y_vals = tf.nn.weighted_cross_entropy_with_logits(logits=x_vals, targets=targets, pos_weight=weight)
xentropy_weighted_y_out = sess.run(xentropy_weighted_y_vals)
```
1. Softmax 交叉熵損失在非標準化輸出上運行。當只有一個目標類別而不是多個目標類別時,此函數用于測量損失。因此,函數通過 softmax 函數將輸出轉換為概率分布,然后根據真實概率分布計算損失函數,如下所示:
```py
unscaled_logits = tf.constant([[1., -3., 10.]])
target_dist = tf.constant([[0.1, 0.02, 0.88]])
softmax_xentropy = tf.nn.softmax_cross_entropy_with_logits_v2(logits=unscaled_logits, labels=target_dist)
print(sess.run(softmax_xentropy))
[ 1.16012561]
```
1. 稀疏 softmax 交叉熵損失與前一個相同,除了目標是概率分布,它是哪個類別為真的索引。我們只傳遞真值的類別的索引,而不是稀疏的全零目標向量,其值為 1,如下所示:
```py
unscaled_logits = tf.constant([[1., -3., 10.]])
sparse_target_dist = tf.constant([2])
sparse_xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=unscaled_logits, labels=sparse_target_dist)
print(sess.run(sparse_xentropy))
[ 0.00012564]
```
## 工作原理
以下是如何使用`matplotlib`繪制回歸損失函數:
```py
x_array = sess.run(x_vals)
plt.plot(x_array, l2_y_out, 'b-', label='L2 Loss')
plt.plot(x_array, l1_y_out, 'r--', label='L1 Loss')
plt.plot(x_array, phuber1_y_out, 'k-.', label='P-Huber Loss (0.25)')
plt.plot(x_array, phuber2_y_out, 'g:', label='P-Huber Loss (5.0)')
plt.ylim(-0.2, 0.4)
plt.legend(loc='lower right', prop={'size': 11})
plt.show()
```
我們得到以下圖作為上述代碼的輸出:

圖 4:繪制各種回歸損失函數
以下是如何使用`matplotlib`繪制各種分類損失函數:
```py
x_array = sess.run(x_vals)
plt.plot(x_array, hinge_y_out, 'b-''', label='Hinge Loss''')
plt.plot(x_array, xentropy_y_out, 'r--''', label='Cross' Entropy Loss')
plt.plot(x_array, xentropy_sigmoid_y_out, 'k-.''', label='Cross' Entropy Sigmoid Loss')
plt.plot(x_array, xentropy_weighted_y_out, g:''', label='Weighted' Cross Enropy Loss (x0.5)')
plt.ylim(-1.5, 3)
plt.legend(loc='lower right''', prop={'size''': 11})
plt.show()
```
我們從前面的代碼中得到以下圖:
Figure 5: Plots of classification loss functions
## 更多
這是一個總結我們描述的不同損失函數的表:
| 損失函數 | 任務 | 優點 | 缺點 |
| --- | --- | --- | --- |
| L2 | 回歸 | 更穩定 | 不太強大 |
| L1 | 回歸 | 更強大 | 不太穩定 |
| 偽 Huber | 回歸 | 更強大,更穩定 | 還有一個參數 |
| Hinge | 分類 | 創建 SVM 中使用的最大邊距 | 受到異常值影響的無限損失 |
| 交叉熵 | 分類 | 更穩定 | 無限損失,不那么強大 |
剩余的分類損失函數都與交叉熵損失的類型有關。交叉熵 sigmoid 損失函數用于未縮放的對率,并且優于計算 sigmoid 然后交叉熵,因為 TensorFlow 具有更好的內置方式來處理數字邊緣情況。 softmax 交叉熵和稀疏 softmax 交叉熵也是如此。
> 這里描述的大多數分類損失函數用于兩類預測。通過對每個預測/目標上的交叉熵項求和,可以將其擴展到多個類。
評估模型時還需要考慮許多其他指標。以下列出了一些需要考慮的事項:
| 模型指標 | 描述 |
| --- | --- |
| R 平方(確定系數) | 對于線性模型,這是因變量的方差比例,由獨立數據解釋。對于具有大量特征的模型,請考慮使用調整后的 R 平方。 |
| 均方根誤差 | 對于連續模型,它通過平均平方誤差的平方根來測量預測與實際之間的差異。 |
| 混淆矩陣 | 對于分類模型,我們查看預測類別與實際類別的矩陣。一個完美的模型具有沿對角線的所有計數。 |
| 召回 | 對于分類模型,這是所有預測陽性的真陽性分數。 |
| 精確 | 對于分類模型,這是所有實際陽性的真陽性分數。 |
| F-得分 | 對于分類模型,這是精度和召回的調和平均值。 |
# 實現反向傳播
使用 TensorFlow 的一個好處是它可以跟蹤操作并根據反向傳播自動更新模型變量。在本文中,我們將介紹如何在訓練機器學習模型時將此方面用于我們的優勢。
## 準備
現在,我們將介紹如何以最小化損失函數的方式更改模型中的變量。我們已經學會了如何使用對象和操作,并創建了測量我們的預測和目標之間距離的損失函數。現在,我們只需告訴 TensorFlow 如何通過我們的計算圖反向傳播誤差來更新變量并最小化損失函數。這是通過聲明優化函數完成的。一旦我們聲明了一個優化函數,TensorFlow 將通過并計算出圖中所有計算的反向傳播項。當我們輸入數據并最小化損失函數時,TensorFlow 將相應地修改圖中的變量。
對于這個秘籍,我們將做一個非常簡單的回歸算法。我們將從正態分布中抽取隨機數,均值為 1,標準差為 0.1。然后,我們將通過一個操作來運行數字,這將是它們乘以變量`A`。由此,損失函數將是輸出和目標之間的 L2 范數,其總是值 10。理論上,A 的最佳值將是數字 10,因為我們的數據將具有平均值 1。
第二個例子是一個非常簡單的二分類算法。在這里,我們將從兩個正態分布`N(-1,1)`和`N(3,1)`生成 100 個數字。來自`N(-1, 1)`的所有數字將在目標等級 0 中,并且來自`N(3, 1)`的所有數字將在目標等級 1 中。用于區分這些數字的模型將是翻譯的 Sigmoid 函數。換句話說,模型將是`sigmoid(x + A)`,其中`A`是我們將適合的變量。從理論上講,A 將等于 -1。我們得到這個數字是因為如果`m1`和`m2`是兩個正常函數的平均值,那么加到它們以將它們等距離轉換為零的值將是 - `(m1 + m2) / 2`。我們將在第二個例子中看到 TensorFlow 如何達到該數字。
雖然指定良好的學習率有助于算法的收斂,但我們還必須指定一種優化。從前兩個例子中,我們使用標準梯度下降。這是通過`GradientDescentOptimizer()` TensorFlow 函數實現的。
## 操作步驟
以下是回歸示例的工作原理:
1. 我們首先加載`numpy`和`tensorflow`數值 Python 包:
```py
import numpy as np
import tensorflow as tf
```
1. 現在,我們啟動圖會話:
```py
sess = tf.Session()
```
1. 接下來,我們創建數據,占位符和`A`變量:
```py
x_vals = np.random.normal(1, 0.1, 100)
y_vals = np.repeat(10., 100)
x_data = tf.placeholder(shape=[1], dtype=tf.float32)
y_target = tf.placeholder(shape=[1], dtype=tf.float32)
A = tf.Variable(tf.random_normal(shape=[1]))
```
1. 我們將乘法運算添加到圖中:
```py
my_output = tf.mul(x_data, A)
```
1. 接下來,我們在乘法輸出和目標數據之間添加 L2 `Loss`函數:
```py
loss = tf.square(my_output - y_target)
```
1. 現在,我們必須聲明一種優化圖中變量的方法。我們聲明了一種優化算法。大多數優化算法需要知道每次迭代中的步進距離。該距離由學習率控制。如果我們的學習率太大,我們的算法可能會超過最小值,但如果我們的學習率太小,我們的算法可能需要很長時間才能收斂;這與消失和爆炸的梯度問題有關。學習率對收斂有很大影響,我們將在本節末尾討論這個問題。雖然我們在這里使用標準梯度下降算法,但是有許多不同的優化算法可以不同地運行,并且可以根據問題做得更好或更差。有關不同優化算法的精彩概述,請參閱 Sebastian Ruder 在本文末尾的另見部分中的文章:
```py
my_opt = tf.train.GradientDescentOptimizer(learning_rate=0.02)
train_step = my_opt.minimize(loss)
```
1. 現在我們可以初始化我們的模型變量:
```py
init = tf.global_variable_initializer()
sess.run(init)
```
There is a lot of theory on which learning rates are best. This is one of the harder things to figure out in machine learning algorithms. Good papers to read about how learning rates are related to specific optimization algorithms are listed in the See also section at the end of this recipe.
1. 最后一步是循環我們的訓練算法并告訴 TensorFlow 多次訓練。我們將這樣做 101 次,并且每 25 次迭代打印出結果。為了訓練,我們將選擇隨機`x`和`y`條目并通過圖提供。 TensorFlow 將自動計算損失,并略微改變`A`偏差以最小化損失:
```py
for i in range(100):
rand_index = np.random.choice(100)
rand_x = [x_vals[rand_index]]
rand_y = [y_vals[rand_index]]
sess.run(train_step, feed_dict={x_data: rand_x, y_target: rand_y})
if (i + 1) % 25 == 0:
print('Step #' + str(i+1) + ' A = ' + str(sess.run(A)))
print('Loss = ' + str(sess.run(loss, feed_dict={x_data: rand_x, y_target: rand_y})))
# Here is the output:
Step #25 A = [ 6.23402166]
Loss = 16.3173
Step #50 A = [ 8.50733757]
Loss = 3.56651
Step #75 A = [ 9.37753201]
Loss = 3.03149
Step #100 A = [ 9.80041122]
Loss = 0.0990248
```
現在,我們將介紹簡單分類示例的代碼。如果我們先重置圖,我們可以使用相同的 TensorFlow 腳本。請記住,我們將嘗試找到一個最佳平移`A`,它將兩個分布轉換為原點,而 sigmoid 函數將兩個分為兩個不同的類:
1. 首先,我們重置圖并重新初始化圖會話:
```py
from tensorflow.python.framework import ops
ops.reset_default_graph()
sess = tf.Session()
```
1. 接下來,我們從兩個不同的正態分布`N(-1, 1)`和`N(3, 1)`中提取數據。我們還將生成目標標簽,數據占位符和偏差變量`A`:
```py
x_vals = np.concatenate((np.random.normal(-1, 1, 50), np.random.normal(3, 1, 50)))
y_vals = np.concatenate((np.repeat(0., 50), np.repeat(1., 50)))
x_data = tf.placeholder(shape=[1], dtype=tf.float32)
y_target = tf.placeholder(shape=[1], dtype=tf.float32)
A = tf.Variable(tf.random_normal(mean=10, shape=[1]))
```
> 我們將`A`初始化為大約 10 的值,遠離理論值-1。我們這樣做的目的是為了說明算法如何從 10 的值收斂到最佳值 -1。
1. 接下來,我們將轉換操作添加到圖中。請記住,我們不必將它包裝在 sigmoid 函數中,因為損失函數將為我們執行此操作:
```py
my_output = tf.add(x_data, A)
```
1. 由于特定損失函數需要具有與之關聯的額外維度的批量數據(添加的維度,即批次編號),因此我們將使用`expand_dims()`函數為輸出添加額外維度。在下一節中,我們將討論如何在訓練中使用可變大小的批次。現在,我們將再次使用一個隨機數據點:
```py
my_output_expanded = tf.expand_dims(my_output, 0)
y_target_expanded = tf.expand_dims(y_target, 0)
```
1. 接下來,我們將初始化我們的一個變量`A`:
```py
init = tf.initialize_all_variables()
sess.run(init)
```
1. 現在,我們宣布我們的損失函數。我們將使用帶有未縮放的對率的交叉熵,它使用 sigmoid 函數對它們進行轉換。在名為`nn.sigmoid_cross_entropy_with_logits()`的神經網絡包中,TensorFlow 為我們提供了這一函數。如前所述,它希望參數具有特定的維度,因此我們必須相應地使用擴展的輸出和目標:
```py
xentropy = tf.nn.sigmoid_cross_entropy_with_logits( my_output_expanded, y_target_expanded)
```
1. 與回歸示例一樣,我們需要向圖中添加優化器函數,以便 TensorFlow 知道如何更新圖中的偏差變量:
```py
my_opt = tf.train.GradientDescentOptimizer(0.05)
train_step = my_opt.minimize(xentropy)
```
1. 最后,我們循環遍歷隨機選擇的數據點數百次并相應地更新`A`變量。每 200 次迭代,我們將打印出`A`的值和損失:
```py
for i in range(1400):
rand_index = np.random.choice(100)
rand_x = [x_vals[rand_index]]
rand_y = [y_vals[rand_index]]
sess.run(train_step, feed_dict={x_data: rand_x, y_target: rand_y})
if (i + 1) % 200 == 0:
print('Step #' + str(i+1) + ' A = ' + str(sess.run(A)))
print('Loss = ' + str(sess.run(xentropy, feed_dict={x_data: rand_x, y_target: rand_y})))
Step #200 A = [ 3.59597969]
Loss = [[ 0.00126199]]
Step #400 A = [ 0.50947344]
Loss = [[ 0.01149425]]
Step #600 A = [-0.50994617]
Loss = [[ 0.14271219]]
Step #800 A = [-0.76606178]
Loss = [[ 0.18807337]]
Step #1000 A = [-0.90859312]
Loss = [[ 0.02346182]]
Step #1200 A = [-0.86169094]
Loss = [[ 0.05427232]]
Step #1400 A = [-1.08486211]
Loss = [[ 0.04099189]]
```
## 工作原理
有關回顧和解釋,對于這兩個示例,我們執行了以下操作:
1. 創建了數據。這兩個示例都需要通過占位符加載數據。
2. 初始化占位符和變量。這些是非常相似的數據占位符。變量非常相似,它們都有乘法矩陣`A`,但第一個分類算法有一個偏差項來找到數據中的分裂。
3. 創建了損失函數,我們使用 L2 損失進行回歸,使用交叉熵損失進行分類。
4. 定義了一種優化算法。兩種算法都使用梯度下降。
5. 迭代隨機數據樣本以迭代更新我們的變量。
## 更多
如前所述,優化算法對學習率的選擇很敏感。重要的是要以簡潔的方式總結這種選擇的效果:
| 學習率大小 | 優點缺點 | 用途 |
| --- | --- | --- |
| 較小的學習率 | 收斂速度較慢但結果更準確 | 如果解決方案不穩定,請先嘗試降低學習率 |
| 學習率更高 | 不太準確,但收斂速度更快 | 對于某些問題,有助于防止解決方案停滯不前 |
有時,標準梯度下降算法會顯著卡住或減速。當優化卡在馬鞍的平坦點時,可能會發生這種情況。為了解決這個問題,還有另一種算法考慮了動量項,它增加了前一步驟的梯度下降值的一小部分。 TensorFlow 內置了`MomentumOptimizer()`函數。
另一種變體是為我們模型中的每個變量改變優化器步驟。理想情況下,我們希望為較小的移動變量采取較大的步驟,為較快的變化變量采取較短的步驟。我們不會深入研究這種方法的數學,但這種思想的常見實現稱為 Adagrad 算法。該算法考慮了變量梯度的整個歷史。 TensorFlow 中的函數稱為`AdagradOptimizer()`。
有時候,Adagrad 會過早地強調梯度為零,因為它考慮了整個歷史。解決方法是限制我們使用的步數。這樣做稱為 Adadelta 算法。我們可以使用`AdadeltaOptimizer()`函數來應用它。
還有一些不同的梯度下降算法的其他實現。對于這些,我們會讓讀者參考 [TensorFlow 文檔](https://www.tensorflow.org/api_guides/python/train)。
## 另見
有關優化算法和學習率的一些參考,請參閱以下文章和文章:
* 另見本章的秘籍如下:
* 在實現損失函數部分。
* 在實現反向傳播部分。
* [Kingma,D.,Jimmy,L.,Adam:一種隨機優化方法,ICLR 2015](https://arxiv.org/pdf/1412.6980.pdf)
* [Ruder,S.,梯度下降優化算法概述,2016](https://arxiv.org/pdf/1609.04747v1.pdf)
* [Zeiler,M.,ADADelta:一種自適應學習率方法,2012](http://www.matthewzeiler.com/pubs/googleTR2012/googleTR2012.pdf)
# 使用批量和隨機訓練
雖然 TensorFlow 根據反向傳播更新我們的模型變量,但它可以同時操作從一個基準觀察到一大批數據的任何事物。在一個訓練示例上操作可以使得學習過程非常不穩定,而使用太大的批次可能在計算上是昂貴的。選擇正確類型的訓練對于使我們的機器學習算法融合到解決方案至關重要。
## 準備
為了使 TensorFlow 計算反向傳播的可變梯度,我們必須測量樣本或多個樣本的損失。隨機訓練一次只適用于一個隨機抽樣的數據 - 目標對,就像我們在上一個秘籍中所做的那樣。另一種選擇是一次放置大部分訓練樣例并平均梯度計算的損失。訓練批次的大小可以一次變化,直到并包括整個數據集。在這里,我們將展示如何將先前的回歸示例(使用隨機訓練)擴展到批量訓練。
我們將首先加載`numpy`,`matplotlib`和`tensorflow`,然后啟動圖會話,如下所示:
```py
import matplotlib as plt
import numpy as np
import tensorflow as tf
sess = tf.Session()
```
## 操作步驟
我們按如下方式處理秘籍:
1. 我們將從聲明批量大小開始。這將是我們將同時通過計算圖提供多少數據觀察:
```py
batch_size = 20
```
1. 接下來,我們在模型中聲明數據,占位符和變量。我們在這里做的改變是我們改變了占位符的形狀。它們現在是兩個維度,第一個維度是`None`,第二個維度是批次中的數據點數。我們可以明確地將它設置為 20,但我們可以推廣并使用`None`值。同樣,正如第 1 章,TensorFlow 入門中所述,我們仍然需要確保維度在模型中運行,這不允許我們執行任何非法矩陣操作:
```py
x_vals = np.random.normal(1, 0.1, 100)
y_vals = np.repeat(10., 100)
x_data = tf.placeholder(shape=[None, 1], dtype=tf.float32)
y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)
A = tf.Variable(tf.random_normal(shape=[1,1]))
```
1. 現在,我們將操作添加到圖中,現在將是矩陣乘法而不是常規乘法。請記住,矩陣乘法不是可交換的,因此我們必須在`matmul()`函數中以正確的順序輸入矩陣:
```py
my_output = tf.matmul(x_data, A)
```
1. 我們的`loss`函數會發生變化,因為我們必須采用批次中每個數據點的所有 L2 損失的平均值。我們通過將先前的損失輸出包裝在 TensorFlow 的`reduce_mean()`函數中來實現:
```py
loss = tf.reduce_mean(tf.square(my_output - y_target))
```
1. 我們像以前一樣聲明我們的優化器并初始化我們的模型變量,如下所示:
```py
my_opt = tf.train.GradientDescentOptimizer(0.02)
train_step = my_opt.minimize(loss)
init = tf.global_variables_initializer()
sess.run(init)
```
1. 最后,我們將循環并迭代訓練步驟以優化算法。這部分與以前不同,因為我們希望能夠繪制隨時間的損失并比較批次與隨機訓練的收斂。因此,我們初始化一個列表,每隔五個時間間隔存儲一次損失函數:
```py
loss_batch = []
for i in range(100):
rand_index = np.random.choice(100, size=batch_size)
rand_x = np.transpose([x_vals[rand_index]])
rand_y = np.transpose([y_vals[rand_index]])
sess.run(train_step, feed_dict={x_data: rand_x, y_target: rand_y})
if (i + 1) % 5 == 0:
print('Step #' + str(i+1) + ' A = ' + str(sess.run(A)))
temp_loss = sess.run(loss, feed_dict={x_data: rand_x, y_target: rand_y})
print('Loss = ' + str(temp_loss))
loss_batch.append(temp_loss)
```
1. 這是 100 次迭代的最終輸出。請注意,`A`的值有一個額外的維度,因為它現在必須是一個 2D 矩陣:
```py
Step #100 A = [[ 9.86720943]]
Loss = 0\.
```
## 工作原理
批量訓練和隨機訓練的優化方法和收斂性不同。找到一個好的批量大小可能很困難。為了了解批量與隨機指標之間的收斂程度如何不同,建議讀者將批量大小更改為各種級別。以下是保存和記錄訓練循環中隨機損失的代碼。只需在上一個秘籍中替換此代碼:
```py
loss_stochastic = []
for i in range(100):
rand_index = np.random.choice(100)
rand_x = [x_vals[rand_index]]
rand_y = [y_vals[rand_index]]
sess.run(train_step, feed_dict={x_data: rand_x, y_target: rand_y})
if (i + 1) % 5 == 0:
print('Step #' + str(i+1) + ' A = ' + str(sess.run(A)))
temp_loss = sess.run(loss, feed_dict={x_data: rand_x, y_target: rand_y})
print('Loss = ' + str(temp_loss))
loss_stochastic.append(temp_loss)
```
下面是為同一回歸問題生成隨機和批量損失圖的代碼:
```py
plt.plot(range(0, 100, 5), loss_stochastic, 'b-', label='Stochastic Loss')
plt.plot(range(0, 100, 5), loss_batch, 'r--', label='Batch' Loss, size=20')
plt.legend(loc='upper right', prop={'size': 11})
plt.show()
```
我們得到以下繪圖:

圖 6:在 100 次迭代中繪制的隨機損失和批量損失(批量大小為 20)。請注意,批次損失更加平滑,隨機損失更加不穩定。
## 更多
| 訓練類型 | 優點 | 缺點 |
| --- | --- | --- |
| 隨機 | 隨機性可能有助于擺脫局部的最小值。 | 通常,需要更多迭代才能收斂。 |
| 批量 | 更快地找到最小值。 | 需要更多資源來計算。 |
# 把所有東西結合在一起
在本節中,我們將結合到目前為止所示的所有內容,并為鳶尾數據集創建分類器。
## 準備
鳶尾數據集在第 1 章,TensorFlow 入門中使用數據源秘籍中有更詳細的描述。我們將加載這些數據并制作一個簡單的二元分類器來預測花是否是山鳶尾的種類。需要說明的是,這個數據集有三個種類,但我們只能預測一種花是單一種,是否是一種花,給我們一個二元分類器。我們將首先加載庫和數據,然后相應地轉換目標。
## 操作步驟
我們按如下方式處理秘籍:
1. 首先,我們加載所需的庫并初始化計算圖。注意我們也在這里加載`matplotlib`,因為我們想在之后繪制結果行:
```py
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets
import tensorflow as tf
sess = tf.Session()
```
1. 接下來,我們加載鳶尾數據。我們還需要將目標數據轉換為 1 或 0,無論目標是否為山鳶尾。由于鳶尾數據集將山鳶尾標記為 0,我們將更改所有目標,值為 0 到 1,其他值全部為 0.我們也將只使用兩個特征,花瓣長度和花瓣寬度。這兩個特征是每個`x-value`中的第三和第四個條目:
```py
iris = datasets.load_iris()
binary_target = np.array([1\. if x==0 else 0\. for x in iris.target])
iris_2d = np.array([[x[2], x[3]] for x in iris.data])
```
1. 讓我們聲明我們的批量大小,數據占位符和模型變量。請記住,可變批量大小的數據占位符將`None`作為第一個維度:
```py
batch_size = 20
x1_data = tf.placeholder(shape=[None, 1], dtype=tf.float32)
x2_data = tf.placeholder(shape=[None, 1], dtype=tf.float32)
y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)
A = tf.Variable(tf.random_normal(shape=[1, 1]))
b = tf.Variable(tf.random_normal(shape=[1, 1]))
```
> 請注意,我們可以通過使用`dtype=tf.float32`來減少浮點數的字節來提高算法的表現(速度)。
1. 在這里,我們定義線性模型。模型將采用`x2 = x1 * A + b`的形式,如果我們想要找到該行上方或下方的點,我們會在插入等式`x2 - x1 * A - b`時看到它們是高于還是低于零。我們將通過取該方程的 sigmoid 并從該方程預測 1 或 0 來實現。請記住,TensorFlow 具有內置 sigmoid 的`loss`函數,因此我們只需要在 sigmoid 函數之前定義模型的輸出:
```py
my_mult = tf.matmul(x2_data, A)
my_add = tf.add(my_mult, b)
my_output = tf.sub(x1_data, my_add)
```
1. 現在,我們使用 TensorFlow 的內置`sigmoid_cross_entropy_with_logits()`函數添加 sigmoid 交叉熵損失函數:
```py
xentropy = tf.nn.sigmoid_cross_entropy_with_logits(my_output, y_target)
```
1. 我們還必須告訴 TensorFlow 如何通過聲明優化方法來優化我們的計算圖。我們希望最大限度地減少交叉熵損失。我們還會選擇`0.05`作為我們的學習率:
```py
my_opt = tf.train.GradientDescentOptimizer(0.05)
train_step = my_opt.minimize(xentropy)
```
1. 現在,我們創建一個變量初始化操作并告訴 TensorFlow 執行它:
```py
init = tf.global_variables_initializer()
sess.run(init)
```
1. 現在,我們將訓練我們的線性模型 1000 次迭代。我們將提供我們需要的三個數據點:花瓣長度,花瓣寬度和目標變量。每 200 次迭代,我們將打印變量值:
```py
for i in range(1000):
rand_index = np.random.choice(len(iris_2d), size=batch_size)
rand_x = iris_2d[rand_index]
rand_x1 = np.array([[x[0]] for x in rand_x])
rand_x2 = np.array([[x[1]] for x in rand_x])
rand_y = np.array([[y] for y in binary_target[rand_index]])
sess.run(train_step, feed_dict={x1_data: rand_x1, x2_data: rand_x2, y_target: rand_y})
if (i + 1) % 200 == 0:
print('Step #' + str(i+1) + ' A = ' + str(sess.run(A)) + ', b = ' + str(sess.run(b)))
Step #200 A = [[ 8.67285347]], b = [[-3.47147632]]
Step #400 A = [[ 10.25393486]], b = [[-4.62928772]]
Step #600 A = [[ 11.152668]], b = [[-5.4077611]]
Step #800 A = [[ 11.81016064]], b = [[-5.96689034]]
Step #1000 A = [[ 12.41202831]], b = [[-6.34769201]]
```
1. 下一組命令提取模型變量并在繪圖上繪制線條。結果繪圖在它的工作原理...部分:
```py
[[slope]] = sess.run(A)
[[intercept]] = sess.run(b)
x = np.linspace(0, 3, num=50)
ablineValues = []
for i in x:
ablineValues.append(slope*i+intercept)
setosa_x = [a[1] for i,a in enumerate(iris_2d) if binary_target[i]==1]
setosa_y = [a[0] for i,a in enumerate(iris_2d) if binary_target[i]==1]
non_setosa_x = [a[1] for i,a in enumerate(iris_2d) if binary_target[i]==0]
non_setosa_y = [a[0] for i,a in enumerate(iris_2d) if binary_target[i]==0]
plt.plot(setosa_x, setosa_y, 'rx', ms=10, mew=2, label='setosa')
plt.plot(non_setosa_x, non_setosa_y, 'ro', label='Non-setosa')
plt.plot(x, ablineValues, 'b-')
plt.xlim([0.0, 2.7])
plt.ylim([0.0, 7.1])
plt.suptitle('Linear' Separator For I.setosa', fontsize=20)
plt.xlabel('Petal Length')
plt.ylabel('Petal Width')
plt.legend(loc='lower right')
plt.show()
```
## 工作原理
我們的目標是僅使用花瓣寬度和花瓣長度在山鳶尾點和其他兩個物種之間擬合一條線。如果我們繪制點和結果線,我們看到我們已經實現了這個:

圖 7:花瓣寬度與花瓣長度的山鳶尾和其它鳶尾的圖;實線是我們在 1000 次迭代后實現的線性分離器
## 更多
雖然我們實現了用一條線分隔兩個類的目標,但它可能不是分離兩個類的最佳模型。在第 4 章,支持向量機中,我們將討論支持向量機,它是在特征空間中分離兩個類的更好方法。
## 另見
* 有關 scikit-learn 鳶尾花數據集實現的信息,請參閱[此鏈接](http://scikit-learn.org/stable/auto_examples/datasets/plot_iris_dataset.html)的文檔。
# 評估模型
我們已經學會了如何在 TensorFlow 中訓練回歸和分類算法。在此之后,我們必須能夠評估模型的預測,以確定它的效果。
## 準備
評估模型非常重要,每個后續模型都將采用某種形式的模型評估。使用 TensorFlow,我們必須將此函數構建到計算圖中,并在我們的模型進行訓練時和/或完成訓練后調用它。
在訓練期間評估模型可以讓我們深入了解算法,并可以提供調試,改進或完全更改模型的提示。雖然訓練期間的評估并不總是必要的,但我們將展示如何使用回歸和分類進行評估。
訓練結束后,我們需要量化模型對數據的執行方式。理想情況下,我們有一個單獨的訓練和測試集(甚至是驗證集),我們可以在其上評估模型。
當我們想要評估模型時,我們希望在大批數據點上進行評估。如果我們已經實現了批量訓練,我們可以重用我們的模型來對這樣的批次進行預測。如果我們實現了隨機訓練,我們可能必須創建一個可以批量處理數據的單獨評估器。
> 如果我們在`loss`函數中包含對模型輸出的轉換,例如`sigmoid_cross_entropy_with_logits()`,我們必須在計算精度計算的預測時考慮到這一點。不要忘記將此包含在您對模型的評估中。
我們要評估的任何模型的另一個重要方面是它是回歸還是分類模型。
回歸模型試圖預測連續數。目標不是類別,而是所需數量。為了評估這些針對實際目標的回歸預測,我們需要對兩者之間的距離進行綜合測量。大多數情況下,有意義的損失函數將滿足這些標準。此秘籍向您展示如何將之前的簡單回歸算法更改為打印出訓練循環中的損失并在結束時評估損失。例如,我們將在本章的先前實現反向傳播秘籍中重新審視并重寫我們的回歸示例。
分類模型基于數字輸入預測類別。實際目標是 1 和 0 的序列,我們必須衡量我們與預測的真實程度。分類模型的損失函數通常對解釋模型的運行情況沒有幫助。通常,我們需要某種分類準確率,這通常是正確預測類別的百分比。對于此示例,我們將使用本章中先前實現反向傳播秘籍的分類示例。
## 操作步驟
首先,我們將展示如何評估簡單回歸模型,該模型簡單地適應目標的常數乘法,即 10,如下所示:
1. 首先,我們首先加載庫并創建圖,數據,變量和占位符。本節還有一個非常重要的部分。在我們創建數據之后,我們將數據隨機分成訓練和測試數據集。這很重要,因為我們總是會測試我們的模型,看看它們是否預測良好。在訓練數據和測試數據上評估模型還可以讓我們看到模型是否過擬合:
```py
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
sess = tf.Session()
x_vals = np.random.normal(1, 0.1, 100)
y_vals = np.repeat(10., 100)
x_data = tf.placeholder(shape=[None, 1], dtype=tf.float32)
y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)
batch_size = 25
train_indices = np.random.choice(len(x_vals), round(len(x_vals)*0.8), replace=False)
test_indices = np.array(list(set(range(len(x_vals))) - set(train_indices)))
x_vals_train = x_vals[train_indices]
x_vals_test = x_vals[test_indices]
y_vals_train = y_vals[train_indices]
y_vals_test = y_vals[test_indices]
A = tf.Variable(tf.random_normal(shape=[1,1]))
```
1. 現在,我們聲明我們的模型,`loss`函數和優化算法。我們還將初始化模型變量`A`。使用以下代碼:
```py
my_output = tf.matmul(x_data, A)
loss = tf.reduce_mean(tf.square(my_output - y_target))
my_opt = tf.train.GradientDescentOptimizer(0.02)
train_step = my_opt.minimize(loss)
init = tf.global_variables_initializer()
sess.run(init)
```
1. 我們正如我們之前看到的那樣運行訓練循環,如下所示:
```py
for i in range(100):
rand_index = np.random.choice(len(x_vals_train), size=batch_size) rand_x = np.transpose([x_vals_train[rand_index]])
rand_y = np.transpose([y_vals_train[rand_index]])
sess.run(train_step, feed_dict={x_data: rand_x, y_target: rand_y})
if (i + 1) % 25 == 0:
print('Step #' + str(i+1) + ' A = ' + str(sess.run(A)))
print('Loss = ' + str(sess.run(loss, feed_dict={x_data: rand_x, y_target: rand_y})))
Step #25 A = [[ 6.39879179]]
Loss = 13.7903
Step #50 A = [[ 8.64770794]]
Loss = 2.53685
Step #75 A = [[ 9.40029907]]
Loss = 0.818259
Step #100 A = [[ 9.6809473]]
Loss = 1.10908
```
1. 現在,為了評估模型,我們將在訓練和測試集上輸出 MSE(損失函數),如下所示:
```py
mse_test = sess.run(loss, feed_dict={x_data: np.transpose([x_vals_test]), y_target: np.transpose([y_vals_test])})
mse_train = sess.run(loss, feed_dict={x_data: np.transpose([x_vals_train]), y_target: np.transpose([y_vals_train])})
print('MSE' on test:' + str(np.round(mse_test, 2)))
print('MSE' on train:' + str(np.round(mse_train, 2)))
MSE on test:1.35
MSE on train:0.88
```
對于分類示例,我們將做一些非常相似的事情。這一次,我們需要創建我們自己的精確度函數,我們可以在最后調用。其中一個原因是我們的損失函數內置了 sigmoid,我們需要單獨調用 sigmoid 并測試它以查看我們的類是否正確:
1. 在同一個腳本中,我們可以重新加載圖并創建數據,變量和占位符。請記住,我們還需要將數據和目標分成訓練和測試集。使用以下代碼:
```py
from tensorflow.python.framework import ops
ops.reset_default_graph()
sess = tf.Session()
batch_size = 25
x_vals = np.concatenate((np.random.normal(-1, 1, 50), np.random.normal(2, 1, 50)))
y_vals = np.concatenate((np.repeat(0., 50), np.repeat(1., 50)))
x_data = tf.placeholder(shape=[1, None], dtype=tf.float32)
y_target = tf.placeholder(shape=[1, None], dtype=tf.float32)
train_indices = np.random.choice(len(x_vals), round(len(x_vals)*0.8), replace=False)
test_indices = np.array(list(set(range(len(x_vals))) - set(train_indices)))
x_vals_train = x_vals[train_indices]
x_vals_test = x_vals[test_indices]
y_vals_train = y_vals[train_indices]
y_vals_test = y_vals[test_indices]
A = tf.Variable(tf.random_normal(mean=10, shape=[1]))
```
1. 我們現在將模型和損失函數添加到圖中,初始化變量,并創建優化過程,如下所示:
```py
my_output = tf.add(x_data, A)
init = tf.initialize_all_variables()
sess.run(init)
xentropy = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(my_output, y_target))
my_opt = tf.train.GradientDescentOptimizer(0.05)
train_step = my_opt.minimize(xentropy)
```
1. 現在,我們運行我們的訓練循環,如下所示:
```py
for i in range(1800):
rand_index = np.random.choice(len(x_vals_train), size=batch_size)
rand_x = [x_vals_train[rand_index]]
rand_y = [y_vals_train[rand_index]]
sess.run(train_step, feed_dict={x_data: rand_x, y_target: rand_y})
if (i+1)%200==0:
print('Step #' + str(i+1) + ' A = ' + str(sess.run(A)))
print('Loss = ' + str(sess.run(xentropy, feed_dict={x_data: rand_x, y_target: rand_y})))
Step #200 A = [ 6.64970636]
Loss = 3.39434
Step #400 A = [ 2.2884655]
Loss = 0.456173
Step #600 A = [ 0.29109824]
Loss = 0.312162
Step #800 A = [-0.20045301]
Loss = 0.241349
Step #1000 A = [-0.33634067]
Loss = 0.376786
Step #1200 A = [-0.36866501]
Loss = 0.271654
Step #1400 A = [-0.3727718]
Loss = 0.294866
Step #1600 A = [-0.39153299]
Loss = 0.202275
Step #1800 A = [-0.36630616]
Loss = 0.358463
```
1. 為了評估模型,我們將創建自己的預測操作。我們將預測操作包裝在擠壓函數中,因為我們希望使預測和目標形成相同的形狀。然后,我們用相等的函數測試相等性。在那之后,我們留下了一個真值和假值的張量,我們將其轉換為`float32`并取平均值。這將產生準確率值。我們將為訓練集和測試集評估此函數,如下所示:
```py
y_prediction = tf.squeeze(tf.round(tf.nn.sigmoid(tf.add(x_data, A))))
correct_prediction = tf.equal(y_prediction, y_target)
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
acc_value_test = sess.run(accuracy, feed_dict={x_data: [x_vals_test], y_target: [y_vals_test]})
acc_value_train = sess.run(accuracy, feed_dict={x_data: [x_vals_train], y_target: [y_vals_train]})
print('Accuracy' on train set: ' + str(acc_value_train))
print('Accuracy' on test set: ' + str(acc_value_test))
Accuracy on train set: 0.925
Accuracy on test set: 0.95
```
1. 通常,查看模型結果(準確率,MSE 等)將有助于我們評估模型。我們可以在這里輕松繪制模型和數據的繪圖,因為它是一維的。以下是使用`matplotlib`使用兩個單獨的直方圖可視化模型和數據的方法:
```py
A_result = sess.run(A)
bins = np.linspace(-5, 5, 50)
plt.hist(x_vals[0:50], bins, alpha=0.5, label='N(-1,1)', color='white')
plt.hist(x_vals[50:100], bins[0:50], alpha=0.5, label='N(2,1)', color='red')
plt.plot((A_result, A_result), (0, 8), 'k--', linewidth=3, label='A = '+ str(np.round(A_result, 2)))
plt.legend(loc='upper right')
plt.title('Binary Classifier, Accuracy=' + str(np.round(acc_value, 2)))
plt.show()
```
## 工作原理
這導致繪圖顯示兩個單獨數據類的直方圖中兩個類的預測最佳分隔符。

圖 8:數據和最終模型的可視化。兩個正常值以 -1 和 2 為中心,使理論最佳分割為 0.5。在這里,模型發現最接近該數字的最佳分割。
- 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
- 六、自編碼器,變分自編碼器和生成對抗網絡
- 七、遷移學習
- 八、機器學習最佳實踐和故障排除
- 九、大規模訓練
- 十、參考文獻