Как получить правильное количество изменений наклона для моей линейной регрессии? - PullRequest
1 голос
/ 10 мая 2019

Я хочу запрограммировать линейную регрессию с помощью Processing. Но я перепутал, какие параметры мне нужно умножить, а затем добавил или вычел из своего уклона.

Я попытался изменить параметры (сделать их отрицательными, изменить скорость обучения). На самом деле b работает, но у меня есть некоторые проблемы, чтобы правильно выбрать уклон.

//Data
float[] P1 = {100,100};
float[] P2 = {200,300};
float[] P3 = {300,250};

float[][] allData = {P1,P2,P3};

//random start values
float w1 = random(0,3);
float b = random(-100,100);

float learningRate = 0.01;
int i = 0;

void setup(){
    size(1000,1000);
}

void draw(){
    background(255);
    axes();

    //Draw Points
    for(int j=0;j<allData.length;j+=1){
    float[] point = allData[j];
        advancedPoint(point[0],point[1],color(181, 16, 32),10);
    }

    //Gradient descend, thats the confusing part...
    if(i<10000){
        i += 1;
        float dcost_dreg = 0;
        float dcost_dtar = 0;
        for(int j=0;j<allData.length;j+=1){
            float[] point = allData[j];
            float yTarget = point[1];
            float yRegression = w1*point[0] + b;
            dcost_dreg += -2*(yRegression-yTarget);  //I don't understand these lines
            dcost_dtar += -2*(yRegression-yTarget)*point[0];
        }
        w1 += learningRate * (dcost_dtar/allData.length); 
        b +=  learningRate * (dcost_dreg/allData.length) ;//until here
    }

    //Draw Regression
    linearPoints(w1, b);
}

void linearPoints (float w1, float b){
    float y;
    for(float x=-width; x<width; x=x+0.25){
        y = w1*x + b;
        strokeWeight(3);
        stroke(100,100);
        point(x+width/2, -y + height/2);
    }
}

void axes(){
    for(float a=0; a<height; a=a+0.25){
        strokeWeight(1);
        stroke(255,100,0);
        point(width/2,a);
    }
    for(float b=0; b<width; b=b+0.25){
        stroke(255,100,0);
        point(b,height/2);
    } 
}

void advancedPoint(float x,float y, color c, int size){
    strokeWeight(size);
    stroke(c);
    point(x+width/2,-y+height/2);
}

Теоретически программа должна соответствовать линейной регрессии по моим данным.

1 Ответ

0 голосов
/ 10 мая 2019

Линейная регрессия основана на уравнении Линии в форме

y = w1 * x + b

Термины

dcost_dreg += -2*(yRegression-yTarget); 
dcost_dtar += -2*(yRegression-yTarget)*point[0];

должен вычислять погрешность уравнения линии в сравнении с точками выборки, но ваш расчет неверен.

Постоянная ошибка (b error) - это разницакоординаты y выборки и координаты y, которая вычисляется по линейному уравнению для координаты x выборки.
Линейная ошибка (w1 ошибка) рассчитывается по разности градиентов.Разница в градиенте - это отношение высоты и ширины (г / х), а не произведение.
Это означает, что вычисление должно быть:

dcost_dreg += (yTarget-yRegression);
dcost_dtar += (yTarget-yRegression)/point[0];

Выражения

w1 += learningRate * (dcost_dtar/allData.length);
b  += learningRate * (dcost_dreg/allData.length);

Рассчитайте среднюю ошибку выборок и примените поправку к уравнению линии, учитывая скорость обучения.

Измените функцию draw, чтобы решить проблему:

void draw(){
    background(255);
    axes();

    //Draw Points
    for(int j=0;j<allData.length;j+=1){
        float[] point = allData[j];
        advancedPoint(point[0],point[1],color(181, 16, 32),10);
    }

    //Gradient descend, thats the confusing part...
    if(i<10000){
        i += 1;
        float dcost_dreg = 0;
        float dcost_dtar = 0;
        for(int j=0;j<allData.length;j+=1){
            float[] point = allData[j];
            float yTarget = point[1];
            float yRegression = w1*point[0] + b;
            dcost_dreg += (yTarget-yRegression);
            dcost_dtar += (yTarget-yRegression)/point[0];
        }
        w1 += learningRate * (dcost_dtar/allData.length); 
        b  += learningRate * (dcost_dreg/allData.length);
    }

    //Draw Regression
    linearPoints(w1, b);
}

Кстати, рекомендуем использовать line() для рисования оси и уравнения текущей линии:

void linearPoints (float w1, float b){
    strokeWeight(3);
    stroke(100,100,255);
    float x0 = -width;
    float x1 = width;
    float y0 = x0 * w1 + b;
    float y1 = x1 * w1 + b;
    line(x0+width/2, -y0+height/2, x1+width/2, -y1+height/2);
}

void axes(){
    strokeWeight(1);
    stroke(255,100,0);
    line(0,height/2, width, height/2);
    line(width/2, 0, width/2, height);
}
...