我的多项式回归梯度下降有什么问题(C++,GNUPLOT)
What is wrong with my gradient descent for Polynomial Regresion (C++, GNUPLOT)
我尝试为多项式回归实现梯度下降。我以为我什么都明白了,但好像哪里不对。
以上公式取自 coursera 机器学习讲义。
现在,代码呢:
for(int m=1;m<=degree;m++){
for(int i = 0;i<iterations;i++)
{
getCoefs(learningStep,m);
}
qDebug()<<"Parameters:";
for(int i=0;i<=degree;i++) {qDebug()<<coefs[i];}
switch(m){
case 1: equation = to_string(coefs[1]) + "*x+" + to_string(coefs[0]);
g1.set_style("lines").plot_equation(equation,"x^1"); break;
case 2: equation = to_string(coefs[2])+ "*x**2+" + to_string(coefs[1]) + "*x+" + to_string(coefs[0]);
g1.set_style("lines").plot_equation(equation,"x^2"); break;
case 3: equation = to_string(coefs[3])+ "*x**3+" +to_string(coefs[2])+ "*x**2+" + to_string(coefs[1]) + "*x+" + to_string(coefs[0]);
g1.set_style("lines").plot_equation(equation,"x^3"); break;
case 4: equation = to_string(coefs[4])+ "*x**4+" + to_string(coefs[3])+ "*x**3+" +to_string(coefs[2])+ "*x**2+" + to_string(coefs[1]) + "*x+" + to_string(coefs[0]);
g1.set_style("lines").plot_equation(equation,"x^4"); break;
case 5: equation = to_string(coefs[5])+ "*x**5+" + to_string(coefs[4])+ "*x**4+" + to_string(coefs[3])+ "*x**3+" +to_string(coefs[2])+ "*x**2+" + to_string(coefs[1]) + "*x+" + to_string(coefs[0]);
g1.set_style("lines").plot_equation(equation,"x^5"); break;
}
for(int i=0;i<=degree;i++) {coefs[i]=0;}
}
这是绘制方程的函数。
Coefs 是参数 {ø1,ø2...øn}
的向量
degree是我要计算的最大度数的整数。
迭代步数,在我的例子中是2000
learningStep 不用解释了(0.001 [我也试了更大的LS 0.01 结果也是错误的])
void getCoefs(double learningStep, int degree){
QVector < double > sum;
for(int j=0;j<=degree;j++){
sum.push_back(0);
}
double numberOfPoints = point.length();
QVector < double > actual;
for(int j=0;j<=degree;j++){
actual.push_back(coefs[j]);
}
for(int i=0;i<point.length();i++){
for(int j=0;j<=degree;j++){
sum[j] += (1/numberOfPoints) *(((actual[1]*point[i].getX() + actual[0]) - (point[i].getY()))*pow(point[i].getX(), j));
}
}
for(int j=0;j<=degree;j++){
coefs[j] -= learningStep*sum[j];
}
}
这是我获取系数的代码。
point 是点向量(具有两个变量 x,y 的对象)。
actual 是包含假设函数系数的向量。
这里我们计算图一所示的总和:
sum[j] += (1/numberOfPoints) *(((actual1*point[i].getX() + actual[0]) - (point[i].getY()))*pow(point[i].getX(), j));
这里我们改变每个 ø。
coefs[j] -= learningStep*sum[j];
我以为一切都按预期完成了。它适用于线性回归,但不适用于多项式回归。
我们可以很容易地看到 x^1 完美拟合,但其他函数仅拟合到中间点。在下一张图片上看起来更清楚:
我很想了解它,但我根本不知道哪里出了问题。数学上一切都是正确的(或者我可能漏掉了什么)
编辑
我改变了假设,它就像一个魅力!
你误解了多项式回归。假设应该看起来像
其中 theta
s 是您要学习的参数。请注意,有 m+1
个完全独立的变量。
即使您的 coefs
的大小确实是 m+1
,但从未使用过 coefs[2], ..., coefs[m]
。事实上,你总是使用线性模型:
actual[1]*point[i].getX() + actual[0]
计算
您应该将上述代码替换为计算 higher-order 多项式的代码。
我尝试为多项式回归实现梯度下降。我以为我什么都明白了,但好像哪里不对。
以上公式取自 coursera 机器学习讲义。 现在,代码呢:
for(int m=1;m<=degree;m++){
for(int i = 0;i<iterations;i++)
{
getCoefs(learningStep,m);
}
qDebug()<<"Parameters:";
for(int i=0;i<=degree;i++) {qDebug()<<coefs[i];}
switch(m){
case 1: equation = to_string(coefs[1]) + "*x+" + to_string(coefs[0]);
g1.set_style("lines").plot_equation(equation,"x^1"); break;
case 2: equation = to_string(coefs[2])+ "*x**2+" + to_string(coefs[1]) + "*x+" + to_string(coefs[0]);
g1.set_style("lines").plot_equation(equation,"x^2"); break;
case 3: equation = to_string(coefs[3])+ "*x**3+" +to_string(coefs[2])+ "*x**2+" + to_string(coefs[1]) + "*x+" + to_string(coefs[0]);
g1.set_style("lines").plot_equation(equation,"x^3"); break;
case 4: equation = to_string(coefs[4])+ "*x**4+" + to_string(coefs[3])+ "*x**3+" +to_string(coefs[2])+ "*x**2+" + to_string(coefs[1]) + "*x+" + to_string(coefs[0]);
g1.set_style("lines").plot_equation(equation,"x^4"); break;
case 5: equation = to_string(coefs[5])+ "*x**5+" + to_string(coefs[4])+ "*x**4+" + to_string(coefs[3])+ "*x**3+" +to_string(coefs[2])+ "*x**2+" + to_string(coefs[1]) + "*x+" + to_string(coefs[0]);
g1.set_style("lines").plot_equation(equation,"x^5"); break;
}
for(int i=0;i<=degree;i++) {coefs[i]=0;}
}
这是绘制方程的函数。 Coefs 是参数 {ø1,ø2...øn}
的向量degree是我要计算的最大度数的整数。
迭代步数,在我的例子中是2000
learningStep 不用解释了(0.001 [我也试了更大的LS 0.01 结果也是错误的])
void getCoefs(double learningStep, int degree){
QVector < double > sum;
for(int j=0;j<=degree;j++){
sum.push_back(0);
}
double numberOfPoints = point.length();
QVector < double > actual;
for(int j=0;j<=degree;j++){
actual.push_back(coefs[j]);
}
for(int i=0;i<point.length();i++){
for(int j=0;j<=degree;j++){
sum[j] += (1/numberOfPoints) *(((actual[1]*point[i].getX() + actual[0]) - (point[i].getY()))*pow(point[i].getX(), j));
}
}
for(int j=0;j<=degree;j++){
coefs[j] -= learningStep*sum[j];
}
}
这是我获取系数的代码。 point 是点向量(具有两个变量 x,y 的对象)。
actual 是包含假设函数系数的向量。
这里我们计算图一所示的总和:
sum[j] += (1/numberOfPoints) *(((actual1*point[i].getX() + actual[0]) - (point[i].getY()))*pow(point[i].getX(), j));
这里我们改变每个 ø。
coefs[j] -= learningStep*sum[j];
我以为一切都按预期完成了。它适用于线性回归,但不适用于多项式回归。
我很想了解它,但我根本不知道哪里出了问题。数学上一切都是正确的(或者我可能漏掉了什么)
编辑
我改变了假设,它就像一个魅力!
你误解了多项式回归。假设应该看起来像
其中 theta
s 是您要学习的参数。请注意,有 m+1
个完全独立的变量。
即使您的 coefs
的大小确实是 m+1
,但从未使用过 coefs[2], ..., coefs[m]
。事实上,你总是使用线性模型:
actual[1]*point[i].getX() + actual[0]
计算
您应该将上述代码替换为计算 higher-order 多项式的代码。