一、牛顿迭代法的原理(公式编辑太麻烦,直接引用了截图):
二、牛顿迭代法具体案例分析
1.xoy平面内有一群带噪音的散乱点,从分布规则上看大致接近于f(x)的函数分布,此时就可以使用牛顿迭代法将目标函数拟合出来。
2.比如以下方式,拟合y=ax+b的过程
3.已知条件:n个点的坐标(xi,yi)
4.构建误差项:loss =1/n((a*xi+b-yi)^2+…),i从0到n-1;
5.牛顿迭代公式:xi+1=xi - t * f(xi)’,其中t为步进
6.因此对于未知量a和b的迭代公式分别为:*
其中
三、牛顿迭代法的代码实现:
1、生成随机点,在直线附近增加一个噪音
// y=ax+b, a=1.5,b=0.6;
vector<float> getRand(vector<float>&x)
{
vector<float>ylist;
for (auto&i : x)
{
float y = 1.5*i + 0.6 + rand() % 1000/10000.0;
ylist.push_back(y);
}
return ylist;
}
2、计算误差项
float getLoss(vector<float>&x, vector<float>&y, float a, float b)
{
int n = x.size();
float loss = 0;
for (int i = 0; i < n; i++)
{
float t = a*x[i] + b - y[i];
loss += t*t;
}
loss /= n;
return loss;
}
3、迭代1000次
int main()
{
vector<float>x_val;
for (float x = 0.5; x < 10.0f; x += 0.05f)
{
x_val.push_back(x);
}
cout << "真值a:1.5 ,b:0.6" << endl;
// y=1.5x+0.6
vector<float>y_val = getRand(x_val);
int n = x_val.size();
float a = 0, b = 0;
float step = 0.005;
cout << "a:" << a << "," << "b:" << b << ":loss=" << getLoss(x_val, y_val, a, b) << endl;
for (int i = 0; i < 1000; i++)
{
float del_a = 0;
float del_b = 0;
for (int j = 0; j < n; j++)
{
del_a += 2 * (a*x_val[j] + b - y_val[j])*x_val[j];
del_b += 2 * (a*x_val[j] + b - y_val[j]);
}
del_a /= n;
del_b /= n;
a = a - step*del_a;
b = b - step*del_b;
}
cout <<"a:" <<a << "," <<"b:"<< b << ":loss=" << getLoss(x_val, y_val, a, b) << endl;
getchar();
return 0;
}
4、运行结果: