優化器 – Optimizer

優化器 – Optimizer

損失函數(Loss Function)在進行梯度下降(Gradient Descent)時,需要反覆計算梯度(微分)並更新參數。當模型規模變大、資料量增加時,計算成本會顯著提高,且收斂速度可能變慢。為了降低計算量、提升訓練效率並加快收斂速度,學術界提出了大量改良方法,例如 Momentum、AdaGrad、RMSprop、Adam 等。這些用來改善參數更新過程的方法,統稱為優化器(Optimizer)

meshgrid

mesh[mɛʃ] 篩孔, 網線

numpy 的 meshgrid 是一個很好用的功能,可以產生每列 x 軸的座標及每行 y 軸的座標。

import numpy as np
a = range(5)
b = range(5)
x,y = np.meshgrid(a, b)
print("每列 x 的座標")
print(x)
print("每列 y 的座標")
print(y)
結果:
每列 x 的座標
[[0 1 2 3 4]
 [0 1 2 3 4]
 [0 1 2 3 4]
 [0 1 2 3 4]
 [0 1 2 3 4]]
每列 y 的座標
[[0 0 0 0 0]
 [1 1 1 1 1]
 [2 2 2 2 2]
 [3 3 3 3 3]
 [4 4 4 4 4]]

上述不論是 x 軸或 y 軸,都是[1,n] 的二維陣列。

標示座標

如果要標示每行每列的座標,代碼如下

import numpy as np
a = range(5)
b = range(5)
x,y = np.meshgrid(a, b)
for row in zip(x, y):
    for col in  zip(row[0], row[1]):
        print(col, end='')
    print()
結果:
(0, 0)(1, 0)(2, 0)(3, 0)(4, 0)
(0, 1)(1, 1)(2, 1)(3, 1)(4, 1)
(0, 2)(1, 2)(2, 2)(3, 2)(4, 2)
(0, 3)(1, 3)(2, 3)(3, 3)(4, 3)
(0, 4)(1, 4)(2, 4)(3, 4)(4, 4)

傳統思維產生格點

如果要在二維平面上產生格點如下圖

傳統思維的代碼如下

import pylab as plt
for x in range(20):
    for y in range(20):
        plt.scatter(x,y, s=0.5, c='b')
plt.show()

plt.scatter

plt.scatter(x, y) 其中的 x 是 x 軸的集合,y 是 y 軸的集合,代碼如下

import pylab as plt
x=[0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
y=[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4]
plt.scatter(x,y,c='b')
plt.show()

上面藍色的 x, y 值,光 5*5 就打到快骨折,那麼如果是 20*20 的話,不就沒完沒了

meshgrid 產生 x , y 集合

把 meshgrid 產生的 x, y,由 [1,n] 的二維陣列轉成一維陣列 (x.reshape(-1)),再放入 plt.scatter(x, y) 就完成了。

import numpy as np
import pylab as plt
a = range(5)
b = range(5)
x, y = np.meshgrid(a, b)
x = x.reshape(-1)
y = y.reshape(-1)
print(x)
print(y)
plt.scatter(x, y, s=0.5)
plt.show()
結果:
[0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4]
[0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4]

plt 自動將二維轉成一維

上述的 x=x.reshape(-1) 其實是多餘的,因為 plt 會自動將多維扁平化成一維,所以只需如下代碼即可。

import numpy as np
import pylab as plt
a = range(5)
b = range(5)
x,y = np.meshgrid(a, b)
plt.scatter(x,y, s=0.5)
plt.show()

總結

meshgrid 的主要目的並不是要產生 (x, y) 的配對,而是要產生 x 軸的 list 及 y 軸的 list,方便傳給 plt.plot()

常態梯度下降

底下四種梯度下降 BGD、SGD、MBGD、SGDM 屬於比較簡單的運算,所以稱為常態梯度下降。

共用函數

底下的函數,在每種梯度下降都會用到,所以獨立成一個 Init.py 檔,供每種說明引用,完整代碼如下

import numpy as np
def xy(n):
    np.random.seed(42)
    x = np.arange(-5, 5.1, 10 / n)
    y = 3 * x + 2 + (np.random.rand(len(x)) - 0.5) * 20
    return x, y
def reg(x, y):
    return np.poly1d(np.polyfit(x, y, 1))

#取得等高線
def contourf(x, y):
    a=np.arange(-10,16,1)
    b=np.arange(-10,16,1)
    A, B=np.meshgrid(a,b)
    loss=np.zeros([len(a),len(b)])
    for per_x, per_y in zip(x, y):
        loss+=((A*per_x+B)-per_y)**2
    loss/=len(x)
    return A, B, loss

BGD 損失率圖解

BGD 是Batch Gradient Descent (批次梯度下降) 的縮寫。

BDG的損失函數梯度下降後,
$(\frac{\sigma Loss(a,b)}{\sigma a}=\frac{2}{n}\sum_{i=1}^{n}(ax_{i}+b-\tilde{y_{i}})*x_{i})$
$(\frac{\sigma Loss(a,b)}{\sigma b}=\frac{2}{n}\sum_{i=1}^{n}(ax_{i}+b-\tilde{y_{i}}))$

底下是BDG 類別 BDG.py 的代碼

🔒 其餘內容需登入會員。

立即登入

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *