我尝试根据数字配方使用Levenberg-marquardt的方法拟合模型。 问题是:它没有收敛,或者它没有收敛,它不精确......或者至少协变矩阵很奇怪。
int i=0;
for (i = 0; i < 3e4; i++) {
mrqmin(x, y, sig, NPCalib, a, ia, 3, covar, alpha, &chisk, afunc,
&alamda);
if (chisk < 1e-8)
sumchisk++;
if (sumchisk > 5)
break;
if (alamda > 1e8)
alamda = 1e8;
}
(x,y)是3分(双),与y=a(x-x0)^2
形式一致
使用像这样的sumchisk是使用此功能的数字配方的建议
alamda在这里被限制在顶部,否则可能会出现溢出。
其他定义和数据点:
double a[4] = {0.0, 0.0001, 100.0, -1};
int ia[4] = {0.0, 1, 1, 0};
double *x = {0.0, 799.157549545577, 799.92196995454, 800.683769692575};
double *y = {0.0, 524.26491, 525.26768, 526.26586};
double *sig = {0.0, 0.1*y[1], 0.1*y[2], 0.1*y[3]};
double **covar = new double*[4];
covar[1] = new double[4];
covar[2] = new double[4];
covar[3] = new double[4];
double **alpha = new double*[4];
alpha[1] = new double[4];
alpha[2] = new double[4];
alpha[3] = new double[4];
double chisk = 0;
double alamda = -1;
void afunc(int i, double x[], double a[], double *y, double dyda[], int ma)
{
*y = a[1] * pow(x[i] + a[2], 2) / pow(1 + a[3] * CT[i - 1], 2);
dyda[1] = pow(x[i] + a[2], 2) / pow(1 + a[3] * CT[i - 1], 2);
dyda[2] = (2 * a[1] * (x[i] + a[2])) / pow
(1 + a[3] * CalibTurn[i - 1], 2);
dyda[3] = (-2 * a[1] * CT[i - 1] * pow(x[i] + a[2], 2)) / pow
(1 + a[3] * CT[i - 1], 3);
}
我将nr-sourcecode更改为使用double而不是float。没有使用第一个数组元素,因为它来自fortran-code,我不想改变这么小的细节。
该模型还包含一个3.参数,该参数未在此拟合中使用,因此仍为[3] = - 1,因为ia [3] = 0。 ia [] = 1表示参数即将拟合......
但是,现在我遇到的问题是,有时这种情况并不会收敛。它以alamda=1e8
和i=3e4
结束。特别是当我设置chisk
的阈值时
这组参数看起来很好,但是...这样的凿子就是大约1e-6并且参数似乎很好,但是看一下协变矩阵的对角线(应该给出每个参数的平方标准差),对于参数0.0001,有一些像800000这样的红色。
使用此算法时有谁知道我做错了什么? 我开始时需要写入covar / alpha的具体内容吗?信号可以像这样设置吗?