磐創AI分享   

來源 | GiantPandaCV

作者 | zzk

【導讀】 在深度學習任務中,我們常常會爲模型定義一個損失函數,損失函數表徵的是預測值和實際值之間的差距,再通過一定的優化算法減小這個差距然後絕大多數情況下,我們的損失函數十分複雜,不像我們解數學題能得到一個確定,唯一的解析解。而是通過數學的方法去逼近一個解,也稱 數值解。

局部最小值和全局最小值

假設我們的損失函數是

image-20200506204323155
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-2, 2, 0.01)
print(x)
f = x*np.cos(np.pi*x)
plt.plot(x, f)
plt.show()

我只畫出了區間(-2, 2)的函數圖像,通過觀察圖像,我們發現該函數有兩個波谷,分別是局部最小值和全局最小值。

到達局部最小值的時候,由損失函數求得的 梯度接近於0 ,我們 很難再跳出這個局部最小值 ,進而優化到全局最小值,即x=1處,這也是損失函數其中的挑戰

鞍 點

假設我們的損失函數爲

image-20200506205323585

文章所標的點,即是鞍點(saddle point),形狀像馬鞍處。

它的特點也是兩邊的梯度趨近於0,但並不是真正的最小值點

在深度學習優化過程中,這兩種情況很常見,我們需要儘可能地通過數學方式去逼近最優

梯度下降爲什麼有效

這裏需要用到高數里面的泰勒展開公式

其中

由於ε是個極小值,所以我們可以用梯度乘上一個很小的數,去替代

由於梯度的平方是恒大於0的,因此有

看到這裏大家應該就明白了,其中n代表的是超參數學習率,我們通過讓x減去一個常數乘以學習率,使得目標損失函數值得到下降

接下來我會以函數

作爲一個梯度下降例子

以下是我的畫圖代碼

import matplotlib.pyplot as plt
import numpy as np

def gradient_optimizer(eta):
x = 0.5
results = [x]
for i in range(5):
# 函數x*np.cos(np.pi*x)的導數爲np.cos(np.pi * x) - x * np.sin(np.pi * x)
x -= eta * (np.cos(np.pi * x) - x * np.sin(np.pi * x))
results.append(x)
return results


res = gradient_optimizer(0.1)


def fx(arr):
ans = []
for num in arr:
ans.append(num * np.cos(np.pi * num))
return ans


def plot():
x = np.arange(-2, 2, 0.01)
y = x * np.cos(np.pi * x)
res_y = fx(res)
plt.plot(x, y)
plt.plot(res, res_y, '-o')
plt.show()


plot()

image-20200506212515114

函數從x=0.5開始,很順利的優化到了全局最小值的地方

那麼我們換到x = -1.0,並增加迭代步伐,再次觀察梯度下降情況

image-20200506212649497

我們將迭代步伐調至20,可見我們卡在局部最小值,無法跳出

那麼我們試試增大學習率,看能不能跳出來

我將eta設置爲1.000542(PS:這個函數太刁鑽了,調了半天學習率才達到想要的結果)

image-20200506213117915

可以看見再經歷過一系列震盪後,我們的函數成功到達了全局最小值點,當然背後是我找這個參數的心酸。

我們再把學習率參數調大一點點,將eta設置爲1.0055

image-20200506213334210

這裏我們也可以看得出學習率的關係

當學習率很小,我們下降較爲平滑,但容易卡在局部最小值點

當學習率很大,我們梯度優化過程中會十分劇烈,可能達到全局最小值點,但也很可能距離優化目標越來越遠

隨機梯度下降SGD

假設我們有n個樣本數據,那麼每次進行梯度下降,我們需要分別對每個數據計算其梯度。

時間複雜度爲O(n),當樣本很多的時候,這個計算開銷是非常大的。

隨機梯度下降則是在梯度下降每次迭代當中, 隨機採取一個樣本,計算其梯度,作爲整體梯度進行下降 ,我們的計算開銷也就下降到了O(1)

爲了梯度值更穩定,我們也可以選擇小批量隨機梯度下降, 以一小批樣本的梯度作爲整體的梯度估計

動量法Momentum

我們實際優化的函數會十分複雜,最常見的函數是多維的情況。當函數在某個方向上變化十分劇烈,則對應方向上的梯度變化也十分劇烈,爲了達到收斂,需要更多時間步迭代。

梯度變化劇烈的另外一個原因是,我們單一地考慮了當前的梯度,而忽略了以前的梯度情況。

當我們把以前的梯度加入到當前梯度計算中,會緩解這種問題,加速收斂

動量法引入了一個速度變量,初始化爲0,由以下兩個公式進行變量維護

指數移動平均

這裏參考的是mxnet出品的動手學教程

我們假設有下面公式

繼續展開得到

則這裏直接是變量替換而我們由高數的常見的極限公式可得

而,則舉個例子,取,則根據前面的極限公式如果我們把0.37看作是個很小的數,那我們可以忽略了更高階的係數,比如等等 換句話說,當,我們只關注近十個階數的係數

簡單來說,指數移動平均就是計算近幾個時間步的加權平均,時間越近,對應的權重就越大

接下來我們對動量法的速度變量進行變形

我們相當於是對

這一項做了移動平均。因此動量法能綜合考慮一定量時間步內的梯度情況

AdaGrad算法

在前面兩種優化算法裏,自變量的每一個元素都是使用同一學習率來自我迭代。

而在前面我們對學習率討論中,不同學習率所帶來的優化效果也不同。

因此我們在思考能否提出一個自適應學習率調整的優化算法

AdaGrad算法維護一個狀態變量

通過以下兩個公式進行迭代更新

我們可以看到狀態變量S每次都是通過梯度按元素平方進行迭代,這樣每個變量就有自己特定的學習率,而且狀態變量放置在分母下,能逐步調小學習率, 不需要人爲進行調整。

缺點就是可能模型還未收斂,學習率已經過小,很難找到合適的數值解

RMSProp算法

既然AdaGrad缺點是因爲平方函數是個遞增函數,一直迭代會讓學習率持續下降。

那麼我們不妨將動量法的移動平均思想,用於處理狀態變量s

因此RMSProp算是結合了Adagrad和Momentum的思想

計算公式如下

移動平均並不是一個單調遞增的函數,因此它能更好地調節學習率

Adam算法

Adam算法則是結合了RMSProp和Momentum算法

它在RMSProp算法基礎上也對梯度變量做了指數加權移動平均

公式如下

這裏對速度變量做的指數移動平均與動量法的方法有點區別

在t較小的時候,各個時間步權值之和不爲1

因此需要做個偏差修正

然後調整每個元素的學習率

- End -

✄------------------------------------------------

看到這裏,說明你喜歡這篇文章,請點擊「 在看 」或順手「 轉發 」「 點贊 」。

歡迎微信搜索「 panchuangxx 」,添加小編 磐小小仙 微信,每日朋友圈更新一篇高質量推文(無廣告),爲您提供更多精彩內容。

▼       掃描二維碼添加小編   ▼    ▼  

相關文章