当前位置: 首页 > 工具软件 > levmar > 使用案例 >

levmar(LM算法)dlevmar_dif()函数实例使用分享

方焱
2023-12-01

前言

找遍了多个地方都没有找到关于这个函数完整的使用例程。所以在终于成功的使用后,决定写一下,希望可以帮到你。第一个例子帮你理解参数传递,跑不通,我会放第二个例子可以跑通的,希望可以帮助你理解

函数解释

以y=k1*x1+k2*x2+k3*x3为例子
int dlevmar_dif(
      void (*func)(double *p, double *hx, int m, int n, void *adata),//自己编写的函数,下面单独说。
      double *p, //p为待优化的系数,就是包含系数的数组{k1,k2,k3}
      double *x,//观测值也就是y的集合,p最优时k1*x1+k2*x2+k3*x3逼近y
      int m,//p的维数,也就是p数组大小
      int n,//x的维数,上面double *x数组大小
      int itmax,//最大迭代次数
      double *opts,//迭代过程中的一些阈值,包括最初计算阻尼系数时需要的系数、迭代结束需要的系数。如果不知道怎么设可以为NULL,代码有默认配置。
      double *info,//返回迭代结束的一些信息,如迭代次数、结束原因等,如果不知道怎么设可以为NULL,代码有默认配置
      double *work,//一般设置为null
      double *covar,//在代码中没有用到,可设置为null
      void *adata)//附加信息,当需要向函数void (*func)中传递其他自己需要的信息时使用,不用时可设置为null
 void (*func)(double *p, //p为待优化的系数,就是包含系数的数组{k1,k2,k3}
 					double *hx, //y值得数组,和上面dlevmar_dif里面的double *x是一个
 					int m,//p的维数,也就是p数组大小
  					int n,//y的维数,上面double *hx数组大小
   					void *adata)//当需要向函数void (*func)中传递其他自己需要的信息时使用,看了例子你就知道了

代码例程

void ros(double* p, double* x, int m, int n, void* data);
//函数为y=k1*X1+k2*X2;
int main()
{
    //   x[10]与data[20]的值要你自己赋予,我这里没写
    int m = 8;
    int n = 10;
    double p[4] = { 1,1, }; //初始的参数设定 k1-k2
    double x[20];						//Y的数据集
    double data[40];					//X的数据集,因为是x1,x2,Y有10个,所以X有2*10个
    
//注意这函数里面的data,我就是通过这把X的数据集传递进去的,这个函数的X和Y很混乱,别整混了
    int ret = dlevmar_dif(ros, p, x, m, n, 1000, NULL, NULL, NULL, NULL, (void*)data);
    cout << p[0] << "," << p[1] << endl;
}

void ros(double* p, double* x, int m, int n, void* data) {
    double* data1 = (double*)data;
    register int i;
    for (i = 0; i < n; i++) {
        x[i] = data1[i]*p[0] + data1[1*10+i] * p[1] ;    
    }
}

代码例程2

这个可以跑通
void expfunc(double* p, double* x, int m,int n, void* data)
{
	int i;
	for(i = 0; i < n; ++i)
	{
		x[i] = p[0] * exp(-p[1] * i) + p[2];
	}
}
int main()
{
	int n = 40, m = 3; // 40 measurements , 3 pa rame te r s
	double p[3], x[40], opts[LM_OPTS_SZ], info[LM_INFO_SZ];
	int i; int ret;
	for(i = 0; i < n; ++i)
	{
		//∗ g e n e r a t e measurement data 

		x[i] = (5.0 * exp(-0.1 * i) + 1.0) + 1;
	}
	// ∗ i n i t i a l pa rame te r s e s tim a t e : (1 . 0, 0 . 0, 0 . 0) ∗ /
	p[0] = 1.0; p[1] = 0.0; p[2] = 0.0;
	// ∗ o p timi z a ti o n c o n t r o l pa rame te r s ∗ /
	opts[0] = LM_INIT_MU; opts[1] =1E-15;
	opts[2] = 1E-15; opts[3] = 1E-20;
	opts[4] = LM_DIFF_DELTA; // f o r f i n i t e d i f f e r e n c e Jacobian
	// ∗ in vo ke the o p timi z a ti o n f u n c ti o n ∗ /
	ret = dlevmar_dif(expfunc, p, x, m, n, 1000, opts, info,
			NULL, NULL, NULL); // wi thou t Jacobian
	cout << p[0] << "," << p[1] << "," << p[2] << endl;
}
 类似资料: