首页 文章

线性回归的梯度下降不收敛

提问于
浏览
0

我已经在JavaScript中使用梯度下降算法实现了一个非常简单的线性回归,但在咨询了多个来源并尝试了几个方面后,我无法将其收敛 .

数据是绝对线性的,它只是数字0到30作为输入,x * 3作为正确的输出要学习 .

这是梯度下降背后的逻辑:

train(input, output) {
  const predictedOutput = this.predict(input);
  const delta = output - predictedOutput;

  this.m += this.learningRate * delta * input;
  this.b += this.learningRate * delta;
}

predict(x) {
  return x * this.m + this.b;
}

我从不同的地方拿了公式,包括:

我已经尝试过了:

  • 将输入和输出值标准化为[-1,1]范围

  • 将输入和输出值标准化为[0,1]范围

  • 将输入和输出值标准化为mean = 0和stddev = 1

  • 降低学习率(1e-7和我去的一样低)

  • 具有完全没有偏差的线性数据集( y = x * 3

  • 具有非零偏差的线性数据集( y = x * 3 + 2

  • 使用介于-1和1之间的随机非零值初始化权重

仍然,权重( this.bthis.m )不接近任何数据值,并且它们分叉到无穷大 .

我显然做错了什么,但我无法弄清楚它是什么 .


Update: 这里有一些更多的上下文可能有助于弄清楚我的问题究竟是什么:

我试图通过线性回归伪神经元在线学习来模拟线性函数的简单近似 . 有了它,我的参数是:

  • 重量:[ this.mthis.b ]

  • 输入:[ x1 ]

  • 激活功能:身份功能 z(x) = x

因此,我的网络将由 y = this.m * x + this.b * 1 表示,模拟我想要近似的数据驱动函数( y = 3 * x ) .

我想要的是我的网络_29454230_参数 this.m = 3this.b = 0 ,但似乎我陷入了局部最小值 .

我的错误函数是均方误差:

error(allInputs, allOutputs) {
  let error = 0;
  for (let i = 0; i < allInputs.length; i++) {
    const x = allInputs[i];
    const y = allOutputs[i];
    const predictedOutput = this.predict(x);
    const delta = y - predictedOutput;

    error += delta * delta;
  }

  return error / allInputs.length;
}

我更新我的权重的逻辑将是(根据我迄今为止检查的来源) wi -= alpha * dError/dwi

为了简单起见,我将调用我的权重 this.mthis.b ,因此我们可以将其与我的JavaScript代码相关联 . 我还将 y^ 称为预测值 .

从这里:

error = y - y^
      = y - this.m * x + this.b

dError/dm = -x
dError/db = 1

因此,将其应用于权重修正逻辑:

this.m += alpha * x
this.b -= alpha * 1

但这似乎不正确 .

1 回答

  • 3

    我终于发现了什么是错的,我正在回答我自己的问题,希望它也能帮助这个领域的初学者 .

    首先,正如萨沙所说,我有一些理论上的误解 . 你的调整包括逐字输入值可能是正确的,但正如他所说,它应该已经是渐变的一部分 . 这一切都取决于您选择的错误功能 .

    您的误差函数将衡量您用什么来衡量您与真实值的关系,并且该测量需要保持一致 . 我使用均方误差作为测量工具(你可以在我的 error 方法中看到),但我在训练方法中使用纯绝对误差( y^ - y )来测量误差 . Your gradient will depend on the choice of this error function. 所以只选择一个并坚持下去 .

    第二, simplify your assumptions in order to test what's wrong . 在这种情况下,我非常清楚要近似的函数是什么( y = x * 3 )所以我手动将权重( this.bthis.m )设置为正确的值,我仍然看到错误发散 . 这意味着在这种情况下权重初始化不是问题 .

    在搜索了一些之后,我的错误就在其他地方:将数据输入网络的功能错误地将 3 硬编码值传递给预测输出(它在数组中使用了错误的索引),因此我看到的振荡是因为尝试近似于 y = 0 * x + 3this.b = 3this.m = 0 )的网络,但由于学习率较小且误差函数导数中的误差, this.b 无法接近正确的值,使 this.m 进行疯狂跳跃调整它 .

    最后, keep track of the error measurement as your network trains ,这样您就可以了解正在发生的事情 . 这有助于识别简单过度拟合,大学习率和简单的简单错误之间的差异 .

相关问题