梯度下降算法

注:本文所有圖片及文章架構均來源於“算法糰子”,後經本人改寫所成


以上兩幅圖片顯然左側這幅能更好描述房價與面積關係,但怎樣用數學表示?

我們將其誤差定義爲J,所有點的歐氏距離之和其實就是它的誤差J

J=all(y-h(x))

如感知器算法,我們的目標就是減小J,根據梯度下降含義,我們可以將J沿着下降最快的方向調整權值,使其能夠收斂到J的最小值(極值)

下降最快的方向,就是一階導數的反方向

如下圖所示:


問題:

1.w的初始值會影響結果嗎?

答:看情況,若只有一個極小值點那不影響,若不是,則會有影響(這也是梯度下降算法的侷限性之一~)

2.一定能找到最優解麼?

答:同於上一問,不一定

3.當初始的時候,就已經爲局部最優解了,w怎樣變化?

答:如公式所示,導數爲0,不會再變化了

4.循環結束條件是什麼?

答;收斂或接近收斂,也可以自己定義一個循環次數以控制執行時間

5.a的取值

5.1 a需要不斷變化麼,以縮小學習速率?

答:不需要,因爲導數會越來越小的~

5.2 a初始值取得過大會怎樣?

a的值取得過大會導致無法收斂的情況發生,當其太大,可能會使生成的新點的導數比原來點的更大,以至於無限循環下去如下圖:

5.3 a初始值過小會怎樣

答:學習效率太慢,導致訓練好久都沒有收斂

J的推導:

J的推導過程略,此處僅寫出第一步和結果,有興趣可以自己慢慢推~



(注意,化簡時候一定注意符號問題)

注:i代表訓練樣本中的第幾個樣本

w=w-J‘(w)    注就是減去上方那一坨

C語言代碼如下:(使用之前需要特徵歸一化,關於特診歸一化見下一篇博文)

//偏導數計算的實現:
double comput_gradient(double x[][],int y[],int w[],int feature_num,int sample_num,int pian){
    //pian 變量代表着你要對哪一個求偏導數,哪一個w求
    doub  sum=0;
    for(int i=0;i<sample_num;i++){
        double tem=0;
        for(int j=0;j<feature_num;j++){
            tem+=x[i][j]*y[j];
        }
        sum+=(tem-y[i])*x[i]pian]
    }
    return sum/sample_num;
}
//以下是梯度下降算法的實現

<pre name="code" class="cpp">void gradient(double x[][],double y[],double a,double w[],int feature_num,int sample_num,int iteratortime){
    while(iteratortime--){
        double* tem=new double[feature_num];
        for(int i=0;i<feature_num;i++){
            tem[i]=w[i]-]-a*comput_gradient(x,y,w,feature_num,sample_num,i);
        }
        for(int i=0;i<feature_num;i++)
            w[i]=tem[i];
    }
}





最小二程法:

最小二乘法與梯度下降其實不是同一種算法

最小二乘法其實是對每個w求偏導,聯立方程解出的,也叫標準方程法,具體爲:

二者區別:梯度下降          最小二乘

                        有a                  無a

                  需迭代                不用迭代

               樣本大無所謂               矩陣計算複雜度高(規模小)

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