機器學習筆記(六)--梯度下降

最近被問機器學習是怎麼訓練的,那麼就順便再深入理解梯度下降算法。

一、導數

           首先我們需要複習一下導數的知識。導數是什麼?一個導數是描述一個函數上的一個點在自變量增大時,因變量的變化率。在這裏我討論導數的對象爲二維空間上的函數。我們用極限來表達導數,當左右側導數相等時,這個點才存在導數。

                                                      \lim_{h \to 0^{-}} \frac{f(x_{0}+h)-f(x_{0})}{h}    及      \lim_{h \to 0^{+}} \frac{f(x_{0}+h)-f(x_{0})}{h}

                                                                         \frac{df}{dx} = \lim_{h \to 0} \frac{f(x+h)-f(x)}{h}

           這裏強調一下導數的方向。用一個二次函數y = x^2爲例子,這個函數的導函數就是y^{'}=2x。在(- \infty, 0)區間中,y是隨着x的增加而減少的,說明這時函數上的每個點都是負增長(沿x正方向),這就是爲什麼導函數這時y^{'}<0

二、偏導數

           將導數從二維空間推廣到多維空間,產生了多元函數的導數,就是偏導數。以二元函數z=f(x,y)爲例,如果只有自變量x變化,而另一個自變量y固定不變(看成常量),那麼這就是x的一元函數,這個函數對x的導數就是二元函數z對於x的偏導數(對y的偏導數同理可得)。與導數相似,偏導數的方向也是對應自變量增大(座標軸正方向)的方向,在其他自變量不變的情況下表達因變量的變化率。

                                                       \frac{\partial z}{\partial x} = f_{x}(x_{0},y_{0}) = \lim_{\Delta x \to 0} \frac{f(x_{0}+\Delta x,y_{0})-f(x_{0},y_{0})}{\Delta x}

三、方向導數

           導數與偏導數反映的是函數沿座標軸方向的變化率。那麼我們如何知道函數沿任意方向的變化率呢?那麼這就產生了方向導數。以二元函數f(x,y)爲例,在點P_{0}(x_{0},y_{0})可微分,那麼函數在該點沿任意方向l的方向導數存在,其中\alpha\beta分別是方向l與x軸和y軸的夾角。這樣我們就可以得到在所有自變量都發生一定改變的方向下,因變量的變化率。

                                                               \frac{\partial f}{\partial l}|_{(x_0,y_{0})} = f_x(x_{0},y_{0})cos\alpha + f_y(x_{0},y_{0})cos\beta

四、梯度

            梯度的本意是一個向量,表示某一函數在該點處的方向導數沿着該方向取得最大值,即函數在該點處沿着該方向(此梯度的方向)變化最快,變化率最大(爲該梯度的模)。換句話說,梯度就是使一個點的方向導數達到最大的方向。那麼我們怎麼求出某個點的梯度?我們還是以二元函數爲例。

            根據方向導數的定義,我們可以知道,一個方向導數是函數的各個偏導數與對應夾角餘弦值的組合。更加直觀的講,就是先將偏導數作用到各個對應基向量(單位向量),再通過類似平行四邊形法則合成的向量,就是梯度的方向。可以理解爲,梯度的方向更偏向偏導數更大的基方向。如圖例所示,假設i方向的偏導數更大,所以紅色即爲梯度方向。

                                                    grad f(x_{0},y_{0}) = \nabla f(x_{0},y_{0}) = f_{x}(x_{0},y_{0})i+f_{y}(x_{0},y_{0})j

                                            

             將梯度推廣到多元函數中,我們就可以得到一個向量,表示對應點的梯度。

                                                            \nabla f(x_{1},x_{2},...,x_{n}) = <\frac{\partial f}{\partial x_{1}},\frac{\partial f}{\partial x_{2}},...,\frac{\partial f}{\partial x_{n}} >

五、梯度下降

                機器學習的本質目標就是使損失函數達到全局最小,我們就可以利用函數的梯度來求解。因爲梯度是一個有大小與方向的向量,所以我們直接用矩陣運算來表示這個算法。以二元函數爲例,假設有原函數,即我們需要擬合的函數h,我們將函數的輸入規定爲x = \begin{bmatrix} 1, & x^{'}_{1}, & x^{'}_{2}\end{bmatrix}(shape=[3,1]),那麼參數向量就是\Theta = \begin{bmatrix} \Theta_{0}, & \Theta_{1}, & \Theta_{2} \end{bmatrix}(shape=[3,1])。那麼X = [x_{1}^{T},x_{2}^{T},...,x_{m}^{T}]就是輸入的m個樣本(shape=[m,3]),h(X)爲擬合值(shape=[m,1]),\overrightarrow{y}爲真實值(shape=[m,1])。

                                                                                   h(x) = x^{T} \Theta

                                                                                   h(X) = X \Theta

                用均方差作損失函數,這個函數的自變量是原函數的參數,因爲X是已知的樣本值,m是樣本數。這裏涉及矩陣函數求導的問題,具體方法自行查詢。

                                              J(\Theta ) =\frac{1}{2m} \sum_{i=1}^{m} (h(x^{(i)}) - y^{(i)})^{2} = \frac{1}{2m}(X\Theta - \overrightarrow{y})^{T}(X\Theta - \overrightarrow{y})

                                                          \nabla J(\Theta ) = <\frac{\partial J}{\partial\Theta _{0}} , \frac{\partial J}{\partial\Theta _{1}},\frac{\partial J}{\partial\Theta _{2}}> = \frac{1}{m}X^{T}(X\Theta -\overrightarrow{y})

                                                                      \frac{\partial J}{\partial \Theta _{0}} = \frac{1}{m} \sum_{i=1}^{m}( h(x^{(i)})- y^{(i)})       

                                                                     \frac{\partial J}{\partial \Theta _{1}} = \frac{1}{m} \sum_{i=1}^{m}( h(x^{(i)})- y^{(i)}) x{'}_{1}^{(i)}     

                                                                     \frac{\partial J}{\partial \Theta _{2}} = \frac{1}{m} \sum_{i=1}^{m}( h(x^{(i)})- y^{(i)}) x{'}_{2}^{(i)}

                迭代訓練開始之前,我們初始化\Theta^{0} = \begin{bmatrix} \Theta_{0}^{0} & \Theta_{1}^{0} & \Theta_{2}^{0} \end{bmatrix}^{T},有以下迭代公式。其中,\alpha就是學習率。本質上梯度還是自變量增大的方向,只是每個自變量增大的幅度不同。注意上面偏導數的寫法,是h-y,這樣纔是當偏導數>0的時候,因變量爲正增長,所以要將對應\Theta_{i}變小。

                                                                         \Theta^{n} = \Theta^{n-1} - \alpha \nabla J(\Theta ^{n-1})

六、代碼實現

                在這裏我用python代碼模擬梯度下降是如何一步一步到達函數的全局最小值點。

import numpy as np

# y = 1 + 2x1 + 3x2
x = np.random.random_integers(1,100,[10,3])
x[:,0] = 1

theta = np.zeros([3])
theta_real = np.asarray([1,2,3])

def PartialTheta0(x,theta):
    J = 0
    for i in range(len(x)):
        J += (np.matmul(theta,x[i]) - np.matmul(theta_real,x[i]))
    return J / len(x)

def PartialTheta1(x,theta):
    J = 0
    for i in range(len(x)):
        J += ((np.matmul(theta,x[i]) - np.matmul(theta_real,x[i])) * x[i][1])
    return J / len(x)

def PartialTheta2(x,theta):
    J = 0
    for i in range(len(x)):
        J += ((np.matmul(theta, x[i]) - np.matmul(theta_real, x[i])) * x[i][2])
    return J / len(x)


for _ in range(100000):
    theta -= 0.000001 * np.asarray([PartialTheta0(x,theta),PartialTheta1(x,theta),PartialTheta2(x,theta)])
    # theta -= 0.000001 * np.matmul(x.transpose(),np.matmul(x,theta)-np.matmul(x,theta_real)) / len(x)
    print(theta)


                   通過運行輸出可以看到,參數在一步步靠近真實值,說明算法是有效的。

 

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