在本文中,我們將通過計算二次凸函數(shù)的最優(yōu)點來比較主要的深度學(xué)習(xí)優(yōu)化算法的性能。
簡介
深度學(xué)習(xí)被稱為人工智能的未來?,F(xiàn)在,神經(jīng)網(wǎng)絡(luò)被稱為通用函數(shù)逼近器,也就是說,它們有能力表示這個宇宙中任何復(fù)雜的函數(shù)。計算這個具有數(shù)百萬個參數(shù)的通用函數(shù)的想法來自優(yōu)化的基本數(shù)學(xué)。優(yōu)化可以通過多種方式完成,但在本文中,我們將重點討論基于梯度下降的優(yōu)化技術(shù)。
非凸函數(shù)的優(yōu)化是研究的主要領(lǐng)域。多年來,不同的科學(xué)家提出了不同的優(yōu)化算法來優(yōu)化神經(jīng)網(wǎng)絡(luò)的成本函數(shù)。這些算法大部分都是基于梯度的方法,稍作修改。在這篇文章中,我們將討論5個專業(yè)的下降基于算法-Gradient Descent,Momentum,Adagrad, RMSprop, Adam。
方法
為了了解每個算法在實際中是如何工作的,我們將使用一個凸二次函數(shù)。我們將對每個算法進行固定次數(shù)的迭代(20次),以比較它們在達到最優(yōu)點時的收斂速度和軌跡。下面給出了為此任務(wù)選擇的函數(shù)的方程,以及使用Matplotlib繪制的函數(shù)的三維圖和級別集。
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(13,6))
ax = plt.axes(projection="3d")
start, stop, n_values = -8, 8, 800
x_vals = np.linspace(start, stop, n_values)
y_vals = np.linspace(start, stop, n_values)
X, Y = np.meshgrid(x_vals, y_vals)
Z = np.sqrt(0.1*X**2 + 2*Y**2)
plt.contourf(X,Y,Z,)
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='winter', edgecolor='none')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
首先,我們將從最基本的梯度下降算法開始,然后我們將跟隨它們發(fā)展的趨勢來支持每個算法發(fā)展背后的想法。所以趨勢是這樣的
1-Gradient Descent
2-Momentum
3-Adagrad
4-RMSprop
5-Adam
因為所有這些算法在更新規(guī)則的每次迭代時都需要梯度。因此,下面給出了函數(shù)的梯度,用于在每次迭代時更新兩個變量。我們將對所有算法使用固定的學(xué)習(xí)率值=0.4。
1、Gradient Descent
梯度下降法是求解最優(yōu)解的最傳統(tǒng)的方法。在這個算法中,使用當(dāng)前梯度(gt)乘以一些稱為學(xué)習(xí)率的因子來更新當(dāng)前權(quán)值。更新規(guī)則的公式如下所示。
lr=0.4
x1=-4
x2=-6
l1_gd=[]
l2_gd=[]
for i in range(20):
l1_gd.append(x1)
l2_gd.append(x2)
x1=x1-lr*0.2*x1
x2=x2-lr*4*x2
使用梯度下降的軌跡
fig = plt.figure(figsize=(13,6))
left, bottom, width, height = 100, 0.1, 0.8, 0.8
ax = fig.add_axes([left, bottom, width, height])
start, stop, n_values = -8, 8, 100
x_vals = np.linspace(start, stop, n_values)
y_vals = np.linspace(start, stop, n_values)
X, Y = np.meshgrid(x_vals, y_vals)
Z = np.sqrt(0.1*X**2 + 2*Y**2)
plt.contourf(X,Y,Z,)
plt.plot(l1_gd[:15],l2_gd[:15],color="red",marker="*",markeredgecolor="black",linewidth=3,label="Gradient Descent")
plt.figure(figsize=(15,10))
plt.figure(figsize=(15,10))
ax.set_title('Level Sets of the Function',size=20)
ax.set_xlabel('x (cm)')
ax.set_ylabel('y (cm)')
ax.legend()
plt.show()
正如我們在上面的圖中看到的,梯度下降經(jīng)歷了很多振蕩,收斂速度非常慢。所以在后面的部分,我們將學(xué)習(xí)梯度下降的改進,它將幫助我們實現(xiàn)穩(wěn)定和更快的收斂。
2、Momentum
動量梯度下降是一種常用的優(yōu)化器,它消除了標(biāo)準(zhǔn)梯度下降引起的振蕩,加速了收斂最優(yōu)點。當(dāng)它在水平方向上加速時,它在垂直方向上減速。在這種杰出行為的幫助下,它使我們在學(xué)習(xí)率的方向上邁出了一大步。此外,動量比標(biāo)準(zhǔn)梯度下降要穩(wěn)定得多。
下面給出的方程式解釋了更新規(guī)則-
v1,v2=0,0
gamma,lr=0.5,0.4
x1,x2=-4,-6
l1_gd_m,l2_gd_m=[],[]
for i in range(20):
l1_gd_m.append(x1)
l2_gd_m.append(x2)
v1=gamma*v1+(0.2*x1)
v2=gamma*v2+(4*x2)
x1=x1-lr*v1
x2=x2-lr*v2
Gradient Descent vs Momentum
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(13,6))
left, bottom, width, height = 100, 0.1, 0.8, 0.8
ax = fig.add_axes([left, bottom, width, height])
start, stop, n_values = -8, 8, 100
x_vals = np.linspace(start, stop, n_values)
y_vals = np.linspace(start, stop, n_values)
X, Y = np.meshgrid(x_vals, y_vals)
Z = np.sqrt(0.1*X**2 + 2*Y**2)
plt.contourf(X,Y,Z,)
plt.plot(l1_gd[:15],l2_gd[:15],color="red",marker="*",markeredgecolor="black",linewidth=3,label="Gradient Descent")
plt.plot(l1_gd_m[:15],l2_gd_m[:15],color="yellow",marker="*",markeredgecolor="orange",linewidth=3,label="Gradient Descent (Momentum =0.5)")
plt.figure(figsize=(15,10))
plt.figure(figsize=(15,10))
ax.set_title('Level Sets of the Function',size=20)
ax.set_xlabel('x (cm)')
ax.set_ylabel('y (cm)')
ax.legend()
plt.show()
3、Adagrad
自適應(yīng)梯度下降算法(adaptive gradient descent)是一種學(xué)者梯度下降算法。其主要區(qū)別在于Adagrad根據(jù)網(wǎng)絡(luò)中參數(shù)的重要性對每個權(quán)值利用不同的學(xué)習(xí)速率。換句話說,用較高的學(xué)習(xí)率訓(xùn)練不必要的參數(shù),用較小的學(xué)習(xí)率訓(xùn)練重要參數(shù),使其更穩(wěn)定地收斂。在不允許失真的情況下,實現(xiàn)了算法的加速。更新公式類似于動量,這里每一步的動量是用之前的動量和梯度的平方來計算的。下面的公式顯示了Adagrad中的更新規(guī)則。
Gt是一個對角矩陣組成的平方和過去的漸變和?平滑項。此外,表示矩陣-向量積運算。
v1,v2=0,0
gamma,lr=0.9,0.4
x1,x2=-4,-6
l1_adagrad,l2_adagrad=[],[]
for i in range(20):
l1_adagrad.append(x1)
l2_adagrad.append(x2)
v1=v1+(0.2*x1)**2
v2=v2+(4*x2)**2
x1=x1-(lr/math.sqrt(v1+c))*0.2*x1
x2=x2-(lr/math.sqrt(v2+c))*4*x2
Momentum vs Adagrad
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(13,6))
left, bottom, width, height = 100, 0.1, 0.8, 0.8
ax = fig.add_axes([left, bottom, width, height])
start, stop, n_values = -8, 8, 100
x_vals = np.linspace(start, stop, n_values)
y_vals = np.linspace(start, stop, n_values)
X, Y = np.meshgrid(x_vals, y_vals)
Z = np.sqrt(0.1*X**2 + 2*Y**2)
plt.contourf(X,Y,Z,)
plt.plot(l1_gd[:15],l2_gd[:15],color="red",marker="*",markeredgecolor="black",linewidth=3,label="Gradient Descent")
plt.plot(l1_gd_m[:15],l2_gd_m[:15],color="yellow",marker="*",markeredgecolor="orange",linewidth=3,label="Gradient Descent (Momentum =0.5)")
plt.plot(l1_adagrad[:15],l2_adagrad[:15],color="blue",marker="*",markeredgecolor="black",linewidth=3,label="Adagrad")
plt.figure(figsize=(15,10))
plt.figure(figsize=(15,10))
ax.set_title('Level Sets of the Function',size=20)
ax.set_xlabel('x (cm)')
ax.set_ylabel('y (cm)')
ax.legend()
plt.show()
從上圖中可以看出,Adagrad雖然運動平穩(wěn)無振蕩,但收斂能力不足。為了解決這個問題,Geoffrey Hinton引入了一個更有效的優(yōu)化器RMSprop。
4、RMSprop
Rmsprop是由著名計算機科學(xué)家Geoffrey Hinton (Hinton et al., 2012)提出的另一種高效優(yōu)化算法。該算法的工作原理與Adagrad相似,只是稍加修改。不像AdaGrad那樣取梯度平方的累積和,我們?nèi)∵@些梯度的指數(shù)移動平均值。使用指數(shù)平均的原因是為了給最近更新的梯度權(quán)重大于最近更新的梯度。下面的方程式顯示了Rmsprop的更新規(guī)則。
v1,v2=0,0
gamma,lr=0.9,0.4
x1,x2=-4,-6
l1,l2=[],[]
for i in range(20):
l1.append(x1)
l2.append(x2)
v1=gamma*v1+(1-gamma)*(0.2*x1)**2
v2=gamma*v2+(1-gamma)*(4*x2)**2
x1=x1-(lr/math.sqrt(v1+c))*0.2*x1
x2=x2-(lr/math.sqrt(v2+c))*4*x2
Momentum vs Adagrad vs RMSprop
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(13,6))
left, bottom, width, height = 100, 0.1, 0.8, 0.8
ax = fig.add_axes([left, bottom, width, height])
start, stop, n_values = -8, 8, 100
x_vals = np.linspace(start, stop, n_values)
y_vals = np.linspace(start, stop, n_values)
X, Y = np.meshgrid(x_vals, y_vals)
Z = np.sqrt(0.1*X**2 + 2*Y**2)
plt.contourf(X,Y,Z,)
plt.plot(l1_gd[:15],l2_gd[:15],color="red",marker="*",markeredgecolor="black",linewidth=3,label="Gradient Descent")
plt.plot(l1_gd_m[:15],l2_gd_m[:15],color="yellow",marker="*",markeredgecolor="orange",linewidth=3,label="Gradient Descent (Momentum =0.5)")
plt.plot(l1_adagrad[:15],l2_adagrad[:15],color="blue",marker="*",markeredgecolor="black",linewidth=3,label="Adagrad")
plt.plot(l1[:15],l2[:15],color="g",marker="*",markeredgecolor="b",linewidth=3,label="RMSprop Algorithm")
plt.figure(figsize=(15,10))
plt.figure(figsize=(15,10))
ax.set_title('Level Sets of the Function',size=20)
ax.set_xlabel('x (cm)')
ax.set_ylabel('y (cm)')
ax.legend()
plt.show()
顯而易見,當(dāng)收斂到最優(yōu)點時,梯度下降算法在垂直方向上產(chǎn)生巨大的振蕩,RMSprop限制了垂直運動,加速了水平方向。此外,雖然動量減小了振蕩,RMSprop提供了更可靠和更快的收斂。
5、Adam
自適應(yīng)矩估計是另一種計算每個參數(shù)的自適應(yīng)學(xué)習(xí)率的優(yōu)化器。與其他優(yōu)化器相比,它更加健壯和可靠,因為它基本上結(jié)合了動量和RMSprop(即。移動類似梯度的動量的平均值,并使用梯度的平方來調(diào)整學(xué)習(xí)速率,如RMSprop)。更精確地說,Adam算法執(zhí)行如下-
v1,v2,s1,s2=0,0,0,0
gamma,beta,lr=0.9,0.999,0.4
x1,x2=-6,-6
l1_adam,l2_adam=[],[]
for i in range(20):
l1_adam.append(x1)
l2_adam.append(x2)
v1=gamma*v1+(1-gamma)*(0.2*x1)
v2=gamma*v2+(1-gamma)*(4*x2)
s1=beta*s1+(1-beta)*(0.2*x1)**2
s2=beta*s2+(1-beta)*(4*x2)**2
m_hat_v1= v1 / (1 - np.power(gamma, i+1))
m_hat_v2 = v2 / (1 - np.power(gamma, i+1))
s_hat_s1= s1 / (1 - np.power(beta, i+1))
s_hat_s2 = s2 / (1 - np.power(beta, i+1))
x1=x1-(lr)*(m_hat_v1/math.sqrt((s_hat_s1)+c))
x2=x2-(lr)*(m_hat_v2/math.sqrt((s_hat_s2)+c))
print(x1,x2)
if abs(x1)<=0.1 and abs(x2)<0.1:
break
在收斂期間的軌跡匯總
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(13,6))
left, bottom, width, height = 100, 0.1, 0.8, 0.8
ax = fig.add_axes([left, bottom, width, height])
start, stop, n_values = -8, 8, 100
x_vals = np.linspace(start, stop, n_values)
y_vals = np.linspace(start, stop, n_values)
X, Y = np.meshgrid(x_vals, y_vals)
Z = np.sqrt(0.1*X**2 + 2*Y**2)
plt.contourf(X,Y,Z,)
plt.plot(l1_gd[:15],l2_gd[:15],color="red",marker="*",markeredgecolor="black",linewidth=3,label="Gradient Descent")
plt.plot(l1_gd_m[:15],l2_gd_m[:15],color="yellow",marker="*",markeredgecolor="orange",linewidth=3,label="Gradient Descent (Momentum =0.5)")
plt.plot(l1_adagrad[:15],l2_adagrad[:15],color="blue",marker="*",markeredgecolor="black",linewidth=3,label="Adagrad")
plt.plot(l1[:15],l2[:15],color="g",marker="*",markeredgecolor="b",linewidth=3,label="RMSprop Algorithm")
plt.plot(l1_adam[:20],l2_adam[:20],color="Brown",marker="*",markeredgecolor="pink",linewidth=3,label="Adam")
plt.figure(figsize=(15,10))
plt.figure(figsize=(15,10))
ax.set_title('Level Sets of the Function',size=20)
ax.set_xlabel('x (cm)')
ax.set_ylabel('y (cm)')
ax.legend()
plt.show()
正如在最后的圖中所看到的,Adam優(yōu)化器在直線路徑上導(dǎo)致最快的收斂。在Adam的例子中,它通過累積之前梯度的總和來減弱振蕩,并且由于梯度的平方項,它遵循一條直線,類似于RMSprop。這導(dǎo)致了一個明顯的結(jié)論,即Adam是Momentum和RMSprop的結(jié)合版本。從上圖中我們可以很容易地看出為什么Adam是deep learning中最流行的優(yōu)化器。即使從離最優(yōu)值(-6,-6)很遠的地方開始,Adam也能以最小的迭代收斂得最快。
作者:Saket Thavanani
本文代碼地址:https://github.com/Saket-Uoft/Deep-Learning-Optimizers