第3章
基于TensorFlow的線性回歸
本章将介紹TensorFlow是如何工作的,以及如何通路本書的資料集和補充學習資源。學完本章将掌握以下知識點:
- 用TensorFlow求逆矩陣
- 用TensorFlow實作矩陣分解
- 用TensorFlow實作線性回歸
- 了解線性回歸中的損失函數
- 用TensorFlow實作戴明回歸(Deming Regression)
- 用TensorFlow實作Lasso回歸和嶺回歸(Ridge Regression)
- 用TensorFlow實作彈性網絡回歸(Elastic Net Regression)
- 用TensorFlow實作邏輯回歸
3.1 簡介
線性回歸算法是統計分析、機器學習和科學計算中最重要的算法之一,也是最常使用的算法之一,是以需要了解其是如何實作的,以及線性回歸算法的各種優點。相對于許多其他算法來講,線性回歸算法是最易解釋的。以每個特征的數值直接代表該特征對目标值或者因變量的影響。本章将揭曉線性回歸算法的經典實作,然後講解其在TensorFlow中的實作。
請讀者注意,本書的所有源碼均可以在GitHub中通路,網址為
https://github.com/nfmcclure/tensorflow_cookbook,也可通路Packt代碼庫
https://github.com/PackPublishing/TensorFlow-Machine-Learning-Cookbook-Second-Edition。
3.2 用TensorFlow求逆矩陣
本節将使用TensorFlow求逆矩陣的方法解決二維線性回歸問題。
3.2.1 開始
線性回歸算法能表示為矩陣計算,Ax = b。這裡要解決的是用矩陣x來求解系數。注意,如果觀測矩陣不是方陣,那求解出的矩陣x為x = (ATA) - 1ATb。為了更直覺地展示這種情況,我們将生成二維資料,用TensorFlow來求解,然後繪制最終結果(見圖3-1)。

3.2.2 動手做
1.導入必要的程式設計庫,初始化計算圖,并生成資料,代碼如下:
2.建立後續求逆方法所需的矩陣。建立A矩陣,其為矩陣x_vals_column和ones_column的合并。然後以矩陣y_vals建立b矩陣,代碼如下:
3.将A和b矩陣轉換成張量,代碼如下:
4.現在,使用TensorFlow的tf.matrix_inverse()方法,代碼如下:
5.從解中抽取系數、斜率和y截距y-intercept,代碼如下:
3.2.3 工作原理
與本書的大部分章節不一樣的是,這裡的解決方法是通過矩陣操作直接求解結果。大部分TensorFlow算法是通過疊代訓練實作的,利用反向傳播自動更新模型變量。這裡通過實作資料直接求解的方法拟合模型,僅僅是為了說明TensorFlow的靈活用法。
我們使用了二維資料例子來展示資料的拟合。需要注意的是,求取系數的公式(x = (AT A)-1 AT b)能夠根據需要擴充到資料中任意數量(但對共線性問題無效)。
3.3 用TensorFlow實作矩陣分解
本節将用TensorFlow為線性回歸算法實作矩陣分解。特别地,我們會使用Cholesky矩陣分解法,相關的函數已在TensorFlow中實作。
3.3.1 開始
在上一節中實作的求逆矩陣的方法在大部分情況下是低效率的,特别地,當矩陣非常大時效率更低。另外一種實作方法是矩陣分解,此方法使用TensorFlow内建的Cholesky矩陣分解法。使用者對将一個矩陣分解為多個矩陣的方法感興趣的原因是,結果矩陣的特性使得其在應用中更高效。Cholesky矩陣分解法把一個矩陣分解為上三角矩陣和下三角矩陣,L和L'(L'和L互為轉置矩陣)。求解Ax = b,改寫成LL'x = b。首先求解Ly = b,然後求解L'x = y得到系數矩陣x。
3.3.2 動手做
1.導入程式設計庫,初始化計算圖,生成資料集。接着擷取矩陣A和b,代碼如下:
2.找到方陣的Cholesky矩陣分解,ATA:
注意,TensorFlow的cholesky()函數僅僅傳回矩陣分解的下三角矩陣,因為上三角矩陣是下三角矩陣的轉置矩陣。
3.抽取系數:
3.3.3 工作原理
正如你所看到的,最終求解的結果與前一節的相似。記住,通過分解矩陣的方法求解有時更高效并且數值穩定(見圖3-2)。
3.4 用TensorFlow實作線性回歸算法
雖然使用矩陣和分解方法非常強大,但TensorFlow有另一種方法來求解斜率和截距。它可以通過疊代做到這一點,逐漸學習将最小化損失的最佳線性回歸參數。
3.4.1 開始
本節将周遊批量資料點并讓TensorFlow更新斜率和y截距。這次将使用Scikit Learn的内建iris資料集。特别地,我們将用資料點(x值代表花瓣寬度,y值代表花瓣長度)找到最優直線。選擇這兩種特征是因為它們具有線性關系,在後續結果中将會看到。下一節将講解不同損失函數的影響,本節将使用L2正則損失函數。
3.4.2 動手做
1.導入必要的程式設計庫,建立計算圖,加載資料集,代碼如下:
2.聲明學習率、批量大小、占位符和模型變量,代碼如下:
3.增加線性模型,y = Ax + b,代碼如下:
4.聲明L2損失函數,其為批量損失的平均值。初始化變量,聲明優化器。注意,學習率設為0.05,代碼如下:
5.現在周遊疊代,并在随機選擇的批量資料上進行模型訓練。疊代100次,每25次疊代輸出變量值和損失值。注意,這裡儲存每次疊代的損失值,将其用于後續的可視化。代碼如下:
6.抽取系數,建立最佳拟合直線,代碼如下:
7.這裡将繪制兩幅圖。第一幅圖(見圖3-3)是拟合的直線;第二幅圖(見圖3-4)是疊代100次的L2正則損失函數,代碼如下:
這裡很容易看出算法模型是過拟合還是欠拟合。将資料集分割成測試資料集和訓練資料集,如果訓練資料集的準确度更大,而測試資料集準确度更低,那麼該拟合為過拟合;如果在測試資料集和訓練資料集上的準确度都一直在增加,那麼該拟合是欠拟合,需要繼續訓練。
3.4.3 工作原理
并不能保證最優直線是最佳拟合的直線。最佳拟合直線的收斂依賴疊代次數、批量大小、學習率和損失函數。最好時刻觀察損失函數,它能幫助我們進行問題定位或者超參數
調整。
3.5 了解線性回歸中的損失函數
了解各種損失函數在算法收斂的影響是非常重要的。這裡将展示L1正則和L2正則損失函數對線性回歸算法收斂的影響。
3.5.1 開始
這次繼續使用上一節中的iris資料集,通過改變損失函數和學習率來觀察收斂性的
變化。
3.5.2 動手做
1.除了損失函數外,程式的開始與以往一樣,導入必要的程式設計庫,建立一個會話,加載資料,建立占位符,定義變量和模型。我們将抽出學習率和模型疊代次數,以便展示調整這些參數的影響。代碼如下:
2.損失函數改為L1正則損失函數,代碼如下:
3.現在繼續初始化變量,聲明優化器,周遊疊代訓練。注意,為了度量收斂性,每次疊代都會儲存損失值。代碼如下:
3.5.3 工作原理
當選擇了一個損失函數時,也要選擇對應的學習率。這裡展示了兩種解決方法,一種是上一節的L2正則損失函數,另一種是L1正則損失函數。
如果學習率太小,算法收斂耗時将更長。但是如果學習率太大,算法有可能産生不收斂的問題。下面繪制iris資料的線性回歸問題的L1正則和L2正則損失(見圖3-5),其中學習率為0.05。
從圖3-5中可以看出,當學習率為0.05時,L2正則損失更優,其有更低的損失值。當學習率增加為0.4時,繪制其損失函數(見圖3-6)。
從圖3-6中可以發現,學習率大導緻L2損失過大,而L1正則損失收斂。
3.5.4 延伸學習
為了更容易地了解上述的情況,這裡清晰地展示大學習率和國小習率對L1正則和L2正則損失函數的影響。這裡可視化的是L1正則和L2正則損失函數的一維情況,如圖3-7所示。
3.6 用TensorFlow實作戴明回歸算法
本節将實作戴明回歸(Deming Regression),其意味着需要不同的方式來度量模型直線和資料集的資料點間的距離。
戴明回歸有很多别名,例如全回歸、正交回歸(ODR)或者最短路徑回歸。
3.6.1 開始
如果最小二乘線性回歸算法最小化到回歸直線的豎直距離(即,平行于y軸方向),則戴明回歸最小化到回歸直線的總距離(即,垂直于回歸直線)。其最小化x值和y值兩個方向的誤差,具體的對比圖如圖3-8所示。
為了實作戴明回歸算法,我們修改一下損失函數。線性回歸算法的損失函數最小化豎直距離;而這裡需要最小化總距離。給定直線的斜率和截距,則求解一個點到直線的垂直距離有已知的幾何公式。代入幾何公式并使TensorFlow最小化距離。
3.6.2 動手做
1.除了損失函數外,其他的步驟跟前面的類似。導入必要的程式設計庫,建立一個計算圖會話,加載資料集,聲明批量大小,建立占位符、變量和模型輸出,代碼如下:
2.損失函數是由分子和分母組成的幾何公式。給定直線y = mx + b,點(x0, y0),則求兩者間的距離的公式為:
3.現在初始化變量,聲明優化器,周遊疊代訓練集以得到參數,代碼如下:
4.繪制輸出結果(見圖3-9)的代碼如下:
3.6.3 工作原理
戴明回歸算法與線性回歸算法得到的結果基本一緻。兩者之間的關鍵不同點在于預測值與資料點間的損失函數度量:線性回歸算法的損失函數是豎直距離損失;而戴明回歸算法是垂直距離損失(到x軸和y軸的總距離損失)。
注意,這裡戴明回歸算法的實作類型是總體回歸(總的最小二乘法誤差)。總體回歸算法是假設x值和y值的誤差是相似的。我們也可以根據不同的理念使用不同的誤差來擴充x軸和y軸的距離計算。
3.7 用TensorFlow實作lasso回歸和嶺回歸算法
也有些正則方法可以限制回歸算法輸出結果中系數的影響,其中最常用的兩種正則方法是lasso回歸和嶺回歸。本節将詳細介紹如何實作這兩種方法。
3.7.1 開始
lasso回歸和嶺回歸算法跟正常線性回歸算法極其相似,有一點不同的是,在公式中增加正則項來限制斜率(或者淨斜率)。這樣做的主要原因是限制特征對因變量的影響,通過增加一個依賴斜率A的損失函數實作。
對于lasso回歸算法,在損失函數上增加一項:斜率A的某個給定倍數。我們使用TensorFlow的邏輯操作,但沒有這些操作相關的梯度,而是使用階躍函數的連續估計,也稱作連續階躍函數,其會在截止點跳躍擴大。一會就可以看到如何使用lasso回歸算法。
對于嶺回歸算法,增加一個L2範數,即斜率系數的L2正則。這個簡單的修改将在3.7.4節介紹。
3.7.2 動手做
1.這次還是使用iris資料集,使用方式跟前面的類似。首先,導入必要的程式設計庫,建立一個計算圖會話,加載資料集,聲明批量大小,建立占位符、變量和模型輸出,代碼如下:
2.增加損失函數,其為改良過的連續階躍函數,lasso回歸的截止點設為0.9。這意味着限制斜率系數不超過0.9,代碼如下:
3.初始化變量和聲明優化器,代碼如下:
4.周遊疊代運作一段時間,因為需要過一會兒才會收斂。最後結果顯示斜率系數小于0.9,代碼如下:
3.7.3 工作原理
通過在标準線性回歸估計的基礎上,增加一個連續的階躍函數,實作lasso回歸算法。由于階躍函數的坡度,我們需要注意步長,因為太大的步長會導緻最終不收斂。對于嶺回歸算法,将在下一節介紹對其的必要修改。
3.7.4 延伸學習
對于嶺回歸算法,在上一節的代碼基礎上稍微改變損失函數即可,代碼如下:
3.8 用TensorFlow實作彈性網絡回歸算法
彈性網絡回歸算法(Elastic Net Regression)是綜合lasso回歸和嶺回歸的一種回歸算法,通過在損失函數中增加L1和L2正則項。
3.8.1 開始
在學完前面兩節之後,可以輕松地實作彈性網絡回歸算法。本節使用多線性回歸的方法實作彈性網絡回歸算法,以iris資料集為訓練資料,用花瓣長度、花瓣寬度和花萼寬度三個特征預測花萼長度。
3.8.2 動手做
1.導入必要的程式設計庫并初始化一個計算圖,代碼如下:
2.加載資料集。這次,x_vals資料将是三列值的數組,代碼如下:
3.聲明批量大小、占位符、變量和模型輸出。這裡唯一不同的是x_data占位符的大小為3,代碼如下:
4.對于彈性網絡回歸算法,損失函數包含斜率的L1正則和L2正則。建立L1和L2正則項,然後加入到損失函數中,代碼如下:
5.現在初始化變量,聲明優化器,然後周遊疊代運作,訓練拟合得到系數,代碼如下:
6.下面是代碼運作的輸出結果:
7.現在能觀察到,随着訓練疊代後損失函數已收斂(見圖3-10),代碼如下:
3.8.3 工作原理
彈性網絡回歸算法的實作是多線性回歸。我們能發現,增加L1和L2正則項後的損失函數中的收斂變慢。
3.9 用TensorFlow實作邏輯回歸算法
本節将實作邏輯回歸算法,預測低出生體重的機率。
3.9.1 開始
邏輯回歸算法可以将線性回歸轉換成一個二值分類器。通過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 )。我們将從多個因素來預測低出生體重。
3.9.2 動手做
1.導入必要的程式設計庫,包括requests子產品,因為我們将通過超連結通路低出生體重資料集。初始化一個計算圖,代碼如下:
2.通過requests子產品加載資料集,指定要使用的特征。實際出生體重特征和ID兩列不需要,代碼如下:
3.分割資料集為測試集和訓練集:
4.将所有特征縮放到0和1區間(min-max縮放),邏輯回歸收斂的效果更好。下面将歸一化特征,代碼如下:
注意,在縮放資料集前,先分割資料集為測試集和訓練集,這是相當重要的。我們要確定訓練集和測試集互不影響。如果我們在分割資料集前先縮放,就無法保證它們不互相影響。
5.聲明批量大小、占位符、變量和邏輯模型。這步不需要用sigmoid函數封裝輸出結果,因為sigmoid操作是包含在内建損失函數中的,代碼如下:
6.聲明損失函數,其包含sigmoid函數。初始化變量,聲明優化器,代碼如下:
7.除記錄損失函數外,也需要記錄分類器在訓練集和測試集上的準确度。是以建立一個傳回準确度的預測函數,代碼如下:
8.開始周遊疊代訓練,記錄損失值和準确度,代碼如下:
9.繪制損失和準确度,代碼如下:
3.9.3 工作原理
這裡是疊代過程中的損失,以及訓練集和測試集的準确度。資料集隻有189個觀測值,但訓練集和測試集的準确度圖由于資料集的随機分割将會變化,如圖3-11和圖3-12所示。