I know, that's why I can't figure out what's going wrong. Attached is my
modified sinfit.c, adapted from expfit.c and merged with nlfit.c
The expfit example works, the sinfit doesn't. :-(
I'm sure I'm missing something important, but from my limited
understanding of GSL, I can't see what.
Thanks.
Gordan
On Thu, 19 Jul 2007, John Gehman wrote:
>
> Hello Gordan,
>
> That block of code is verbatim from the example, and it has worked
> for me, so I reckon there's something wrong with either the component
> functions/variables of your gsl_multifit_function_fdf (i.e. f, df,
> fdf, n, p, params), or your gsl_multifit_fdfsolver_...
>
> Cheers,
> john
>
> ---------------------------------------------------------
>
> Dr John Gehman ([EMAIL PROTECTED])
> Research Fellow; Separovic Lab
> School of Chemistry
> University of Melbourne (Australia)
>
>
> On 18/07/2007, at 8:11 PM, Gordan Bobic wrote:
>
> > Thanks for that, really appreciate your help.
> >
> > The problem I seem to have now is that the main fitting iteration loop
> > seems to just bail out on me immediately:
> >
> > 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);
> >
> > "if (status)" always evaluates to true (status == -2, I checked)
> > but the
> > error string is actually "the iteration has not converged yet". If I
> > change this to:
> >
> > if (status != -2), then it just keeps going until the maximum
> > number of
> > iterations are up. So, status == GSL_CONTINUE, but the worrying
> > thing is
> > that at each pass the numbers output by print_state() are the same.
> > It is
> > as if there is no gradient descent happening.
> >
> > Am I missing something obvious? It doesn't seem to make any difference
> > what I put in x_init[], be it the output of the guesstimator, 1s 0s or
> > some other random number. It never seems to descend.
> >
> > I removed all the gsl_rng* stuff because I have a fixed data block
> > I use
> > for testing so I can make meaningful comparisons between different
> > algorithms and libraries (i.e. content of y[] is pre-generated). This
> > couldn't be the cause of the problem, could it?
> >
> > My Jacobian setting is:
> >
> > for (i = 0; i < n; i++)
> > {
> > // Yi = a * sin(X/b + c) + d
> >
> > gsl_matrix_set (J, i, 0, sinf(b / i + c) / sigma[i]);
> > gsl_matrix_set (J, i, 1, a * cosf(b / i + c) / sigma[i] / i);
> > gsl_matrix_set (J, i, 2, a * cosf(b / i + c) / sigma[i]);
> > gsl_matrix_set (J, i, 3, 1 / sigma[i]);
> > }
> >
> > But even if this is wrong, surely it should still descend _somewhere_,
> > given random starting points, should it not?
> >
> > Gordan
> >
> >
> > On Wed, 18 Jul 2007, John Gehman wrote:
> >
> >> G'day Gordan,
> >>
> >> The Jacobian matrix J is the differential of your objective equation
> >> with respect to each parameter (corresponding to the second index)
> >> at each data point (corresponding to the first index).
> >>
> >> The relevant equation is [a * sin(b / t + c) + d - yi ] / sigma[i],
> >> i.e. you're trying to minimize the difference between the model and
> >> the data (yi), where some points may be more reliable than others
> >> (given sigma[i]), by optimizing the amplitude, period, phase, and
> >> offset of your sine wave. The Jacobian provides the analytic
> >> equations to inform the system of the sensitivity of the residuals in
> >> the evolving fit to changes in each of the parameters.
> >>
> >> Taking the partial derivative of your equation with respect to each
> >> of the floating parameters, and setting them appropriately into the
> >> matrix J, assuming your vector of floating parameters elsewhere is
> >> ordered (a,b,c,d), and retaining your s = sigma[i], I get:
> >>
> >>
> >> gsl_matrix_set (J, i, 0, sin(b / t + c) / s); # derivative
> >> with respect to a
> >> gsl_matrix_set (J, i, 1, cos(b / t + c) * a/(t*s) ); # derivative
> >> with respect to b
> >> gsl_matrix_set (J, i, 2, cos(b / t + c) * a/s); # derivative
> >> with respect to c
> >> gsl_matrix_set (J, i, 3, 1/s); #
> >> derivative with respect to d
> >>
> >> The analytic derivatives are usually my problem, however, so please
> >> confirm them!
#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>
#define N 40
void print_state (size_t iter, gsl_multifit_fdfsolver * s);
struct data {
size_t n;
float * y;
float * sigma;
};
int sinb_f (const gsl_vector *x, void *data, gsl_vector *f)
{
size_t n = ((struct data *)data)->n;
float *y = ((struct data *)data)->y;
float *sigma = ((struct data *) data)->sigma;
float a = gsl_vector_get (x, 0);
float b = gsl_vector_get (x, 1);
float c = gsl_vector_get (x, 2);
float d = gsl_vector_get (x, 3);
size_t i;
for (i = 0; i < n; i++)
{
/* Model Yi = a * sin(b/i + c) + d */
float t = i;
float Yi = a * sin (b/t + c) + d;
gsl_vector_set (f, i, (Yi - y[i])/sigma[i]);
}
return GSL_SUCCESS;
}
int sinb_df (const gsl_vector * x, void *data, gsl_matrix * J)
{
size_t n = ((struct data *)data)->n;
float *sigma = ((struct data *) data)->sigma;
float a = gsl_vector_get (x, 0);
float b = gsl_vector_get (x, 1);
float c = gsl_vector_get (x, 2);
float d = gsl_vector_get (x, 3);
size_t i;
for (i = 0; i < n; i++)
{
/* Jacobian matrix J(i,j) = dfi / dxj, */
/* where fi = (Yi - yi)/sigma[i], */
/* Yi = a * sin(b/i + c) + d */
/* and the xj are the parameters (A,lambda,b) */
float t = i;
gsl_matrix_set (J, i, 0, sinf(b/t + c) / sigma[i]);
gsl_matrix_set (J, i, 1, a * cosf(b/t + c) / sigma[i] / t);
gsl_matrix_set (J, i, 2, a * cosf(b/t + c) / sigma[i]);
gsl_matrix_set (J, i, 3, 1 / sigma[i]);
}
return GSL_SUCCESS;
}
int sinb_fdf (const gsl_vector *x, void *data, gsl_vector *f, gsl_matrix *J)
{
sinb_f (x, data, f);
sinb_df (x, data, J);
return GSL_SUCCESS;
}
int main (void)
{
const gsl_multifit_fdfsolver_type *T;
gsl_multifit_fdfsolver *s;
int status;
unsigned int i, iter = 0;
const size_t n = N;
const size_t p = 4;
gsl_matrix *covar = gsl_matrix_alloc (p, p);
float y[N], sigma[N];
struct data d = { n, y, sigma};
gsl_multifit_function_fdf f;
double x_init[4] = {1.0, 1.0, 1.0, 1.0};
gsl_vector_view x = gsl_vector_view_array (x_init, p);
const gsl_rng_type * type;
gsl_rng * r;
gsl_rng_env_setup();
type = gsl_rng_default;
r = gsl_rng_alloc (type);
f.f = &sinb_f;
f.df = &sinb_df;
f.fdf = &sinb_fdf;
f.n = n;
f.p = p;
f.params = &d;
/* This is the data to be fitted */
for (i = 0; i < n; i++)
{
float t = i;
y[i] = 5 * sin (4/t + 3) + 2 + gsl_ran_gaussian (r, 0.3);
sigma[i] = 0.1;
printf ("data: %u %g %g\n", i, y[i], sigma[i]);
};
T = gsl_multifit_fdfsolver_lmsder;
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))
{
float chi = gsl_blas_dnrm2(s->f);
float dof = n - p;
float 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 ("b = %.5f +/- %.5f\n", FIT(1), c*ERR(1));
printf ("c = %.5f +/- %.5f\n", FIT(2), c*ERR(2));
printf ("d = %.5f +/- %.5f\n", FIT(3), c*ERR(3));
}
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: %3u x = % 15.8f % 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_vector_get (s->x, 3),
gsl_blas_dnrm2 (s->f));
}
_______________________________________________
Help-gsl mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/help-gsl