注:本文所有圖片及文章架構均來源於“算法糰子”,後經本人改寫所成
以上兩幅圖片顯然左側這幅能更好描述房價與面積關係,但怎樣用數學表示?
我們將其誤差定義爲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
需迭代 不用迭代
樣本大無所謂 矩陣計算複雜度高(規模小)