在機器學習中,我們構建的模型,大部分都是通過求解代價函數的最優值進而得到模型參數的值。那么,對於構建好的目標函數和約束條件,我們應該如何對其進行求解呢!
在機器學習中,最常用的優化方法是梯度下降法。梯度下降法或最速下降法是求解無約束最優化問題的一種最常用的方法,有實現簡單的優點。梯度下降法是迭代算法,每一步需要求解目標函數的梯度向量。
假設f(x)是Rn上具有一階連續偏導數的函數。要求解的無約束最優化問題是:
x*表示目標函數f(x)的極小值。
梯度下降法是一種迭代算法。選取適當的初值x0,不斷迭代,更新x的值,進行目標函數的極小化,直到收斂。由於負梯度方向是使函數值下降最快的反向,在迭代的每一步,以負梯度方向更新x的值,從而達到減小函數值的目的。
由於f(x)是具有一階連續偏導數,若第k次迭代值為X(k),則可將f(x)在X(k)附近進行一階泰勒展開:
這里,為f(x)在X(k)的梯度。
求出第k+1次迭代值X(k+1):
其中,P(k)是搜索方向,取負梯度方向,
是步長,由一維搜索確定,即
使得:
當目標函數是凸函數時,梯度下降的解是全局最優解,一般情況下,其解不保證是全局最優解。梯度下降法的收斂速度也未必是很快的。
梯度下降算法根據更新梯度所使用的樣本數,又可以分為:標准梯度下降,隨機梯度下降,批量梯度下降。
標准梯度下降:通過所有的訓練樣本來進行梯度下降,每一次得到的結果都能靠近極值點,但是對於所有的樣本進行計算,每次更新需花費的時間較多。
隨機梯度下降:通過每次隨機選取一個樣本來對參數進行更新,由於是隨機選取一個樣本來進行更新,因而並不是每次迭代都能夠靠近極值點,但是迭代的整體方向是朝着最優化方向的,並且迭代的速度較快。
批量梯度下降:將上述兩種方法進行折中,就得到了批量梯度下降,將訓練數據分為若干個批次,每次選取其中的一個批次進行迭代,既能夠加快訓練速度,又能夠使得模型穩定的收斂。
簡單代碼演示:
1 import numpy as np 2 import matplotlib as mpl 3 import matplotlib.pyplot as plt 4 from mpl_toolkits.mplot3d import Axes3D 5 6 def f(x, y): 7 # z = 2*np.sin(1.5*x**2 - 0.25*y + 0.25*np.pi) + 3*np.cos(1.5*x*y - 0.5*np.pi) 8 z = np.sin(x) + np.cos(y) 9 return z 10 11 if __name__ == '__main__': 12 t = np.linspace(0, np.pi*2, 50) 13 x1, y1 = np.meshgrid(t, t) 14 z = np.stack([x1.flat, y1.flat], axis=1) 15 # print(z.shape) 16 x = z[:, 0] 17 y = z[:, 1] 18 # print(x) 19 z = f(x, y) 20 # print(z) 21 z = z.reshape(x1.shape) 22 # print(z.shape) 23 fig = plt.figure() 24 ax = Axes3D(fig) 25 ax.plot_surface(x1, y1, z, rstride=1, cstride=1, cmap='rainbow') 26 plt.xlabel("x") 27 plt.ylabel("y") 28 ax.set_zlabel("z") 29 30 x0 = 2 31 y0 = 0.5 32 n = 0.5 33 xy = [] 34 for i in range(100): 35 xn = x0 - n*np.cos(x0) 36 yn = y0 + n*np.sin(y0) 37 x0 = xn 38 y0 = yn 39 xy.append([x0, y0]) 40 xy = np.array(xy) 41 ax.plot(xy[:, 0], xy[:, 1], f(xy[:, 0], xy[:, 1]), 'k-' ,linewidth=5) 42 ax.plot(xy[:, 0], xy[:, 1], f(xy[:, 0], xy[:, 1]), 'k*' ,linewidth=20) 43 plt.show()