深度學習中梯度及梯度法

  • 梯度

簡單來說,例如有 y=f(x_{0},x_{1})

(\frac{\partial f}{\partial x_{0}},\frac{\partial f}{\partial x_{1}})這樣的全部由變量的偏導數組成的向量稱爲梯度(gradient)。

實際上,梯度會指向各點處的函數值降低的方向。更嚴格的講,梯度指示的方向是各點處的函數值減少最多的方向。

爲什麼這麼說,因爲方向導數=cos(\theta)×梯度,而\theta是方向導數的方向和梯度方向的夾角。所以,所有的下降方向中,梯度方向下降的最多。

 

  • 梯度法

   神經網絡的主要任務是在學習時找到最優的參數(權重和偏置),這個最優參數也就是損失函數最小時的參數。但是,一般情況下,損失函數比較複雜,參數也很多,無法確定在哪裏取得最小值。所以通過梯度來尋找最小值(或者儘可能小的值)的方法就是梯度法

   需要注意的是,梯度表示的是各點處的函數值減少最多的方向,所以梯度的方向並不一定指向最小值。但是沿着它的方向能夠最大限度地減少函數的值。因此,在尋找函數的最小值(或者儘可能小的值)的位置的時候,要以梯度的信息爲線索,決定前進的方向。

   此時梯度法就派上用場了。在梯度法中,函數的取值從當前位置沿着梯度方向前進一定距離,然後在新的方向重新求梯度,再沿着新梯度方向前進,如此反覆。

   像這樣,通過不斷地沿梯度方向前進,逐漸減小函數值的過程就是梯度法(gradient mothod)。一般來說,神經網絡(深度學習)中,梯度法主要是指梯度下降法(gradient descent mothod)。

   現在,我們試着用數學公式表達梯度下降(兩個變量情況下):

x_{0}=x_{0}-\eta \frac{\partial f}{\partial x_{0}}, x_{1}=x_{1}-\eta \frac{\partial f}{\partial x_{1}}

其中,\eta表示更新量,在神經網絡的學習中,稱爲學習率 (learning rate)。學習率決定在一次學習中,應該學習多少,以及在多大程度上更新參數。

   學習率需要事先設定爲某個值,比如0.01或0.001。一般而言,這個值過大或過小,都無法抵達一個“好的位置”。在神經網絡的學習中,一般會一邊改變學習率的值,一邊確認學習是否正確進行。

下面,我們用Python來實現梯度下降法。

def gradient_descent(f, init_x, lr=0.01, epoch=100):
    x = init_x
    for i in range(epoch):
        grad = numerical_gradient(f, x) # 求導函數
        x -= lr * grad

    return x

其中,f是要求的函數,init_x是初始值,lr是learning rate,epoch是梯度法的重複次數,也就是計算多少次。

其中numerical_gradient(f, x)爲\frac{\mathrm{d} f(x)}{\mathrm{d} x}= \frac{f(x+h)-f(x-h)}{2h},代碼如下:

# 用定義法求導數
def numerical_gradient(f, x):
    h = 1e-4
    grad = np.zeros_like(x)

    for idx in range(x.size):
        temp = x[idx]
        # 計算f(x+h)
        x[idx] = temp + h
        fxh1 = f(x)

        # 計算f(x-h)
        x[idx] = temp - h
        fxh2 = f(x)

        grad[idx] = (fxh1 - fxh2)/(2 * h)
        x[idx] = temp

    return grad

例:用梯度法求f(x_{0},x_{1})=x_{0}^{2}+x_{1}^{2} 的最小值.

def function(x):
    return x[0]**2 + x[1]**2

inin_x = np.array([-3.0, 4.0])

print(gradient_descent(function, inin_x, lr=0.1, epoch=100))

初始值爲(-3,4)可以看出結果很接近(0,0)。實際的最小值點(0,0),所以可以說基本得到了正確的結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章