機器學習中梯度下降演算法的實際應用和技巧

李文哲發表於2019-03-22

當在現實生活中的遇到問題時,我們總是希望找到最佳的解決方案。製造軟體產品也是一樣的道理,最優化的程式才是最理想的產品。

最優化意味著獲得最佳輸出。它既是一個數學的重要分支,也在現實生活中有著重要的作用。現代的電腦科學和人工智慧科學把最優化作為一個重要的領域來研究。我們也認為人工智慧的一些演算法,就是模擬了人類尋求實際問題最優解的過程。例如,利用人工智慧演算法設計軟體,配合外部的電子裝置例如攝像頭識別人臉;利用資料探勘和神經網路演算法來尋找投資的最佳時機等等,都是利用了最優化的原理。

機器學習中的最優化和其他學科的應用比起來有輕微的差異。一般來說,在優化的同時,我們確切地知道資料的外觀以及我們想要改進的地方。 但是在機器學習中,我們不知道“新資料”是怎麼樣的,更別提對其進行優化了。為了解決這個問題,在機器學習中,我們對訓練資料(training data)執行優化,並檢查由此新創造出的驗證資料(validation data)。

最優化的廣泛應用

  • 機械學:設計航空航天產品的表面;
  • 經濟學:成本最小化;
  • 物理學:量子計算中的優化時間;
  • 決定最佳運輸路線,貨架空間優化等等。

許多流行的機器演算法都依賴於線性迴歸,k最近鄰,神經網路等技術。優化的應用是無限的,因此它成為了學術界和工業界廣泛研究的課題。在本文中,我們將介紹一種稱為梯度下降(Gradient Descent)的優化技術。 這是機器學習時最常用的優化技術。


1.什麼是梯度下降?

我們來看一下經典的登山示例:假設你在山頂,你必須到達山谷最低點的一個湖。 但是你被矇住眼睛,看不到你的目標。 那麼,你會採取什麼方法到達湖邊?

機器學習中梯度下降演算法的實際應用和技巧

最簡單的方法是檢查你附近的地面,找到土地向下傾斜的方向。 這是你該邁出第一步的方向。 沿著下坡路線一直走,很有可能你會到達湖泊。下圖表示你走過的路:

機器學習中梯度下降演算法的實際應用和技巧

現在我們來用數學術語來描述一下這個場景。

假設我們想要找出學習演算法的最佳引數(θ0)和(θ1)。與上面的登山示例類似,當我們繪製成本空間J(θ)函式的3D影象時發現了類似的山脈和山谷。當z軸代表成本J(θ),x軸和z軸分別對應引數θ0和θ1時,丘陵由紅色地區代表成本高,而山谷以藍色地區代表成本低。成本空間不過是演算法在某個引數選擇特定值時的表現。

現在主要有兩種型別的梯度下降演算法:

1.1 資料攝入基準法

  1. 全批梯度下降演算法(Full Batch)
  2. 隨機梯度下降演算法(Stochastic)

全批梯度下降演算法一次使用所有資料來計算梯度,而隨機梯度下降演算法可以在計算梯度時進行取樣。

1.2 分化技巧基準法

  1. 一階微分
  2. 二階微分

梯度下降需要通過成本函式J(θ)的微分方程來計算梯度。我們可以使用一階微分或二階微分。


2.執行梯度下降法所面臨的挑戰

梯度下降是一種適用於大多數情況的技術。但也有時候梯度下降也不能正常工作,或完全不能工作。發生這種情況時有三個主要原因:

2.1 來自資料的挑戰

  • 如果資料的排列方式會造成非凸優化問題(non-convex optimization problem),使用梯度下降來執行優化會非常困難。
  • 即使在優化凸優化問題時,也可能存在許多最小值。最低點稱為全域性最小值(Global Minima),其餘點稱為區域性最小值(Local Minima)。我們的目標是在避免區域性最小值的同時到達全域性最小值。
  • 還有鞍點(Saddle Point)問題。這是資料中梯度為零但不是最優點的點。目前並沒有具體的方法來避免這一點,這仍然是一個非常活躍的研究領域。

2.2 來自梯度的挑戰

  • 如果梯度下降執行的不正確,則可能導致像梯度消失(vanishing gradient)或梯度爆炸(exploding gradient)之類的問題。這些問題會在梯度過小或過大時發生,導致演算法不會收斂(Converge)。

2.3 來自實際應用難度的挑戰

  • 大多數神經網路從業人員不大關注實際應用。但是網路的資源利用率之類的事情也是非常重要的。在實施梯度下降時,具體需要多少資源是非常重要的。如果記憶體對於應用程式來說太小就一定會失敗。
  • 此外,梯度下降演算法對於浮點和硬體/軟體的要求也很高。


3.梯度下降演算法的變體

最常用的梯度下降演算法及其實施。

3.1 Vanilla(香草)梯度下降法

這是梯度下降技術的最簡單形式。香草意味著純粹/沒有任何摻假。其主要特點是通過採用成本函式的梯度向最小值方向不斷邁出小步。它的虛擬碼如下:

update = learning_rate * gradient_of_parameters
parameters = parameters - update複製程式碼

我們通過獲取舊引數的梯度來不斷更新引數。把它乘以一個學習速率(learning_rate,一個常數),表明我們想要達到最低點的速度。學習速率是一個超引數(hyper-parameter),在選擇它的大小時應該十分小心謹慎。


機器學習中梯度下降演算法的實際應用和技巧

3.2動量梯度下降(Gradient Descent with Momentum)

通過調整Vanilla演算法,可以在每次進行下一步之前注意前一步驟。

update = learning_rate * gradient
velocity = previous_update * momentum
parameter = parameter + velocity – update
複製程式碼

在這裡,update與香草梯度下降法相同。 但是引入了一個名為velocity的新術語,它考慮了之前的update和一個稱為momentum的常量。

機器學習中梯度下降演算法的實際應用和技巧

3.3 Adagrad

Adagrad使用自適應技術進行學習速率的更新。 這個演算法根據以前所有迭代的梯度變化情況來改變學習速率。虛擬碼如下:

grad_component = previous_grad_component + (gradient * gradient)
rate_change = square_root(grad_component)+epsilon
adapted_learning_rate = learning_rate * rate_change
update = adapted_learning_rate * gradient
parameter = parameter – update
複製程式碼

其中,epsilon是一個常量,用於保持學習速率的變化率。

3.4 Adam

Adam是一種基於Adagrad的自適應技術,進一步緩解了它的不足。 換句話說,它就是 Momentum + Adagrad。虛擬碼如下:

adapted_gradient = previous_gradient + 
 ((gradient – previous_gradient) * (1 – beta1))
gradient_component = (gradient_change – previous_learning_rate)
adapted_learning_rate = previous_learning_rate + 
 (gradient_component * (1 – beta2))
update = adapted_learning_rate * adapted_gradient
parameter = parameter – update
複製程式碼

其中,beta1和beta2是常量,用於檢查梯度和學習速率的變化。


4.梯度下降演算法的實際應用

使用python進行梯度下降的基本應用。

接下來我們使用梯度下降優化來找到深度學習模型的最佳引數,並將其用於影象識別問題。 我們的問題是:識別來自給定的28×28影象裡的數字。準備的圖片中,有一部分影象用於訓練,其餘部分用於測試模型。

如下是定義Vanilla梯度下降的主要程式碼:

params = [weights_hidden, weights_output, bias_hidden, bias_output]
def sgd(cost, params, lr=0.05):
 grads = T.grad(cost=cost, wrt=params)
 updates = []
 for p, g in zip(params, grads):
 updates.append([p, p - g * lr])
 return updates
updates = sgd(cost, params)
複製程式碼

我們來拆分理解一下這段程式碼。定義函式sgd作為cost,params和lr的因變數,它和如前所述的J(θ)同出一轍;而之前的θ0,θ1在這裡是深度學習演算法的引數和學習速率。 我們將預設學習速率設定為0.05,但該值可隨時被更改。

def sgd(cost, params, lr=0.05):
複製程式碼


然後我們定義了關於成本函式J(θ)的引數的梯度。 在這裡,我們使用theano庫來找到相應梯度,並且我們將theano作為T匯入

grads = T.grad(cost=cost, wrt=params)
複製程式碼

最後把所有可能的引數更新,這裡應使用Vanilla梯度下降。

for p, g in zip(params, grads):
 updates.append([p, p - g * lr]
複製程式碼

我們可以使用這個函式來為神經網路找到最佳引數。 在使用這個函式時,該神經網路出色地完成了任務,如下所示:

Prediction is: 8
複製程式碼
機器學習中梯度下降演算法的實際應用和技巧

在這個應用中,梯度下降法為深度學習演算法找到了最優引數。


5.應用梯度下降的實用技巧

上面提到的每個梯度下降演算法都有其優點和缺點。下面的一些小提示可能會幫助您選擇正確的演算法。

  • 為了快速建立原型,請使用Adam / Adagrad等自適應技術。他們很短時高效,並且不需要太多的超引數調整。
  • 要獲得最佳效果,您應該使用Vanilla梯度下降法或Momentum。雖然計算速度超級慢,但是這些結果大多比自適應技術得來的結果更準確。
  • 如果資料很小並且適合一次迭代,則可以使用二階技術,如l-BFGS。因為二階技術對於足夠小的資料的處理非常快速和準確。

神經網路無法成功學習的原因有很多。但是如果可以找到演算法出錯的地方,對未來的工作還是非常有幫助的。

在應用梯度下降法時,有以下幾點常見注意事項:

  • 錯誤率 - 應該在特定迭代後檢查訓練錯誤率、測試錯誤率,並確保它們都成減小趨勢。如果錯誤率並未減小,演算法很有可能出了問題。
  • 隱藏層中的梯度流 - 檢查是否有梯度消失或梯度爆炸的問題。
  • 學習速率 - 使用自適應技術時應該檢查。

希望您閱讀本文後,將熟練掌握有關梯度下降及其變體的基礎知識。希望你覺得我對這些演算法的實際應用的解讀也有所幫助!


相關文章