【发布时间】:2016-02-07 04:57:20
【问题描述】:
我正在尝试在 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,p = -382.666,误差为 102.88。但是如果我用我的计算器找出正确的线性回归模型,我发现m和p的正确值应该分别是1.601和-191.1。
我还注意到,对于 alpha > 0.00007,该算法不会收敛,这似乎很低,并且 p 的值在 8 次迭代期间几乎没有变化(甚至在 2000 次迭代之后)。
我的代码有什么问题?
Here 很好地概述了我正在尝试实现的算法。 theta0 和 theta1 的值在我的程序中称为 p 和 m。
【问题讨论】:
-
您能否分享一个链接,您使用此代码实现的数学公式?我不是数学编程专家,但我可能会在某处建议太小的值,即非规范化,或公式和实现之间的明显分歧。
-
另外,您确定
return res / 2.0 / (double)n;会按照您的意愿行事(考虑到运算符的关联性)? -
这里是 Python 中类似实现的链接:spin.atomicobject.com/2014/06/24/… 您还可以在此处阅读更多相关信息:en.wikipedia.org/wiki/Gradient_descent 对于您提到的那一行,我正在尝试返回 1/2n * res ,这就是我这样写的原因。但是损失函数只是一种检查结果的手段,它本身并不会改变得到的值。
标签: c++ linear-regression gradient-descent convergence