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;
}
4

2 回答 2

2

更改 alpha 的值会导致算法发散,因此这可能是发生这种情况的原因之一。您可以通过计算每次迭代中的误差来检查,看看是增加还是减少。

此外,建议在开始时随机设置 theta 的值,而不是将它们分配为零。

除此之外,当您更新 theta 的值时,您应该除以 N,如下所示:

theta0 -= 灵敏度 * d0/N;

theta1 -= 灵敏度 * d1/N;

于 2013-05-29T18:10:29.777 回答
0

我快速浏览了您的实现,对我来说它看起来不错。

我的代码根本不起作用。

我不会这么说的。对于足够小的 值,它似乎表现正确sensitivity,这是一个您只需要“猜测”的值,这就是梯度下降应该如何工作的方式。

我觉得梯度下降在 alpha 中不应该如此敏感

如果您难以将其可视化,请记住您正在使用梯度下降来找到线性回归的成本函数的最小值,这是一个二次函数。如果你绘制成本函数,你会明白为什么学习率在这些情况下如此敏感:直观地说,如果抛物线很窄,算法会更快收敛,这很好,但是学习率更“敏感”并且如果你不小心,算法很容易发散。

于 2013-05-30T10:39:01.190 回答