Градиентный спуск, сходящийся к неправильному значению

Я пытаюсь реализовать алгоритм градиентного спуска в C ++. Вот код, который у меня есть до сих пор:

#include <iostream>

double X[] {163,169,158,158,161,172,156,161,154,145};
double Y[] {52, 68, 49, 73, 71, 99, 50, 82, 56, 46 };
double m, p;
int n = sizeof(X)/sizeof(X[0]);

int main(void) {
double alpha = 0.00004; // 0.00007;
m = (Y[1] - Y[0]) / (X[1] - X[0]);
p = Y[0] - m * X[0];
for (int i = 1; i <= 8; i++) {
gradientStep(alpha);
}
return 0;
}

double Loss_function(void) {
double res = 0;
double tmp;
for (int i = 0; i < n; i++) {
tmp =  Y[i] - m * X[i] - p;
res += tmp * tmp;
}
return res / 2.0 / (double)n;
}

void gradientStep(double alpha) {
double pg = 0, mg = 0;
for (int i = 0; i < n; i++) {
pg += Y[i] - m * X[i] - p;
mg += X[i] * (Y[i] - m * X[i] - p);
}
p += alpha * pg / n;
m += alpha * mg / n;
}

Этот код сходится к m = 2,79822, р = -382,666 и ошибке 102,88. Но если я использую свой калькулятор, чтобы найти правильную модель линейной регрессии, я нахожу, что правильные значения m и p должны быть соответственно 1.601 и -191.1.

Я также заметил, что алгоритм не будет сходиться для альфа> 0,00007, что кажется довольно низким, и значение p практически не изменяется в течение 8 итераций (или даже после 2000 итераций).

Что не так с моим кодом?

Вотхороший обзор алгоритма, который я пытаюсь реализовать. Значения theta0 и theta1 в моей программе называются p и m.

Другая реализация в python

Подробнее об алгоритме

1

Решение

Эта ссылка дает исчерпывающее представление об алгоритме; оказывается, я следовал совершенно неправильному подходу.

Следующий код не работает должным образом (и я не планирую работать над ним дальше), но должен поставить в известность любого, кто сталкивался с той же проблемой, что и я:

#include <vector>
#include <iostream>

typedef std::vector<double> vect;

std::vector<double> y, omega(2, 0), omega2(2, 0);;
std::vector<std::vector<double>> X;
int n = 10;

int main(void) {
/* Initialize x so that each members contains (1, x_i) */
/* Initialize x so that each members contains y_i */
double alpha = 0.00001;
display();
for (int i = 1; i <= 8; i++) {
gradientStep(alpha);
display();
}
return 0;
}

double f_function(const std::vector<double> &x) {
double c;
for (unsigned int i = 0; i < omega.size(); i++) {
c += omega[i] * x[i];
}
return c;
}

void gradientStep(double alpha) {
for (int i = 0; i < n; i++) {
for (unsigned int j = 0; j < X[0].size(); j++) {
omega2[j] -= alpha/(double)n * (f_function(X[i]) - y[i]) * X[i][j];
}
}
omega = omega2;
}

void display(void) {
double res = 0, tmp = 0;
for (int i = 0; i < n; i++) {
tmp = y[i] - f_function(X[i]);
res += tmp * tmp; // Loss functionn
}

std::cout << "omega = ";
for (unsigned int i = 0; i < omega.size(); i++) {
std::cout << "[" << omega[i] << "] ";
}
std::cout << "\tError : " << res * .5/(double)n << std::endl;
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector