在之前的描述中,我們通常把機器學習模型和訓練算法當作黑箱子來處理。如果你實踐過前幾章的一些示例,你驚奇的發(fā)現(xiàn)你可以優(yōu)化回歸系統(tǒng),改進數字圖像的分類器,你甚至可以零基礎搭建一個垃圾郵件的分類器,但是你卻對它們內部的工作流程一無所知。事實上,許多場合你都不需要知道這些黑箱子的內部有什么,干了什么。
然而,如果你對其內部的工作流程有一定了解的話,當面對一個機器學習任務時候,這些理論可以幫助你快速的找到恰當的機器學習模型,合適的訓練算法,以及一個好的假設集。同時,了解黑箱子內部的構成,有助于你更好地調試參數以及更有效的誤差分析。本章討論的大部分話題對于機器學習模型的理解,構建,以及神經網絡(詳細參考本書的第二部分)的訓練都是非常重要的。
首先我們將以一個簡單的線性回歸模型為例,討論兩種不同的訓練方法來得到模型的最優(yōu)解:
直接使用封閉方程進行求根運算,得到模型在當前訓練集上的最優(yōu)參數(即在訓練集上使損失函數達到最小值的模型參數)
使用迭代優(yōu)化方法:梯度下降(GD),在訓練集上,它可以逐漸調整模型參數以獲得最小的損失函數,最終,參數會收斂到和第一種方法相同的的值。同時,我們也會介紹一些梯度下降的變體形式:批量梯度下降(Batch GD)、小批量梯度下降(Mini-batch GD)、隨機梯度下降(Stochastic GD),在第二部分的神經網絡部分,我們會多次使用它們。
接下來,我們將研究一個更復雜的模型:多項式回歸,它可以擬合非線性數據集,由于它比線性模型擁有更多的參數,于是它更容易出現(xiàn)模型的過擬合。因此,我們將介紹如何通過學習曲線去判斷模型是否出現(xiàn)了過擬合,并介紹幾種正則化方法以減少模型出現(xiàn)過擬合的風險。
最后,我們將介紹兩個常用于分類的模型:Logistic回歸和Softmax回歸
提示
在本章中包含許多數學公式,以及一些線性代數和微積分基本概念。為了理解這些公式,你需要知道什么是向量,什么是矩陣,以及它們直接是如何轉化的,以及什么是點積,什么是矩陣的逆,什么是偏導數。如果你對這些不是很熟悉的話,你可以閱讀本書提供的 Jupyter 在線筆記,它包括了線性代數和微積分的入門指導。對于那些不喜歡數學的人,你也應該快速簡單的瀏覽這些公式。希望它足以幫助你理解大多數的概念。
線性回歸
在第一章,我們介紹了一個簡單的的生活滿意度回歸模型:
$$ life_satisfaction = \theta _{0} + \theta _{1} * GDP_per_capita $$
這個模型僅僅是輸入量GDP_per_capita的線性函數,$\theta _{0}$ 和 $\theta _{1}$ 是這個模型的參數,線性模型更一般化的描述指通過計算輸入變量的加權和,并加上一個常數偏置項(截距項)來得到一個預測值。如公式 4-1:
公式 4-1:線性回歸預測模型
$$ \hat{y} = \theta _{0} + \theta _{1}x _{1}+\theta _{2}x _{2}+\dots+\theta _{n}x _{n} $$
$\hat{y}$ 表示預測結果
$n$ 表示特征的個數
$x_{i}$ 表示第i個特征的值
$\theta_{j}$ 表示第j個參數(包括偏置項 $\theta _{0}$ 和特征權重值 $\theta _{1},\theta _{2},\dots,\theta _{n}$)
上述公式可以寫成更為簡潔的向量形式,如公式 4-2:
公式 4-2:線性回歸預測模型(向量形式)
$$ \hat{y} = h _{\theta} (\mathbf{x})= \theta^T \cdot \mathbf{x} $$
$\theta$ 表示模型的參數向量包括偏置項 $\theta _{0}$ 和特征權重值 $\theta _{1}$ 到 $\theta _{n}$
$\theta^T$ 表示向量$\theta$的轉置(行向量變?yōu)榱肆邢蛄浚?/p>
$\mathbf{x}$ 為每個樣本中特征值的向量形式,包括 $x {1}$ 到 $x{n}$,而且 $x_0$ 恒為 1
$\theta^T \cdot \mathbf{x}$ 表示 $\theta^T$ 和$ \mathbf{x}$ 的點積
$h_{\theta}$ 表示參數為 $\theta$ 的假設函數
怎么樣去訓練一個線性回歸模型呢?好吧,回想一下,訓練一個模型指的是設置模型的參數使得這個模型在訓練集的表現(xiàn)較好。為此,我們首先需要找到一個衡量模型好壞的評定方法。在第二章,我們介紹到在回歸模型上,最常見的評定標準是均方根誤差(RMSE,詳見公式 2-1)。因此,為了訓練一個線性回歸模型,你需要找到一個 $\theta$ 值,它使得均方根誤差(標準誤差)達到最小值。實踐過程中,最小化均方誤差比最小化均方根誤差更加的簡單,這兩個過程會得到相同的 $\theta$,因為函數在最小值時候的自變量,同樣能使函數的方根運算得到最小值。
在訓練集 $\mathbf{X}$ 上使用公式 4-3 來計算線性回歸假設 $h_{\theta}$ 的均方差($MSE$)。
公式 4-3:線性回歸模型的 MSE 損失函數
$$ MSE (\mathbf{X},h {\theta}$) = $\frac{1}{m} \sum\limits{i=1}^m{\left(\theta^T \cdot \mathbf{x}^{(i)}-y^{(i)}\right)}^2 $$
公式中符號的含義大多數都在第二章(詳見“符號”)進行了說明,不同的是:為了突出模型的參數向量 $\theta$,使用 $h_{\theta}$ 來代替 $h$。以后的使用中為了公式的簡潔,使用 $MSE(\theta)$ 來代替 $MSE(\mathbf{X},h _{\theta})$。
正態(tài)方程
為了找到最小化損失函數的 $\theta$ 值,可以采用公式解,換句話說,就是可以通過解正態(tài)方程直接得到最后的結果。
公式 4-4:正態(tài)方程
$$ \hat{\theta} = ({\mathbf{X}}^T\cdot\mathbf{X})^{-1}\cdot{\mathbf{X}}^T\cdot\mathbf{y} $$
$\hat{\theta}$ 指最小化損失 $\theta$ 的值
$\mathbf{y}$ 是一個向量,其包含了 $y^{(1)}$ 到 $y^{(m)}$ 的值
讓我們生成一些近似線性的數據(如圖 4-1)來測試一下這個方程。
import numpy as np X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1)
圖 4-1:隨機線性數據集
現(xiàn)在讓我們使用正態(tài)方程來計算 $\hat{\theta}$,我們將使用 Numpy 的線性代數模塊(np.linalg)中的inv()函數來計算矩陣的逆,以及dot()方法來計算矩陣的乘法。
X_b = np.c_[np.ones((100, 1)), X] theta_best = np.linalg.inv(X_b.T.dot(X_B)).dot(X_b.T).dot(y)
我們生產數據的函數實際上是 $y = 4 + 3x_0 + 高斯噪聲$。讓我們看一下最后的計算結果。
>>> theta_best array([[4.21509616],[2.77011339]])
我們希望最后得到的參數為 $\theta_0=4,\theta_1=3$ 而不是 $\theta_0=3.865,\theta_1=3.139$ (譯者注:我認為應該是 $\theta_0=4.2150,\theta_1=2.7701$)。這已經足夠了,由于存在噪聲,參數不可能達到到原始函數的值。
現(xiàn)在我們能夠使用 $\hat{\theta}$ 來進行預測:
>>> X_new = np.array([[0],[2]]) >>> X_new_b = np.c_[np.ones((2, 1)), X_new] >>> y_predict = X_new_b.dot(theta.best) >>> y_predict array([[4.21509616],[9.75532293]])
畫出這個模型的圖像,如圖 4-2
plt.plot(X_new,y_predict,"r-") plt.plot(X,y,"b.") plt.axis([0,2,0,15]) plt.show()
圖4-2:線性回歸預測
使用下面的 Scikit-Learn 代碼可以達到相同的效果:
計算復雜度
正態(tài)方程需要計算矩陣 ${\mathbf{X}}^T\cdot\mathbf{X}$ 的逆,它是一個 $n * n$ 的矩陣($n$ 是特征的個數)。這樣一個矩陣求逆的運算復雜度大約在 $O(n^{2.4})$ 到 $O(n^3)$ 之間,具體值取決于計算方式。換句話說,如果你將你的特征個數翻倍的話,其計算時間大概會變?yōu)樵瓉淼?5.3($2^{2.4}$)到 8($2^3$)倍。
提示
當特征的個數較大的時候(例如:特征數量為 100000),正態(tài)方程求解將會非常慢。
有利的一面是,這個方程在訓練集上對于每一個實例來說是線性的,其復雜度為 $O(m)$,因此只要有能放得下它的內存空間,它就可以對大規(guī)模數據進行訓練。同時,一旦你得到了線性回歸模型(通過解正態(tài)方程或者其他的算法),進行預測是非??斓摹R驗槟P椭杏嬎銖碗s度對于要進行預測的實例數量和特征個數都是線性的。 換句話說,當實例個數變?yōu)樵瓉淼膬杀抖嗟臅r候(或特征個數變?yōu)樵瓉淼膬杀抖啵?,預測時間也僅僅是原來的兩倍多。
接下來,我們將介紹另一種方法去訓練模型。這種方法適合在特征個數非常多,訓練實例非常多,內存無法滿足要求的時候使用。
梯度下降
梯度下降是一種非常通用的優(yōu)化算法,它能夠很好地解決一系列問題。梯度下降的整體思路是通過的迭代來逐漸調整參數使得損失函數達到最小值。
假設濃霧下,你迷失在了大山中,你只能感受到自己腳下的坡度。為了最快到達山底,一個最好的方法就是沿著坡度最陡的地方下山。這其實就是梯度下降所做的:它計算誤差函數關于參數向量$\theta$的局部梯度,同時它沿著梯度下降的方向進行下一次迭代。當梯度值為零的時候,就達到了誤差函數最小值 。
具體來說,開始時,需要選定一個隨機的$\theta$(這個值稱為隨機初始值),然后逐漸去改進它,每一次變化一小步,每一步都試著降低損失函數(例如:均方差損失函數),直到算法收斂到一個最小值(如圖:4-3)。
圖 4-3:梯度下降
在梯度下降中一個重要的參數是步長,超參數學習率的值決定了步長的大小。如果學習率太小,必須經過多次迭代,算法才能收斂,這是非常耗時的(如圖 4-4)。
圖 4-4:學習率過小
另一方面,如果學習率太大,你將跳過最低點,到達山谷的另一面,可能下一次的值比上一次還要大。這可能使的算法是發(fā)散的,函數值變得越來越大,永遠不可能找到一個好的答案(如圖 4-5)。
圖 4-5:學習率過大
最后,并不是所有的損失函數看起來都像一個規(guī)則的碗。它們可能是洞,山脊,高原和各種不規(guī)則的地形,使它們收斂到最小值非常的困難。 圖 4-6 顯示了梯度下降的兩個主要挑戰(zhàn):如果隨機初始值選在了圖像的左側,則它將收斂到局部最小值,這個值要比全局最小值要大。 如果它從右側開始,那么跨越高原將需要很長時間,如果你早早地結束訓練,你將永遠到不了全局最小值。
圖 4-6:梯度下降的陷阱
幸運的是線性回歸模型的均方差損失函數是一個凸函數,這意味著如果你選擇曲線上的任意兩點,它們的連線段不會與曲線發(fā)生交叉(譯者注:該線段不會與曲線有第三個交點)。這意味著這個損失函數沒有局部最小值,僅僅只有一個全局最小值。同時它也是一個斜率不能突變的連續(xù)函數。這兩個因素導致了一個好的結果:梯度下降可以無限接近全局最小值。(只要你訓練時間足夠長,同時學習率不是太大 )。
事實上,損失函數的圖像呈現(xiàn)碗狀,但是不同特征的取值范圍相差較大的時,這個碗可能是細長的。圖 4-7 展示了梯度下降在不同訓練集上的表現(xiàn)。在左圖中,特征 1 和特征 2 有著相同的數值尺度。在右圖中,特征 1 比特征2的取值要小的多,由于特征 1 較小,因此損失函數改變時,$\theta_1$ 會有較大的變化,于是這個圖像會在$\theta_1$軸方向變得細長。
圖 4-7:有無特征縮放的梯度下降
正如你看到的,左面的梯度下降可以直接快速地到達最小值,然而在右面的梯度下降第一次前進的方向幾乎和全局最小值的方向垂直,并且最后到達一個幾乎平坦的山谷,在平坦的山谷走了很長時間。它最終會達到最小值,但它需要很長時間。
提示
當我們使用梯度下降的時候,應該確保所有的特征有著相近的尺度范圍(例如:使用 Scikit Learn 的 StandardScaler類),否則它將需要很長的時間才能夠收斂。
這幅圖也表明了一個事實:訓練模型意味著找到一組模型參數,這組參數可以在訓練集上使得損失函數最小。這是對于模型參數空間的搜索,模型的參數越多,參數空間的維度越多,找到合適的參數越困難。例如在300維的空間找到一枚針要比在三維空間里找到一枚針復雜的多。幸運的是線性回歸模型的損失函數是凸函數,這個最優(yōu)參數一定在碗的底部。
批量梯度下降
使用梯度下降的過程中,你需要計算每一個 $\theta_j$ 下?lián)p失函數的梯度。換句話說,你需要計算當$\theta_j$變化一點點時,損失函數改變了多少。這稱為偏導數,它就像當你面對東方的時候問:"我腳下的坡度是多少?"。然后面向北方的時候問同樣的問題(如果你能想象一個超過三維的宇宙,可以對所有的方向都這樣做)。公式 4-5 計算關于 $\theta_j$ 的損失函數的偏導數,記為 $\frac{\partial }{\partial \theta_j}MSE(\theta)$。
公式 4-5: 損失函數的偏導數
$$ \frac{\partial }{\partial \theta_j}MSE(\theta)=\frac{2}{m} \sum\limits_{i=1}^m{\left(\theta^T \cdot \mathbf{x}^{(i)}-y^{(i)}\right)}{x_j}^{(i)} $$
為了避免單獨計算每一個梯度,你也可以使用公式 4-6 來一起計算它們。梯度向量記為 $\nabla_{\theta}MSE(\theta)$,其包含了損失函數所有的偏導數(每個模型參數只出現(xiàn)一次)。
公式 4-6:損失函數的梯度向量
$$ \nabla_{\theta}MSE(\theta)= \left(\begin{matrix} \frac{\partial }{\partial \theta_0}MSE(\theta)\ \frac{\partial }{\partial \theta_1}MSE(\theta)\ \vdots \ \frac{\partial }{\partial \theta_n}MSE(\theta)\ \end{matrix}\right) =\frac{2}{m}{\mathbf{X}}^T\cdot{(\mathbf{X}\cdot\theta-y)} $$
提示
在這個方程中每一步計算時都包含了整個訓練集 $\mathbf{X}$,這也是為什么這個算法稱為批量梯度下降:每一次訓練過程都使用所有的的訓練數據。因此,在大數據集上,其會變得相當的慢(但是我們接下來將會介紹更快的梯度下降算法)。然而,梯度下降的運算規(guī)模和特征的數量成正比。訓練一個數千數量特征的線性回歸模型使用*梯度下降要比使用正態(tài)方程快的多。
一旦求得了方向是上山的梯度向量,你就可以向著相反的方向去下山。這意味著從 $\theta$ 中減去 $\nabla_{\theta}MSE(\theta)$。學習率 $\eta$ 和梯度向量的積決定了下山時每一步的大小,如公式 4-7。
公式 4-7:梯度下降步長
$$ \theta^{(next\ step)}=\theta - \eta\nabla_{\theta}MSE(\theta) $$
讓我們看一下這個算法的應用:
eta = 0.1 # 學習率 n_iterations = 1000 m = 100 theta = np.random.randn(2,1) # 隨機初始值 for iteration in range(n_iterations): gradients = 2/m * X_b.T.dot(X_b.dot(theta) - y) theta = theta - eta * gradiens
這不是太難,讓我們看一下最后的結果 $\theta$:
>>> theta array([[4.21509616],[2.77011339]])
看!正態(tài)方程的表現(xiàn)非常好。完美地求出了梯度下降的參數。但是當你換一個學習率會發(fā)生什么?圖 4-8 展示了使用了三個不同的學習率進行梯度下降的前 10 步運算(虛線代表起始位置)。
圖 4-8:不同學習率的梯度下降
在左面的那副圖中,學習率是最小的,算法幾乎不能求出最后的結果,而且還會花費大量的時間。在中間的這幅圖中,學習率的表現(xiàn)看起來不錯,僅僅幾次迭代后,它就收斂到了最后的結果。在右面的那副圖中,學習率太大了,算法是發(fā)散的,跳過了所有的訓練樣本,同時每一步都離正確的結果越來越遠。
為了找到一個好的學習率,你可以使用網格搜索(詳見第二章)。當然,你一般會限制迭代的次數,以便網格搜索可以消除模型需要很長時間才能收斂這一個問題。
你可能想知道如何選取迭代的次數。如果它太小了,當算法停止的時候,你依然沒有找到最優(yōu)解。如果它太大了,算法會非常的耗時同時后來的迭代參數也不會發(fā)生改變。一個簡單的解決方法是:設置一個非常大的迭代次數,但是當梯度向量變得非常小的時候,結束迭代。非常小指的是:梯度向量小于一個值 $\varepsilon$(稱為容差)。這時候可以認為梯度下降幾乎已經達到了最小值。
收斂速率:
當損失函數是凸函數,同時它的斜率不能突變(就像均方差損失函數那樣),那么它的批量梯度下降算法固定學習率之后,它的收斂速率是 $O(\frac{1}{iterations})$。換句話說,如果你將容差 $\varepsilon$ 縮小 10 倍后(這樣可以得到一個更精確的結果),這個算法的迭代次數大約會變成原來的 10 倍。
-
機器學習
+關注
關注
66文章
8349瀏覽量
132315 -
tensorflow
+關注
關注
13文章
328瀏覽量
60473 -
sklearn
+關注
關注
0文章
2瀏覽量
3390
原文標題:【翻譯】Sklearn 與 TensorFlow 機器學習實用指南 —— 第4章( 上) 訓練模型
文章出處:【微信號:AI_shequ,微信公眾號:人工智能愛好者社區(qū)】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論