# 三、線性回歸
在本章中,我們將介紹涉及線性回歸的秘籍。我們從用矩陣求解線性回歸的數學公式開始,然后繼續使用 TensorFlow 范例實現標準線性回歸和變量。我們將涵蓋以下領域:
* 使用矩陣逆方法
* 實現分解方法
* 學習 TensorFlow 回歸方式
* 理解線性回歸中的損失函數
* 實現戴明回歸
* 實現套索和嶺回歸
* 實現彈性網絡回歸
* 實現邏輯回歸
# 介紹
線性回歸可能是統計學,機器學習和一般科學中最重要的算法之一。它是最廣泛使用的算法之一,了解如何實現它及其各種風格非常重要。線性回歸優于許多其他算法的優點之一是它是非常可解釋的。我們最終得到一個數字,用于直接表示該特征如何影響目標或因變量的每個特征。在本章中,我們將介紹線性回歸是如何經典實現的,然后繼續討論如何在 TensorFlow 范例中最好地實現它。
> 請記住,所有代碼都可以在 [Github](https://github.com/nfmcclure/tensorflow_cookbook) 以及 [Packt 倉庫](https://github.com/PacktPublishing/TensorFlow-Machine-Learning-Cookbook-Second-Edition)獲得。
# 使用矩陣逆方法
在這個秘籍中,我們將使用 TensorFlow 用矩陣逆方法求解二維線性回歸。
## 準備
線性回歸可以表示為一組矩陣方程,比如`Ax = b`。在這里,我們感興趣的是求解矩陣`x`中的系數。如果我們的觀察矩陣(設計矩陣)`A`不是正方形,我們必須要小心。解決`x`的解決方案可以表示為:

為了證明確實如此,我們將生成二維數據,在 TensorFlow 中解決它,并繪制結果。
## 操作步驟
我們按如下方式處理秘籍:
1. 首先,我們加載必要的庫,初始化圖并創建數據。請參閱以下代碼:
```py
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
sess = tf.Session()
x_vals = np.linspace(0, 10, 100)
y_vals = x_vals + np.random.normal(0, 1, 100)
```
1. 接下來,我們創建要在逆方法中使用的矩陣。我們首先創建`A`矩陣,它將是`x`數據列和全 1 的列。然后,我們從`y`數據創建`b`矩陣。使用以下代碼:
```py
x_vals_column = np.transpose(np.matrix(x_vals))
ones_column = np.transpose(np.matrix(np.repeat(1, 100)))
A = np.column_stack((x_vals_column, ones_column))
b = np.transpose(np.matrix(y_vals))
```
1. 然后我們將`A`和`b`矩陣轉換為張量,如下所示:
```py
A_tensor = tf.constant(A)
b_tensor = tf.constant(b)
```
1. 現在我們已經設置了矩陣,我們可以使用 TensorFlow 通過矩陣逆方法解決這個問題,如下所示:
```py
tA_A = tf.matmul(tf.transpose(A_tensor), A_tensor)
tA_A_inv = tf.matrix_inverse(tA_A)
product = tf.matmul(tA_A_inv, tf.transpose(A_tensor))
solution = tf.matmul(product, b_tensor)
solution_eval = sess.run(solution)
```
1. 我們現在使用以下代碼從解,斜率和 y 截距中提取系數:
```py
slope = solution_eval[0][0]
y_intercept = solution_eval[1][0]
print('slope: ' + str(slope))
print('y_intercept: ' + str(y_intercept))
slope: 0.955707151739
y_intercept: 0.174366829314
best_fit = []
for i in x_vals:
best_fit.append(slope*i+y_intercept)
plt.plot(x_vals, y_vals, 'o', label='Data')
plt.plot(x_vals, best_fit, 'r-', label='Best fit line', linewidth=3)
plt.legend(loc='upper left')
plt.show()
```
我們得到前面代碼的圖,如下所示:

圖 1:數據點和通過矩陣逆方法獲得的最佳擬合線
## 工作原理
與之前的秘籍或本書中的大多數秘籍不同,此處的解決方案僅通過矩陣運算找到。我們將使用的大多數 TensorFlow 算法都是通過訓練循環實現的,并利用自動反向傳播來更新模型變量。在這里,我們通過實現將模型擬合到數據的直接解決方案來說明 TensorFlow 的多功能性。
> 我們在這里使用了一個二維數據示例來顯示與數據擬合的圖。值得注意的是,用于求解系數的公式
>
> 
>
> 將根據需要擴展到數據中的許多特征(除非存在任何共線性問題)。
# 實現分解方法
對于這個秘籍,我們將實現一個用于線性回歸的矩陣分解方法。具體來說,我們將使用 Cholesky 分解,TensorFlow 中存在相關函數。
## 準備
在大多數情況下,實現前一個秘籍中的逆方法在數值上效率低,尤其是當矩陣變得非常大時。另一種方法是分解`A`矩陣并對分解執行矩陣運算。一種方法是在 TensorFlow 中使用內置的 Cholesky 分解方法。
人們對將矩陣分解為更多矩陣如此感興趣的一個原因是,所得到的矩陣將具有允許我們有效使用某些方法的保證屬性。 Cholesky 分解將矩陣分解為下三角矩陣和上三角矩陣,比如`L`和`L'`,使得這些矩陣是彼此的轉置。有關此分解屬性的更多信息,有許多可用資源來描述它以及如何到達它。在這里,我們將通過將其寫為`LL'x = b`來解決系統`Ax = b`。我們首先解決`Ly = b`的`y`,然后求解`L'x = y`得到我們的系數矩陣`x`。
## 操作步驟
我們按如下方式處理秘籍:
1. 我們將以與上一個秘籍完全相同的方式設置系統。我們將導入庫,初始化圖并創建數據。然后,我們將以之前的方式獲得我們的`A`矩陣和`b`矩陣:
```py
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow.python.framework import ops
ops.reset_default_graph()
sess = tf.Session()
x_vals = np.linspace(0, 10, 100)
y_vals = x_vals + np.random.normal(0, 1, 100)
x_vals_column = np.transpose(np.matrix(x_vals))
ones_column = np.transpose(np.matrix(np.repeat(1, 100)))
A = np.column_stack((x_vals_column, ones_column))
b = np.transpose(np.matrix(y_vals))
A_tensor = tf.constant(A)
b_tensor = tf.constant(b)
```
1. 接下來,我們找到方陣的 Cholesky 分解,`A^T A`:
```py
tA_A = tf.matmul(tf.transpose(A_tensor), A_tensor)
L = tf.cholesky(tA_A)
tA_b = tf.matmul(tf.transpose(A_tensor), b)
sol1 = tf.matrix_solve(L, tA_b)
sol2 = tf.matrix_solve(tf.transpose(L), sol1)
```
> 請注意,TensorFlow 函數`cholesky()`僅返回分解的下對角線部分。這很好,因為上對角矩陣只是下對角矩陣的轉置。
1. 現在我們有了解決方案,我們提取系數:
```py
solution_eval = sess.run(sol2)
slope = solution_eval[0][0]
y_intercept = solution_eval[1][0]
print('slope: ' + str(slope))
print('y_intercept: ' + str(y_intercept))
slope: 0.956117676145
y_intercept: 0.136575513864
best_fit = []
for i in x_vals:
best_fit.append(slope*i+y_intercept)
plt.plot(x_vals, y_vals, 'o', label='Data')
plt.plot(x_vals, best_fit, 'r-', label='Best fit line', linewidth=3)
plt.legend(loc='upper left')
plt.show()
```
繪圖如下:

圖 2:通過 Cholesky 分解獲得的數據點和最佳擬合線
## 工作原理
如您所見,我們得出了與之前秘籍非常相似的答案。請記住,這種分解矩陣然后對碎片執行操作的方式有時會更加高效和數值穩定,尤其是在考慮大型數據矩陣時。
# 學習 TensorFlow 線性回歸方法
雖然使用矩陣和分解方法非常強大,但 TensorFlow 還有另一種解決斜率和截距的方法。 TensorFlow 可以迭代地執行此操作,逐步學習最小化損失的線性回歸參數。
## 準備
在這個秘籍中,我們將遍歷批量數據點并讓 TensorFlow 更新斜率和`y`截距。我們將使用內置于 scikit-learn 庫中的鳶尾花數據集,而不是生成的數據。具體來說,我們將通過數據點找到最佳線,其中`x`值是花瓣寬度,`y`值是萼片長度。我們選擇了這兩個,因為它們之間似乎存在線性關系,我們將在最后的繪圖中看到。我們還將在下一節中詳細討論不同損失函數的影響,但對于這個秘籍,我們將使用 L2 損失函數。
## 操作步驟
我們按如下方式處理秘籍:
1. 我們首先加載必要的庫,創建圖并加載數據:
```py
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from sklearn import datasets
from tensorflow.python.framework import ops
ops.reset_default_graph()
sess = tf.Session()
iris = datasets.load_iris()
x_vals = np.array([x[3] for x in iris.data])
y_vals = np.array([y[0] for y in iris.data])
```
1. 然后我們聲明我們的學習率,批量大小,占位符和模型變量:
```py
learning_rate = 0.05
batch_size = 25
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]))
b = tf.Variable(tf.random_normal(shape=[1,1]))
```
1. 接下來,我們編寫線性模型的公式`y = Ax + b`:
```py
model_output = tf.add(tf.matmul(x_data, A), b)
```
1. 然后,我們聲明我們的 L2 損失函數(包括批量的平均值),初始化變量,并聲明我們的優化器。請注意,我們選擇`0.05`作為我們的學習率:
```py
loss = tf.reduce_mean(tf.square(y_target - model_output))
init = tf.global_variables_initializer()
sess.run(init)
my_opt = tf.train.GradientDescentOptimizer(learning_rate)
train_step = my_opt.minimize(loss)
```
1. 我們現在可以在隨機選擇的批次上循環并訓練模型。我們將運行 100 個循環并每 25 次迭代打印出變量和損失值。請注意,在這里,我們還保存了每次迭代的損失,以便我們以后可以查看它們:
```py
loss_vec = []
for i in range(100):
rand_index = np.random.choice(len(x_vals), 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})
temp_loss = sess.run(loss, feed_dict={x_data: rand_x, y_target: rand_y})
loss_vec.append(temp_loss)
if (i+1)%25==0:
print('Step #' + str(i+1) + ' A = ' + str(sess.run(A)) + ' b = ' + str(sess.run(b)))
print('Loss = ' + str(temp_loss))
Step #25 A = [[ 2.17270374]] b = [[ 2.85338426]]
Loss = 1.08116
Step #50 A = [[ 1.70683455]] b = [[ 3.59916329]]
Loss = 0.796941
Step #75 A = [[ 1.32762754]] b = [[ 4.08189011]]
Loss = 0.466912
Step #100 A = [[ 1.15968263]] b = [[ 4.38497639]]
Loss = 0.281003
```
1. 接下來,我們將提取我們找到的系數并創建一個最合適的線以放入圖中:
```py
[slope] = sess.run(A)
[y_intercept] = sess.run(b)
best_fit = []
for i in x_vals:
best_fit.append(slope*i+y_intercept)
```
1. 在這里,我們將創建兩個圖。第一個是覆蓋擬合線的數據。第二個是 100 次迭代中的 L2 損失函數。這是生成兩個圖的代碼。
```py
plt.plot(x_vals, y_vals, 'o', label='Data Points')
plt.plot(x_vals, best_fit, 'r-', label='Best fit line', linewidth=3)
plt.legend(loc='upper left')
plt.title('Sepal Length vs Petal Width')
plt.xlabel('Petal Width')
plt.ylabel('Sepal Length')
plt.show()
plt.plot(loss_vec, 'k-')
plt.title('L2 Loss per Generation')
plt.xlabel('Generation')
plt.ylabel('L2 Loss')
plt.show()
```
此代碼生成以下擬合數據和損失圖。

圖 3:來自鳶尾數據集的數據點(萼片長度與花瓣寬度)重疊在 TensorFlow 中找到的最佳線條擬合。

圖 4:用我們的算法擬合數據的 L2 損失;注意損失函數中的抖動,可以通過較大的批量大小減小抖動,或者通過較小的批量大小來增加。
Here is a good place to note how to see whether the model is overfitting or underfitting the data. If our data is broken into test and training sets, and the accuracy is greater on the training set and lower on the test set, then we are overfitting the data. If the accuracy is still increasing on both test and training sets, then the model is underfitting and we should continue training.
## 工作原理
找到的最佳線不保證是最合適的線。最佳擬合線的收斂取決于迭代次數,批量大小,學習率和損失函數。隨著時間的推移觀察損失函數總是很好的做法,因為它可以幫助您解決問題或超參數變化。
# 理解線性回歸中的損失函數
了解損失函數在算法收斂中的作用非常重要。在這里,我們將說明 L1 和 L2 損失函數如何影響線性回歸中的收斂。
## 準備
我們將使用與先前秘籍中相同的鳶尾數據集,但我們將更改損失函數和學習率以查看收斂如何變化。
## 操作步驟
我們按如下方式處理秘籍:
1. 程序的開始與上一個秘籍相同,直到我們達到我們的損失函數。我們加載必要的庫,啟動會話,加載數據,創建占位符,并定義我們的變量和模型。需要注意的一點是,我們正在提取學習率和模型迭代。我們這樣做是因為我們希望顯示快速更改這些參數的效果。使用以下代碼:
```py
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from sklearn import datasets
sess = tf.Session()
iris = datasets.load_iris()
x_vals = np.array([x[3] for x in iris.data])
y_vals = np.array([y[0] for y in iris.data])
batch_size = 25
learning_rate = 0.1 # Will not converge with learning rate at 0.4
iterations = 50
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]))
b = tf.Variable(tf.random_normal(shape=[1,1]))
model_output = tf.add(tf.matmul(x_data, A), b)
```
1. 我們的損失函數將變為 L1 損失(`loss_l1`),如下所示:
```py
loss_l1 = tf.reduce_mean(tf.abs(y_target - model_output))
```
1. 現在,我們通過初始化變量,聲明我們的優化器以及通過訓練循環迭代數據來恢復。請注意,我們也在節省每一代的損失來衡量收斂。使用以下代碼:
```py
init = tf.global_variables_initializer()
sess.run(init)
my_opt_l1 = tf.train.GradientDescentOptimizer(learning_rate)
train_step_l1 = my_opt_l1.minimize(loss_l1)
loss_vec_l1 = []
for i in range(iterations):
rand_index = np.random.choice(len(x_vals), size=batch_size)
rand_x = np.transpose([x_vals[rand_index]])
rand_y = np.transpose([y_vals[rand_index]])
sess.run(train_step_l1, feed_dict={x_data: rand_x, y_target: rand_y})
temp_loss_l1 = sess.run(loss_l1, feed_dict={x_data: rand_x, y_target: rand_y})
loss_vec_l1.append(temp_loss_l1)
if (i+1)%25==0:
print('Step #' + str(i+1) + ' A = ' + str(sess.run(A)) + ' b = ' + str(sess.run(b)))
plt.plot(loss_vec_l1, 'k-', label='L1 Loss')
plt.plot(loss_vec_l2, 'r--', label='L2 Loss')
plt.title('L1 and L2 Loss per Generation')
plt.xlabel('Generation')
plt.ylabel('L1 Loss')
plt.legend(loc='upper right')
plt.show()
```
## 工作原理
在選擇損失函數時,我們還必須選擇適合我們問題的相應學習率。在這里,我們將說明兩種情況,一種是首選 L2,另一種是首選 L1。
如果我們的學習率很小,我們的收斂會花費更多時間。但是如果我們的學習速度太大,我們的算法就會遇到問題從不收斂。下面是當學習率為 0.05 時,鳶尾線性回歸問題的 L1 和 L2 損失的損失函數圖:

圖 5:鳶尾線性回歸問題的學習率為 0.05 的 L1 和 L2 損失
學習率為 0.05 時,似乎 L2 損失是首選,因為它會收斂到較低的損失。下面是我們將學習率提高到 0.4 時的損失函數圖:

圖 6:鳶尾線性回歸問題的 L1 和 L2 損失,學習率為 0.4;請注意,由于 y 軸的高比例,L1 損失不可見
在這里,我們可以看到高學習率可以在 L2 范數中超調,而 L1 范數收斂。
## 更多
為了理解正在發生的事情,我們應該看看大學習率和小學習率如何影響 L1 范數和 L2 范數。為了使這個可視化,我們查看兩個規范的學習步驟的一維表示,如下所示:

圖 7:學習率越來越高的 L1 和 L2 范數會發生什么
# 實現戴明回歸
在這個秘籍中,我們將實現戴明回歸,這意味著我們需要一種不同的方法來測量模型線和數據點之間的距離。
> 戴明回歸有幾個名字。它也稱為總回歸,正交距離回歸(ODR)和最短距離回歸。
## 準備
如果最小二乘線性回歸最小化到線的垂直距離,則戴明回歸最小化到線的總距離。這種類型的回歸可以最小化`y`和`x`值的誤差。
請參閱下圖進行比較:

圖 8:常規線性回歸和戴明回歸之間的差異;左邊的線性回歸最小化了到線的垂直距離,右邊的變形回歸最小化了到線的總距離
要實現戴明回歸,我們必須修改損失函數。常規線性回歸中的損失函數使垂直距離最小化。在這里,我們希望最小化總距離。給定線的斜率和截距,到點的垂直距離是已知的幾何公式??。我們只需要替換此公式并告訴 TensorFlow 將其最小化。
## 操作步驟
我們按如下方式處理秘籍:
1. 代碼與之前的秘籍非常相似,除非我們進入損失函數。我們首先加載庫;開始一個會議;加載數據;聲明批量大小;并創建占位符,變量和模型輸出,如下所示:
```py
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from sklearn import datasets
sess = tf.Session()
iris = datasets.load_iris()
x_vals = np.array([x[3] for x in iris.data])
y_vals = np.array([y[0] for y in iris.data])
batch_size = 50
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]))
b = tf.Variable(tf.random_normal(shape=[1,1]))
model_output = tf.add(tf.matmul(x_data, A), b)
```
1. 損失函數是由分子和分母組成的幾何公式??。為清楚起見,我們將分別編寫這些內容。給定一條線`y = mx + b`和一個點`(x0, y0)`,兩者之間的垂直距離可以寫成如下:

```py
deming_numerator = tf.abs(tf.sub(y_target, tf.add(tf.matmul(x_data, A), b)))
deming_denominator = tf.sqrt(tf.add(tf.square(A),1))
loss = tf.reduce_mean(tf.truediv(deming_numerator, deming_denominator))
```
1. 我們現在初始化變量,聲明我們的優化器,并循環遍歷訓練集以獲得我們的參數,如下所示:
```py
init = tf.global_variables_initializer()
sess.run(init)
my_opt = tf.train.GradientDescentOptimizer(0.1)
train_step = my_opt.minimize(loss)
loss_vec = []
for i in range(250):
rand_index = np.random.choice(len(x_vals), 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})
temp_loss = sess.run(loss, feed_dict={x_data: rand_x, y_target: rand_y})
loss_vec.append(temp_loss)
if (i+1)%50==0:
print('Step #' + str(i+1) + ' A = ' + str(sess.run(A)) + ' b = ' + str(sess.run(b)))
print('Loss = ' + str(temp_loss))
```
1. 我們可以使用以下代碼繪制輸出:
```py
[slope] = sess.run(A)
[y_intercept] = sess.run(b)
best_fit = []
for i in x_vals:
best_fit.append(slope*i+y_intercept)
plt.plot(x_vals, y_vals, 'o', label='Data Points')
plt.plot(x_vals, best_fit, 'r-', label='Best fit line', linewidth=3)
plt.legend(loc='upper left')
plt.title('Sepal Length vs petal Width')
plt.xlabel('petal Width')
plt.ylabel('Sepal Length')
plt.show()
```
我們得到上面代碼的以下圖:

圖 9:對鳶尾數據集進行戴明回歸的解決方案
## 工作原理
戴明回歸的方法幾乎與常規線性回歸相同。關鍵的區別在于我們如何衡量預測和數據點之間的損失。而不是垂直損失,我們對`y`和`x`值有垂直損失(或總損失)。
> 當我們假設`x`和`y`值中的誤差相似時,使用這種類型的回歸。根據我們的假設,我們還可以根據誤差的差異在距離計算中縮放`x`和`y`軸。
# 實現套索和嶺回歸
還有一些方法可以限制系數對回歸輸出的影響。這些方法稱為正則化方法,兩種最常見的正則化方法是套索和嶺回歸。我們將介紹如何在本文中實現這兩個方面。
## 準備
套索和嶺回歸與常規線性回歸非常相似,除了我們添加正則化項以限制公式中的斜率(或部分斜率)。這可能有多種原因,但一個常見的原因是我們希望限制對因變量產生影響的特征。這可以通過在損失函數中添加一個取決于我們的斜率值`A`的項來實現。
對于套索回歸,如果斜率`A`超過某個值,我們必須添加一個能大大增加損失函數的項。我們可以使用 TensorFlow 的邏輯運算,但它們沒有與之關聯的梯度。相反,我們將使用稱為連續重階函數的階梯函數的連續近似,該函數按比例放大到我們選擇的正則化截止值。我們將展示如何在此秘籍中進行套索回歸。
對于嶺回歸,我們只是在 L2 范數中添加一個項,這是斜率系數的縮放 L2 范數。這種修改很簡單,并在本秘籍末尾的“更多”部分中顯示。
## 操作步驟
我們按如下方式處理秘籍:
1. 我們將再次使用鳶尾花數據集并以與以前相同的方式設置我們的腳本。我們先加載庫;開始一個會議;加載數據;聲明批量大小;并創建占位符,變量和模型輸出,如下所示:
```py
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from sklearn import datasets
from tensorflow.python.framework import ops
ops.reset_default_graph()
sess = tf.Session()
iris = datasets.load_iris()
x_vals = np.array([x[3] for x in iris.data])
y_vals = np.array([y[0] for y in iris.data])
batch_size = 50
learning_rate = 0.001
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]))
b = tf.Variable(tf.random_normal(shape=[1,1]))
model_output = tf.add(tf.matmul(x_data, A), b)
```
1. 我們添加了損失函數,它是一個改進的連續 Heaviside 階梯函數。我們還為`0.9`設定了套索回歸的截止值。這意味著我們希望將斜率系數限制為小于`0.9`。使用以下代碼:
```py
lasso_param = tf.constant(0.9)
heavyside_step = tf.truediv(1., tf.add(1., tf.exp(tf.multiply(-100., tf.subtract(A, lasso_param)))))
regularization_param = tf.mul(heavyside_step, 99.)
loss = tf.add(tf.reduce_mean(tf.square(y_target - model_output)), regularization_param)
```
1. 我們現在初始化變量并聲明我們的優化器,如下所示:
```py
init = tf.global_variables_initializer()
sess.run(init)
my_opt = tf.train.GradientDescentOptimizer(learning_rate)
train_step = my_opt.minimize(loss)
```
1. 我們將訓練循環延長了一段時間,因為它可能需要一段時間才能收斂。我們可以看到斜率系數小于`0.9`。使用以下代碼:
```py
loss_vec = []
for i in range(1500):
rand_index = np.random.choice(len(x_vals), 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})
temp_loss = sess.run(loss, feed_dict={x_data: rand_x, y_target: rand_y})
loss_vec.append(temp_loss[0])
if (i+1)%300==0:
print('Step #' + str(i+1) + ' A = ' + str(sess.run(A)) + ' b = ' + str(sess.run(b)))
print('Loss = ' + str(temp_loss))
Step #300 A = [[ 0.82512331]] b = [[ 2.30319238]]
Loss = [[ 6.84168959]]
Step #600 A = [[ 0.8200165]] b = [[ 3.45292258]]
Loss = [[ 2.02759886]]
Step #900 A = [[ 0.81428504]] b = [[ 4.08901262]]
Loss = [[ 0.49081498]]
Step #1200 A = [[ 0.80919558]] b = [[ 4.43668795]]
Loss = [[ 0.40478843]]
Step #1500 A = [[ 0.80433637]] b = [[ 4.6360755]]
Loss = [[ 0.23839757]]
```
## 工作原理
我們通過在線性回歸的損失函數中添加連續的 Heaviside 階躍函數來實現套索回歸。由于階梯函數的陡峭性,我們必須小心步長。步長太大而且不會收斂。對于嶺回歸,請參閱下一節中所需的更改。
## 更多
對于嶺回歸,我們將損失`ss`函數更改為如下:
```py
ridge_param = tf.constant(1.)
ridge_loss = tf.reduce_mean(tf.square(A))
loss = tf.expand_dims(tf.add(tf.reduce_mean(tf.square(y_target - model_output)), tf.multiply(ridge_param, ridge_loss)), 0)
```
# 實現彈性網絡回歸
彈性網絡回歸是一種回歸類型,通過將 L1 和 L2 正則化項添加到損失函數,將套索回歸與嶺回歸相結合。
## 準備
在前兩個秘籍之后實現彈性網絡回歸應該是直截了當的,因此我們將在鳶尾數據集上的多元線性回歸中實現這一點,而不是像以前那樣堅持二維數據。我們將使用花瓣長度,花瓣寬度和萼片寬度來預測萼片長度。
## 操作步驟
我們按如下方式處理秘籍:
1. 首先,我們加載必要的庫并初始化圖,如下所示:
```py
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from sklearn import datasets
sess = tf.Session()
```
1. 現在,我們加載數據。這次,`x`數據的每個元素將是三個值的列表而不是一個。使用以下代碼:
```py
iris = datasets.load_iris()
x_vals = np.array([[x[1], x[2], x[3]] for x in iris.data])
y_vals = np.array([y[0] for y in iris.data])
```
1. 接下來,我們聲明批量大小,占位符,變量和模型輸出。這里唯一的區別是我們更改`x`數據占位符的大小規范,取三個值而不是一個,如下所示:
```py
batch_size = 50
learning_rate = 0.001
x_data = tf.placeholder(shape=[None, 3], dtype=tf.float32)
y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)
A = tf.Variable(tf.random_normal(shape=[3,1]))
b = tf.Variable(tf.random_normal(shape=[1,1]))
model_output = tf.add(tf.matmul(x_data, A), b)
```
1. 對于彈性網絡,損失函數具有部分斜率的 L1 和 L2 范數。我們創建這些項,然后將它們添加到損失函數中,如下所示:
```py
elastic_param1 = tf.constant(1.)
elastic_param2 = tf.constant(1.)
l1_a_loss = tf.reduce_mean(tf.abs(A))
l2_a_loss = tf.reduce_mean(tf.square(A))
e1_term = tf.multiply(elastic_param1, l1_a_loss)
e2_term = tf.multiply(elastic_param2, l2_a_loss)
loss = tf.expand_dims(tf.add(tf.add(tf.reduce_mean(tf.square(y_target - model_output)), e1_term), e2_term), 0)
```
1. 現在,我們可以初始化變量,聲明我們的優化函數,運行訓練循環,并擬合我們的系數,如下所示:
```py
init = tf.global_variables_initializer()
sess.run(init)
my_opt = tf.train.GradientDescentOptimizer(learning_rate)
train_step = my_opt.minimize(loss)
loss_vec = []
for i in range(1000):
rand_index = np.random.choice(len(x_vals), size=batch_size)
rand_x = 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})
temp_loss = sess.run(loss, feed_dict={x_data: rand_x, y_target: rand_y})
loss_vec.append(temp_loss[0])
if (i+1)%250==0:
print('Step #' + str(i+1) + ' A = ' + str(sess.run(A)) + ' b = ' + str(sess.run(b)))
print('Loss = ' + str(temp_loss))
```
1. 這是代碼的輸出:
```py
Step #250 A = [[ 0.42095602]
[ 0.1055888 ]
[ 1.77064979]] b = [[ 1.76164341]]
Loss = [ 2.87764359]
Step #500 A = [[ 0.62762028]
[ 0.06065864]
[ 1.36294949]] b = [[ 1.87629771]]
Loss = [ 1.8032167]
Step #750 A = [[ 0.67953539]
[ 0.102514 ]
[ 1.06914485]] b = [[ 1.95604002]]
Loss = [ 1.33256555]
Step #1000 A = [[ 0.6777274 ]
[ 0.16535147]
[ 0.8403284 ]] b = [[ 2.02246833]]
Loss = [ 1.21458709]
```
1. 現在,我們可以觀察訓練迭代的損失,以確保算法收斂,如下所示:
```py
plt.plot(loss_vec, 'k-')
plt.title('Loss per Generation')
plt.xlabel('Generation')
plt.ylabel('Loss')
plt.show()
```
我們得到上面代碼的以下圖:

圖 10:在 1,000 次訓練迭代中繪制的彈性凈回歸損失
## 工作原理
這里實現彈性網絡回歸以及多元線性回歸。我們可以看到,利用損失函數中的這些正則化項,收斂速度比先前的秘籍慢。正則化就像在損失函數中添加適當的項一樣簡單。
# 實現邏輯回歸
對于這個秘籍,我們將實現邏輯回歸來預測樣本人群中低出生體重的概率。
## 準備
邏輯回歸是將線性回歸轉換為二元分類的一種方法。這是通過將線性輸出轉換為 Sigmoid 函數來實現的,該函數將輸出在 0 和 1 之間進行縮放。目標是零或一,表示數據點是在一個類還是另一個類中。由于我們預測 0 和 1 之間的數字,如果預測高于指定的截止值,則預測被分類為類值 1,否則分類為 0。出于此示例的目的,我們將指定截斷為 0.5,這將使分類像舍入輸出一樣簡單。
我們將用于此示例的數據將是從作者的 GitHub 倉庫獲得的[低出生體重數據](https://github.com/nfmcclure/tensorflow_cookbook/raw/master/01_Introduction/07_Working_with_Data_Sources/birthweight_data/birthweight.dat)。我們將從其他幾個因素預測低出生體重。
## 操作步驟
我們按如下方式處理秘籍:
1. 我們首先加載庫,包括`request`庫,因為我們將通過超鏈接訪問低出生體重數據。我們還發起了一個會議:
```py
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
import requests
from sklearn import datasets
from sklearn.preprocessing import normalize
from tensorflow.python.framework import ops
ops.reset_default_graph()
sess = tf.Session()
```
1. 接下來,我們通過請求模塊加載數據并指定我們要使用的特征。我們必須具體,因為一個特征是實際出生體重,我們不想用它來預測出生體重是大于還是小于特定量。我們也不想將 ID 列用作預測器:
```py
birth_weight_file = 'birth_weight.csv'
# Download data and create data file if file does not exist in current directory
if not os.path.exists(birth_weight_file):
birthdata_url = 'https://github.com/nfmcclure/tensorflow_cookbook/raw/master/01_Introduction/07_Working_with_Data_Sources/birthweight_data/birthweight.dat'
birth_file = requests.get(birthdata_url)
birth_data = birth_file.text.split('\r\n')
birth_header = birth_data[0].split('\t')
birth_data = [[float(x) for x in y.split('\t') if len(x)>=1] for y in birth_data[1:] if len(y)>=1]
with open(birth_weight_file, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(birth_header)
writer.writerows(birth_data)
# Read birth weight data into memory
birth_data = []
with open(birth_weight_file, newline='') as csvfile:
csv_reader = csv.reader(csvfile)
birth_header = next(csv_reader)
for row in csv_reader:
birth_data.append(row)
birth_data = [[float(x) for x in row] for row in birth_data]
# Pull out target variable
y_vals = np.array([x[0] for x in birth_data])
# Pull out predictor variables (not id, not target, and not birthweight)
x_vals = np.array([x[1:8] for x in birth_data])
```
1. 首先,我們將數據集拆分為測試和訓練集:
```py
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]
```
1. 當特征在 0 和 1 之間縮放(最小 - 最大縮放)時,邏輯回歸收斂效果更好。那么,接下來我們將擴展每個特征:
```py
def normalize_cols(m, col_min=np.array([None]), col_max=np.array([None])):
if not col_min[0]:
col_min = m.min(axis=0)
if not col_max[0]:
col_max = m.max(axis=0)
return (m-col_min) / (col_max - col_min), col_min, col_max
x_vals_train, train_min, train_max = np.nan_to_num(normalize_cols(x_vals_train))
x_vals_test = np.nan_to_num(normalize_cols(x_vals_test, train_min, train_max))
```
> 請注意,在縮放數據集之前,我們將數據集拆分為訓練和測試。這是一個重要的區別。我們希望確保測試集完全不影響訓練集。如果我們在分裂之前縮放整個集合,那么我們不能保證它們不會相互影響。我們確保從訓練組中保存縮放以縮放測試集。
1. 接下來,我們聲明批量大小,占位符,變量和邏輯模型。我們不將輸出包裝在 sigmoid 中,因為該操作內置于損失函數中。另請注意,每次觀察都有七個輸入特征,因此`x_data`占位符的大小為`[None, 7]`。
```py
batch_size = 25
x_data = tf.placeholder(shape=[None, 7], dtype=tf.float32)
y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)
A = tf.Variable(tf.random_normal(shape=[7,1]))
b = tf.Variable(tf.random_normal(shape=[1,1]))
model_output = tf.add(tf.matmul(x_data, A), b)
```
1. 現在,我們聲明我們的損失函數,它具有 sigmoid 函數,初始化我們的變量,并聲明我們的優化函數:
```py
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(model_output, y_target))
init = tf.global_variables_initializer()
sess.run(init)
my_opt = tf.train.GradientDescentOptimizer(0.01)
train_step = my_opt.minimize(loss)
```
1. 在記錄損失函數的同時,我們還希望在訓練和測試集上記錄分類準確率。因此,我們將創建一個預測函數,返回任何大小的批量的準確率:
```py
prediction = tf.round(tf.sigmoid(model_output))
predictions_correct = tf.cast(tf.equal(prediction, y_target), tf.float32)
accuracy = tf.reduce_mean(predictions_correct)
```
1. 現在,我們可以開始我們的訓練循環并記錄損失和準確率:
```py
loss_vec = []
train_acc = []
test_acc = []
for i in range(1500):
rand_index = np.random.choice(len(x_vals_train), size=batch_size)
rand_x = 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})
temp_loss = sess.run(loss, feed_dict={x_data: rand_x, y_target: rand_y})
loss_vec.append(temp_loss)
temp_acc_train = sess.run(accuracy, feed_dict={x_data: x_vals_train, y_target: np.transpose([y_vals_train])})
train_acc.append(temp_acc_train)
temp_acc_test = sess.run(accuracy, feed_dict={x_data: x_vals_test, y_target: np.transpose([y_vals_test])})
test_acc.append(temp_acc_test)
```
1. 以下是查看損失和準確率圖的代碼:
```py
plt.plot(loss_vec, 'k-')
plt.title('Cross' Entropy Loss per Generation')
plt.xlabel('Generation')
plt.ylabel('Cross' Entropy Loss')
plt.show()
plt.plot(train_acc, 'k-', label='Train Set Accuracy')
plt.plot(test_acc, 'r--', label='Test Set Accuracy')
plt.title('Train and Test Accuracy')
plt.xlabel('Generation')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')
plt.show()
```
## 工作原理
這是迭代和訓練和測試精度的損失。由于數據集僅為 189 次觀測,因此隨著數據集的隨機分裂,訓練和測試精度圖將發生變化。第一個數字是交叉熵損失:

圖 11:在 1,500 次迭代過程中繪制的交叉熵損失
第二個圖顯示了訓練和測試裝置的準確率:
Figure 12: Test and train set accuracy plotted over 1,500 generations
- 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
- 六、自編碼器,變分自編碼器和生成對抗網絡
- 七、遷移學習
- 八、機器學習最佳實踐和故障排除
- 九、大規模訓練
- 十、參考文獻