2013-05-29 50 views
1

我正試圖實現一個非常簡單的1維梯度下降算法。我的代碼根本不起作用。基本上取決於我的alpha值,最終參數要麼非常大(如〜70位數),要麼基本上爲零(〜0.000)。我覺得梯度下降不應該接近alpha的敏感度(我在[0.0,1.0]中生成小數據,但我認爲梯度本身應該解釋數據的規模,不是嗎?)。任何人都可以看看一些簡單的漸變下降代碼?

下面的代碼:

#include <cstdio> 
#include <cstdlib> 
#include <ctime> 
#include <vector> 

using namespace std; 

double a, b; 
double theta0 = 0.0, theta1 = 0.0; 

double myrand() { 
    return double(rand())/RAND_MAX; 
} 

double f(double x) { 
    double y = a * x + b; 
    y *= 0.1 * (myrand() - 0.5); // +/- 5% noise 

    return y; 
} 

double h(double x) { 
    return theta1 * x + theta0; 
} 

int main() { 
    srand(time(NULL)); 
    a = myrand(); 
    b = myrand(); 

    printf("set parameters: a = %lf, b = %lf\n", a, b); 

    int N = 100; 

    vector<double> xs(N); 
    vector<double> ys(N); 
    for (int i = 0; i < N; ++i) { 
    xs[i] = myrand(); 
    ys[i] = f(xs[i]); 
    } 

    double sensitivity = 0.008; 
    double d0, d1; 

    for (int n = 0; n < 100; ++n) { 
    d0 = d1 = 0.0; 
    for (int i = 0; i < N; ++i) { 
     d0 += h(xs[i]) - ys[i]; 
     d1 += (h(xs[i]) - ys[i]) * xs[i]; 
    } 

    theta0 -= sensitivity * d0; 
    theta1 -= sensitivity * d1; 

    printf("theta0: %lf, theta1: %lf\n", theta0, theta1); 
    } 

    return 0; 
} 
+0

據我所見,你的函數「f」是一個隨機函數,但你的漸變不一定對應那個函數。如果梯度沒有很好的定義,那麼下降不能保證轉換。我錯過了什麼嗎? – Pedrom

+0

不要緊......只是意識到這是一個隨機噪聲 – Pedrom

+0

是的,'f'只是用來生成訓練數據。 'h'是我執行下降的功能。 – Alec

回答

2

改變的α的值可以產生算法發散,這樣可能是正在發生的事情的原因之一。您可以通過計算每次迭代中的錯誤來查看是否增加或減少。

此外,建議在開始時隨機設置theta的值,而不是將它們賦值爲零。

除此之外,應該由N個劃分在更新theta的值如下:

theta0 - = *靈敏度D0/N;

theta1 - = sensitivity * d1/N;

+1

使用工作GD算法和線性模型,不需要隨機初始化參數。這隻會讓事情變得更加複雜。 –

0

我快速查看了你的實現,看起來對我來說很好。

我的代碼根本不起作用。

我不會那麼說。對於sensitivity這個足夠小的值來說,它似乎表現正確,這是一個值得你「猜測」的值,這就是梯度下降應該如何工作。

我覺得自己像一個梯度下降不應該出現在阿爾法

接近這個敏感的。如果你很難想象的是,記住你是使用梯度下降,以找出最小線性的成本函數迴歸,這是一個二次函數。如果您繪製成本函數,您將看到爲什麼學習率在這些情況下非常敏感:直觀地說,如果拋物線較窄,算法會更快地收斂,這很好,但是學習速率更加「敏感」,並且如果你不小心,該算法可能很容易發生分歧。

相關問題