问题描述
- C语言数学函数拟合(最小二乘法)
-
参数说明:double Step_A, // A参数步长
double Step_B, // B参数步长
double Step_C, // C参数步长
double Range_A_Down, // A参数取值下限
double Range_B_Down, // B参数取值下限
double Range_C_Down, // C参数取值下限
double Range_A_Up, // A参数取值上限
double Range_B_Up, // B参数取值上限
double Range_C_Up, // C参数取值上限
double Sigma_Down // Sigma容忍值下限
最小二乘法函数:int Sigma_Converge_Func( double Step_A,
double Step_B,
double Step_C,
double Range_A_Down,
double Range_B_Down,
double Range_C_Down,
double Range_A_Up,
double Range_B_Up,
double Range_C_Up,
double Sigma_Down)
{
for(A=Range_A_Down;A < Range_A_Up;A += Step_A) // 第一层循环,扫描A参数
{
for(B=Range_B_Down;B < Range_B_Up;B += Step_B) // 第二层循环,扫描B参数
{
for(C=Range_C_Down;C < Range_C_Up;C += Step_C) // 第三层循环,扫描C参数
{
Sigma = 0;
for(int i=0;i<PtsNum;i++)
{
y0[i] = A*x[i]*x[i]+B*x[i]+C;
y1[i] = (y[i]-y0[i])*(y[i]-y0[i]);
Sigma += y1[i];
}
if(Sigma < Sigma_Buff)
{
Sigma_Buff = Sigma;
if(Sigma <= Sigma_Down)
{
return 1;
}
}
else
{
}} } } return 0;
}
下面是三级优化:
// 第一轮优化,大步长,大范围,进行快速扫描,缩小范围
Sigma_Converge_Func( Step_A0,
Step_B0,
Step_C0,
Range_A_Down0,
Range_B_Down0,
Range_C_Down0,
Range_A_Up0,
Range_B_Up0,
Range_C_Up0,
Sigma_Down0
);
// 第二轮优化,范围适当缩小,-100~+100,步长缩小为1,快速扫描,进一步缩小范围
Range_A_Down0 = A - 100;
Range_A_Up0 = A + 100;
Range_B_Down0 = B - 100;
Range_B_Up0 = B + 100;
Range_C_Down0 = C - 100;
Range_C_Up0 = C + 100;Step_A0 = 1;
Step_B0 = 1;
Step_C0 = 1;
Sigma_Down0 = 1000;
Sigma_Converge_Func( Step_A0,
Step_B0,
Step_C0,
Range_A_Down0,
Range_B_Down0,
Range_C_Down0,
Range_A_Up0,
Range_B_Up0,
Range_C_Up0,
Sigma_Down0
);
// 第三轮优化,范围十分小,步长为0.1,逐步扫描,直至Sigma趋近于0,暂定为小于1e-9即可
Range_A_Down0 = A - 1;
Range_A_Up0 = A + 1;
Range_B_Down0 = B - 10;
Range_B_Up0 = B + 10;
Range_C_Down0 = C - 10;
Range_C_Up0 = C + 10;Step_A0 = 0.1;
Step_B0 = 0.1;
Step_C0 = 0.1;
Sigma_Down0 = 1e-9;
if (true == Sigma_Converge_Func( Step_A0, //若Sigma_Converge_Func()的返回值为1,即Sigma<Sigma_Down0,此时的参数最适合
Step_B0,
Step_C0,
Range_A_Down0,
Range_B_Down0,
Range_C_Down0,
Range_A_Up0,
Range_B_Up0,
Range_C_Up0,
Sigma_Down0
))思路和问题:(题目:通过10个已知坐标和函数模型(带3个参数)拟合出原函数)
对于函数原型y=A*x^2+B*x+C来说,假设A,B,C三个参数是从-1000到1000,本来我打算设置0.1的步长,从-1000扫描到1000,可是这样的话三层循环都是从-1000到1000以0.1的步长扫描参数,太慢了,然后我就想设定一个Sigma的容忍值,第一次扫描到Sigma<(一个值)就退出二乘法函数,然后重新在得到的大概的A,B,C参数值附近再进行下一步扫描,然后继续缩小Sigma的值,再重复一次,直至Sigma逼近0,这也就是说A,B,C参数就是我想要的值。
但是这个方法有问题,当我换一个函数模型时,程序就不行了,好比说,A,B,C正确值分别是A=5,B=20,C=-35,可是我在第一次扫描时得到Sigma<(一个值)时的A=-20,B=40,C=-30,那么程序会自动在这个附近进行下一次扫描,比如说在A=-30~-10之间进行扫描,B,C以此类推,但是这远远偏离了正确值,需要重新手动调整扫描范围才能让结果趋向于正确值。
请问该怎么办,我想不出好的解决办法。谢谢大家!