我尝试实现多项式回归的梯度下降法。我以为自己已经完全理解了,但似乎有些地方出了问题。
上图是来自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 是我想要计算的最高次数的整数。
iterations 步数,在我的例子中是2000
learningStep 不需要解释(0.001 [我也尝试了更大的学习步长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
是你试图学习的参数。请注意,这里有 m+1
个完全独立的变量。
尽管你的 coefs
确实是 m+1
大小的,但 coefs[2], ..., coefs[m]
从未被使用。实际上,你总是使用线性模型:
actual[1]*point[i].getX() + actual[0]
计算
你应该用计算高阶多项式的代码替换上述代码。