使用GSL的非线性拟合

马兹

因此,我正在尝试修改此处找到的某些代码以适合其他功能,但是经过略微修改的版本无法收敛,我也不明白为什么。

我试图找到最小二乘拟合的函数是“ A + lambda log(t)+ b log(t)^ 2。这是代码

main.cpp

#include <stdlib.h>
#include <stdio.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_multifit_nlin.h>

#include "expfit.c"

#define N 40 // All "N"s are 40

void print_state (size_t iter, gsl_multifit_fdfsolver * s);//The prototype of some function

int main (void){

    const gsl_multifit_fdfsolver_type *T; //pointer to a newly allocated instance of a solver of type T
    gsl_multifit_fdfsolver *s;
    int status;
    unsigned int i, iter = 0;
    const size_t n = N; //N number of observations
    const size_t p = 3;//3 parameters

    gsl_matrix *covar = gsl_matrix_alloc (p, p); // creates a pxp gsl_matrix
    double y[N], sigma[N]; //declares vector variables that will hold the noise data. They are "N" long
    struct data d = { n, y, sigma}; //Populates struct d with variables n, y and sigma. Struct data is defined in expfit.c
    gsl_multifit_function_fdf f;
    double x_init[3] = { 0, -.1, -.1 }; //initial x values !These are initial guesses to the solution!
    gsl_vector_view x = gsl_vector_view_array (x_init, p);//view arrays allow one to litterally view elements of a certain array without modifying or created a copy of the original array. Essentially a pointer to the original data.
    const gsl_rng_type * type; // pointer to a new random number generator type. RNG type will be assigned later
    gsl_rng * r; //Pointer to a new RNG

    gsl_rng_env_setup();

    type = gsl_rng_default; //Assigns random number generator type
    r = gsl_rng_alloc (type); // Allocates memory for new RNG of type "type"

    f.f = &logb_f;
    f.df = &logb_df;
    f.fdf = &logb_fdf;
    f.n = n;
    f.p = p;
    f.params = &d;



    for (i = 0; i < n; i++){// This is where the data is being generated

        double t = i; // t is being redclared at each iteration for some reason wtf
        if(t==0){//since log(0) is undefined, I said they equal 0 at t=0
            y[i] = 2.0 -.5 * 0 - 0 + gsl_ran_gaussian (r, 0.1);
        }else{
            y[i] = 2.0 -.5 * log (t) - pow(log(t),2) + gsl_ran_gaussian (r, 0.1); //This is the noised up data
        }
        sigma[i] = .1; //not sure what this sigma does
        printf ("data: %u %g %g\n", i, y[i], sigma[i]);//Printing out the data at each iteration
    };

    T = gsl_multifit_fdfsolver_lmsder; // Not sure what this is doing
    s = gsl_multifit_fdfsolver_alloc (T, n, p);
    gsl_multifit_fdfsolver_set (s, &f, &x.vector);

    print_state (iter, s);

    do{
        iter++;
        status = gsl_multifit_fdfsolver_iterate (s);

        printf ("status = %s\n", gsl_strerror (status));

        print_state (iter, s);

        if (status)
            break;

        status = gsl_multifit_test_delta (s->dx, s->x, 1e-4, 1e-4);

    }while (status == GSL_CONTINUE && iter < 500);

    gsl_multifit_covar (s->J, 0.0, covar);

#define FIT(i) gsl_vector_get(s->x, i)
#define ERR(i) sqrt(gsl_matrix_get(covar,i,i))

    {
        double chi = gsl_blas_dnrm2(s->f);
        double dof = n - p;
        double c = GSL_MAX_DBL(1, chi / sqrt(dof));

        printf("chisq/dof = %g\n",  pow(chi, 2.0) / dof);

        printf ("A      = %.5f +/- %.5f\n", FIT(0), c*ERR(0));
        printf ("lambda = %.5f +/- %.5f\n", FIT(1), c*ERR(1));
        printf ("b      = %.5f +/- %.5f\n", FIT(2), c*ERR(2));
    }

    printf ("status = %s\n", gsl_strerror (status));

    gsl_multifit_fdfsolver_free (s);
    gsl_matrix_free (covar);
    gsl_rng_free (r);
    return 0;
}

void print_state (size_t iter, gsl_multifit_fdfsolver * s){
    printf ("iter: %3zu x = % 15.8f % 15.8f % 15.8f "
            "|f(x)| = %g\n",
            iter,
            gsl_vector_get (s->x, 0),
            gsl_vector_get (s->x, 1),
            gsl_vector_get (s->x, 2),
            gsl_blas_dnrm2 (s->f));
}

expfit.c

//
//  expfit.c
//  test
//
//  Created by [] on 4/11/15.
//  Copyright (c) 2015 []. All rights reserved.
//
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_multifit_nlin.h>

#include "expfit.h"

/* expfit.c -- model functions for exponential + background */

struct data {
    size_t n;
    double * y;
    double * sigma;
};

int logb_f (const gsl_vector * x, void *data, gsl_vector * f){
    size_t n = ((struct data *)data)->n;
    double *y = ((struct data *)data)->y;
    double *sigma = ((struct data *) data)->sigma;

    double A = gsl_vector_get (x, 0);
    double lambda = gsl_vector_get (x, 1);
    double b = gsl_vector_get (x, 2);
    double Yi;//will hold the value of the function to be stored into the vector set
    double t;//time variable.
    size_t i;//iterative variable

    for (i = 0; i < n; i++){
        /* Model Yi = A + lambda*log(i) + b*lambda*log(i)^2 */
        t = i;

        if(t==0){ //need if statement to bypass log(0) when t==0 since the value of log is undefined there
            Yi = A + lambda * log(t) + b * pow(log(t),2);//function for t==0
        }else{
            Yi = A + lambda * log(t) + b * pow(log(t),2); // This is the function we used
        }
        gsl_vector_set (f, i, (Yi - y[i])/sigma[i]);
    }

    return GSL_SUCCESS;
}

int logb_df (const gsl_vector * x, void *data, gsl_matrix * J){
    size_t n = ((struct data *)data)->n;
    double *sigma = ((struct data *) data)->sigma;

    //double A = gsl_vector_get (x, 0);
    //double lambda = gsl_vector_get (x, 1);
    //double b = gsl_vector_get(x,2);

    size_t i;

    for (i = 0; i < n; i++){
        /* Jacobian matrix J(i,j) = dfi / dxj, */
        /* where fi = (Yi - yi)/sigma[i],      */
        /*       Yi = A + lambda*log(i) + b*log(i)^2  */
        /* and the xj are the parameters (A,lambda,b) */
        double t = i;
        double s = sigma[i];

        gsl_matrix_set (J, i, 0, 1/s);
        gsl_matrix_set (J, i, 1, log(t)/s);
        gsl_matrix_set (J, i, 2, pow(log(t),2)/s);
    }
    return GSL_SUCCESS;
}

int logb_fdf (const gsl_vector * x, void *data, gsl_vector * f, gsl_matrix * J){
    logb_f (x, data, f);
    logb_df (x, data, J);

    return GSL_SUCCESS;
}

这是头文件,以防万一您想要它

//
//  expfit.h
//  test
//
//  Created by [] on 4/11/15.
//  Copyright (c) 2015 []. All rights reserved.
//

#ifndef __test__expfit__
#define __test__expfit__

#include <stdio.h>

#endif /* defined(__test__expfit__) */
斯蒂芬·W

在计算拟合函数时,请考虑特殊情况t = 0以避免log(0),但函数值没有不同:

if(t==0){ 
            Yi = A + lambda * log(t) + b * pow(log(t),2);//function for t==0
        }else{
            Yi = A + lambda * log(t) + b * pow(log(t),2); // This is the function we used
        }

此外,您在计算导数时不会考虑这种情况。因此,我将功能和派生更改如下:

int logb_f (const gsl_vector * x, void *data, gsl_vector * f){
    size_t n = ((struct data *)data)->n;
    double *y = ((struct data *)data)->y;
    double *sigma = ((struct data *) data)->sigma;

    double A = gsl_vector_get (x, 0);
    double lambda = gsl_vector_get (x, 1);
    double b = gsl_vector_get (x, 2);
    double Yi;//will hold the value of the function to be stored into the vector set
    double t;//time variable.
    size_t i;//iterative variable


    for (i = 0; i < n; i++){
        /* Model Yi = A + lambda*log(i) + b*lambda*log(i)^2 */
        t = i;
    if(t==0){ //need if statement to bypass log(0) when t==0 since the value of log is undefined there
        Yi = A ;
        }else{
            Yi = A + lambda * log(t) + b * pow(log(t),2); // This is the function we used
        }

    //Yi = A + lambda * log(t) + b * pow(log(t),2); // This is the function we used
        gsl_vector_set (f, i, (Yi - y[i])/sigma[i]);
    }
    return GSL_SUCCESS;
}

int logb_df (const gsl_vector * x, void *data, gsl_matrix * J){
    size_t n = ((struct data *)data)->n;
    double *sigma = ((struct data *) data)->sigma;

    //double A = gsl_vector_get (x, 0);
    //double lambda = gsl_vector_get (x, 1);
    //double b = gsl_vector_get(x,2);

    size_t i;

    for (i = 0; i < n; i++){
        /* Jacobian matrix J(i,j) = dfi / dxj, */
        /* where fi = (Yi - yi)/sigma[i],      */
        /*       Yi = A + lambda*log(i) + b*log(i)^2  */
        /* and the xj are the parameters (A,lambda,b) */
      // d 
        double t = i;
        double s = sigma[i];
        if(i == 0) 
          {
            gsl_matrix_set (J, i, 0, 0);
            gsl_matrix_set (J, i, 1, 0);
            gsl_matrix_set (J, i, 2, 0);
          }
        else 
          {
            gsl_matrix_set (J, i, 0, 1/s);
            gsl_matrix_set (J, i, 1, log(t)/s);
            gsl_matrix_set (J, i, 2, pow(log(t),2)/s);
          }
        //Yi = A + lambda * log(t) + b * pow(log(t),2); // This is the function we used
    }
    return GSL_SUCCESS;
}

在这种情况下,迭代收敛:

iter:   0 x =      0.00000000     -0.10000000     -0.10000000 |f(x)| = 470.77
status = success
iter:   1 x =      2.08763815     -0.60282892     -0.97819822 |f(x)| = 5.5047
status = success
iter:   2 x =      2.08763815     -0.60282892     -0.97819822 |f(x)| = 5.5047
chisq/dof = 0.818964
A      = 2.08764 +/- 0.08245
lambda = -0.60283 +/- 0.07702
b      = -0.97820 +/- 0.01722
status = success

然而,我建议以验证T的拟合函数的微分- > 0。如果有疑问,也可以通过仅考虑对于t> 0的值限制在上述功能的拟合范围:for (i = 1; i < n; i++) ...代替for (i = 0; i < n; i++) ...

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

R:拟合曲线到点:使用什么线性/非线性模型?

来自分类Dev

在GSL中,是任何用于非线性曲线拟合的函数

来自分类Dev

Octave 中的非线性拟合

来自分类Dev

在R中拟合广义非线性模型

来自分类Dev

逐段拟合非线性数据

来自分类Dev

R中的非线性曲线拟合

来自分类Dev

非线性拟合正弦曲线失败

来自分类Dev

使用pyMCMC / pyMC将非线性函数拟合到数据/观测

来自分类Dev

在R中拟合非线性Langmuir等温线

来自分类Dev

错误非线性回归python曲线拟合

来自分类Dev

Matlab中的n维非线性曲线拟合

来自分类Dev

将两个非线性模型拟合到数据

来自分类Dev

确定R中非线性回归的拟合方程

来自分类Dev

如何在 R 中拟合非线性线?

来自分类Dev

如何从非线性回归拟合功率曲线?

来自分类Dev

用线性/非线性回归拟合两条曲线

来自分类Dev

如何使用matplotlib绘制非线性函数?

来自分类Dev

使用优化的R中的非线性优化

来自分类Dev

如何使用matplotlib绘制非线性模型?

来自分类Dev

在VHDL中使用非线性查找操作

来自分类Dev

R中的非线性最小二乘曲线拟合

来自分类Dev

以变量为积分极限的非线性最小二乘拟合

来自分类Dev

为什么我在Mathematica中拟合的非线性模型不能提供小的数字?

来自分类Dev

具有lmfit的两个独立变量的非线性最小二乘拟合

来自分类Dev

如何将对数非线性拟合添加到ggplot?

来自分类Dev

Python中的非线性最小二乘拟合(二维)

来自分类Dev

将数据拟合到后处理非线性模型时,curve_fit 的算法是什么?

来自分类Dev

运行时警告:具有多个参数和自变量的无效值非线性拟合

来自分类Dev

在Scikit-Learn中使用非线性SVM时出错

Related 相关文章

热门标签

归档