機器學習:初始點對優化的影響

簡單地說,找到給定方程的最小值被認為是優化。這在現實生活中有很多應用:路徑規劃,工作車間調度,空中交通管理等。優化一直是機器學習的支柱,人們期望這些算法從海量數據中提取知識。

優化在神經網絡中起著重要作用,神經網絡中有數百萬個參數,目標是找到正確的參數集以正確表示數據。儘管優化器的性能已經有了很大的提高,但是還有一個優化所依賴的問題,即初始點。優化的軌跡在很大程度上取決於初始點。

在這篇文章中,我們將看到初始點是如何影響一些優化算法的性能的。雖然我們在這裡使用的是一個二維問題(因為它很容易可視化),但當參數(神經網絡)達到數百萬時,初始化問題就會變得更加普遍。

目標

初始化x、y,使用梯度下降算法找到x、y的最優值,使Beale函數的值為零(或儘可能低)。

優化算法簡介

我們將考慮三種流行的優化算法,因為我們更加關注初始化,這些對於我們的分析就足夠了。

  1. 隨機梯度下降:隨機梯度下降(SGD)算法每次執行一次更新,計算每一步的梯度。。
  2. momentum:通過考慮梯度在一段時間內的動量,解決了隨機梯度下降更新緩慢的問題。
  3. Adam:被認為是最流行的優化算法。。

我們將使用PyTorch的autograd功能來獲得梯度,使用matplotlib來繪製軌跡。首先導入Python庫:

<code>import torch 
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from mpl_toolkits.mplot3d
import Axes3D from matplotlib.colors
import LogNorm
import warnings
warnings.filterwarnings("ignore")/<code>

Beale函數

機器學習:初始點對優化的影響

  1. Beale函數是在二維中定義的多峰非凸連續函數。
  2. 通常在(x,y)∈[-4.5,4.5]範圍內進行評估。
  3. 該函數只有一個全局最小值(x,y)=(3,0.5)。

可視化Beale函數

由於Beale函數是一個介於-4.5和4.5之間的雙變量函數,我們可以使用NumPy生成一個網格,將所有可能的x和y值傳遞給該函數。這使我們能夠在每一個可能的點上得到Beale函數的輸出,我們可以使用這些輸出將函數可視化。

當我們將優化問題與神經網絡聯繫起來時,我們將(x,y)稱為(w1,w2)。當使用神經網絡時,我們將目標函數稱為損失函數,並將函數的輸出稱為損失。在這種情況下,我們將Beale函數稱為損失函數,將輸出稱為損失。

<code># Defining function
f = lambda x, y: (1.5 - x + x*y)**2 + (2.25 - x + x*y**2)**2 + (2.625 - x + x*y**3)**2

# Defining the range of w1 and w2, step size
w1_min, w1_max, w1_step = -4.5, 4.5, .2
w2_min, w2_max, w2_step = -4.5, 4.5, .2

# Global minima of the function
minima_ = [3, 0.5]


# generating meshgrid
w1, w2 = np.meshgrid(np.arange(w1_min, w1_max + w1_step, w1_step),
np.arange(w2_min, w2_max + w2_step, w2_step))
losses = f(w1, w2)/<code>

現在,我們將使用以下Python代碼繪製損失。

<code>fig, ax = plt.subplots(figsize=(10, 6))
ax.contour(w1, w2, losses, levels=np.logspace(0, 5, 35),
norm=LogNorm(), cmap=plt.cm.jet, alpha = 0.8)
ax.plot(*minima_, 'r*', color='r',
markersize=10, alpha=0.7, label='minima')
ax.set_xlabel('w1')
ax.set_ylabel('w2')
ax.set_xlim((w1_min, w1_max))
ax.set_ylim((w2_min, w2_max))
ax.legend(bbox_to_anchor=(1.2, 1.))
ax.set_title("Beale Function")
fig.tight_layout(rect=[0, 0.03, 1, 0.95])/<code>

輸出

如圖所示,藍色區域表示Beale函數的值較低,紅色區域表示Beale函數的值較高。最小值(3,0.5)用星號表示。

機器學習:初始點對優化的影響

設定參數

當我們使用PyTorch時,我們需要將要優化的參數放入nn.Module類中。__init__()以(X,Y)作為輸入來初始化參數(W1,W2)。另外,我們將在forward函數中編寫Beale方程。

<code>class Net_Beale(torch.nn.Module):     
def __init__(self, x, y):
super(Net_Beale, self).__init__()
self.w1 = torch.nn.Parameter(torch.tensor([x]))
self.w2 = torch.nn.Parameter(torch.tensor([y]))
def forward(self):
# Beale Function Equation
a = (1.5 - self.w1 + self.w1*self.w2)**2
b = (2.25 - self.w1 + self.w1*self.w2**2)**2
c = (2.625 - self.w1 + self.w1*self.w2**3)**2
return a+b+c/<code>

優化和保存軌跡

下面的函數初始化網絡的參數,初始化優化器,並在收集參數路徑的同時針對指定的步驟數運行優化。

<code>def get_trajectory(x, y, optim, lr, epochs, interval=1):  
# Initialize Network
net = Net_Beale(x,y)

# Initialize Optimizer
if optim == "sgd":
optim = torch.optim.SGD(net.parameters(), lr)
elif optim == "mom":
optim = torch.optim.SGD(net.parameters(), lr, momentum=0.9)
elif optim == "adam":
optim = torch.optim.Adam(net.parameters(), lr)

# Initialize Trackers
w_1s = []
w_2s = []

# Run Optimization
for i in range(epochs):
optim.zero_grad()
o = net()
o.backward()

if i % interval == 0:
# Append current w1 and w2 to trackers
w_1s.append(net.w1.item())
w_2s.append(net.w2.item())
optim.step()

w_1s.append(net.w1.item())
w_2s.append(net.w2.item())
# Join w1's and w2's into one array
trajectory = np.array([w_1s, w_2s])
return trajectory/<code>

軌跡之間的比較

下面的函數給出了初始位置、優化器列表以及相應的學習率和epoch,並繪製了具有指定設置的算法軌跡。

<code>def compare_trajectories(x, y, epochs, optims, lrs):

colors = ['k', 'g', 'b', 'r', 'y', 'c', 'm']
trajectories = []
names = []
# Loop on all optimizers in list
for ep, optim, lr in zip(epochs, optims, lrs):
trajectory = get_trajectory(float(x), float(y), optim=optim, lr=lr, epochs=ep)
names.append(optim)
trajectories.append(trajectory)

# Plot the Contour plot of Beale Function and trajectories of optimizers
fig, ax = plt.subplots(figsize=(10, 6))
ax.contour(w1, w2, losses, levels=np.logspace(0, 5, 35),
norm=LogNorm(), cmap=plt.cm.jet, alpha = 0.5)

for i, trajectory in enumerate(trajectories):
ax.quiver(trajectory[0,:-1], trajectory[1,:-1], trajectory[0,1:]-trajectory[0,:-1],
trajectory[1,1:]-trajectory[1,:-1], scale_units='xy', angles='xy', scale=1,
color=colors[i], label=names[i], alpha=0.8)

start_ =[x,y]
ax.plot(*start_, 'r*', color='k',markersize=10, alpha=0.7, label='start')
ax.plot(*minima_, 'r*', color='r',markersize=10, alpha=0.7, label='minima')
ax.set_xlabel('w1')
ax.set_ylabel('w2')
ax.set_xlim((w1_min, w1_max))
ax.set_ylim((w2_min, w2_max))
ax.set_title("Initial point - ({},{})".format(x,y))
ax.legend(bbox_to_anchor=(1.2, 1.))
fig.suptitle("Optimization Trajectory")
fig.tight_layout(rect=[0, 0.03, 1, 0.95])/<code>

嘗試不同的初始點

在設置好一切之後,我們現在準備用不同的初始點來比較這三種算法。

學習率設置:

  • SGD— 0.0001
  • momentum— 0.0001
  • Adam-0.01

我們將對不同算法的初始點使用相同的學習率,以保持分析的簡單性,因為我們沒有進行超參數調優。

<code># Settings for optimizers 
epochs = [10000] * 3
optims = ['sgd', 'mom', 'adam']
lrs = [0.0001, 0.0001, 0.01]/<code>

情況1:接近極小點

<code>#  A point closer to minima 
x = 2.5
y = 2.
compare_trajectories(x, y, epochs, optims, lrs)/<code>
機器學習:初始點對優化的影響

這三個都達到了全局最小值,讓我們再進一步看看會發生什麼。

情況2:離極小點遠一點

<code># A little away in the same region 
x = 1.5
y = 2.5
compare_trajectories(x, y, epochs, optims, lrs)/<code>
機器學習:初始點對優化的影響

如上圖所示,Adam優化器趨向於一個局部的最小值並停滯不前,而sgd和momentum則達到了全局最小值。需要注意的是,我們並沒有改變這裡的學習率,我們關注的是初始點對優化的影響。

情況3:遠離極小值

<code># Lower left region 
x = -4
y = -4
compare_trajectories(x, y, epochs, optims, lrs)/<code>
機器學習:初始點對優化的影響

結論

初始點在優化問題中起著至關重要的作用。在這裡,我們試圖解決一個二維問題,與使用大型數據集和上百萬個參數(維度)時找到最小值相比,這很容易。雖然我們在這裡沒有調優超參數,但是我們可以使用正確的超參數集有效地將優化推向正確的方向。


分享到:


相關文章: