IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 7130


Ignore:
Timestamp:
May 17, 2006, 2:24:13 PM (20 years ago)
Author:
Paul Price
Message:

Better test for psMinimize --- fitting a Gaussian, and comparing parameters.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/test/math/tst_psMinimizeLMM.c

    r7085 r7130  
    1212#include <math.h>
    1313#define NUM_ITERATIONS 100
    14 #define ERR_TOL 0.1
    15 #define NUM_DATA_POINTS 20
    16 #define NUM_PARAMS 5
     14#define ERR_TOL 1e-6
     15#define NUM_DATA_POINTS 100
     16#define NUM_PARAMS 3
    1717float expectedParm[NUM_PARAMS];
     18
     19
     20float function(const psVector *params,      // Paramters
     21               const psVector *x            // Ordinate
     22              )
     23{
     24    return params->data.F32[0] *
     25           expf(- params->data.F32[1] * (PS_SQR(x->data.F32[0]) + PS_SQR(x->data.F32[1]))) +
     26           params->data.F32[2];
     27}
     28
     29void derivatives(psVector *deriv,       // Derivatives
     30                 const psVector *params,      // Paramters
     31                 const psVector *x            // Ordinate
     32                )
     33{
     34    deriv->data.F32[0] = expf(- params->data.F32[1] * (PS_SQR(x->data.F32[0]) + PS_SQR(x->data.F32[1])));
     35    deriv->data.F32[1] = - params->data.F32[0] * (PS_SQR(x->data.F32[0]) + PS_SQR(x->data.F32[1])) *
     36                         expf(- params->data.F32[1] * (PS_SQR(x->data.F32[0]) + PS_SQR(x->data.F32[1])));
     37    deriv->data.F32[2] = 1.0;
     38}
     39
     40
    1841
    1942/*****************************************************************************
    2043myFunc():
    21     sum = param[0] + x[0] * x[1] +
     44    sum = param[0] * x[0] * x[1] +
    2245          param[1] * x[0] +
    2346          param[2] * x[0]^2 +
     
    2649 
    2750 *****************************************************************************/
    28 psF32 myFunc(psVector *deriv,
    29              psVector *params,
    30              psVector *x)
     51psF32 fitFunc(psVector *deriv,
     52              psVector *params,
     53              psVector *x)
    3154{
    3255    if ((deriv == NULL) || (params == NULL) || (x == NULL)) {
     
    3457    }
    3558
    36     psF32 sum = (params->data.F32[0] * x->data.F32[0] * x->data.F32[1]) +
    37                 (params->data.F32[1] * x->data.F32[0]) +
    38                 (params->data.F32[2] * PS_SQR(x->data.F32[0])) +
    39                 (params->data.F32[3] * x->data.F32[1]) +
    40                 (params->data.F32[4] * PS_SQR(x->data.F32[1]));
    41 
    42     deriv->data.F32[0] = x->data.F32[0] * x->data.F32[1];
    43     deriv->data.F32[1] = x->data.F32[0];
    44     deriv->data.F32[2] = PS_SQR(x->data.F32[0]);
    45     deriv->data.F32[3] = x->data.F32[1];
    46     deriv->data.F32[4] = PS_SQR(x->data.F32[1]);
    47 
    48     return(sum);
     59    derivatives(deriv, params, x);
     60    return function(params, x);
    4961}
    5062
     
    5466    psBool testStatus = true;
    5567
     68    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Random number generator; using known seed
    5669    psMinimization *min = psMinimizationAlloc(NUM_ITERATIONS, ERR_TOL);
    57     psImage *myCovar = psImageAlloc(NUM_PARAMS, NUM_PARAMS, PS_TYPE_F32);
    58     psVector *myParams = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
    59     psVector *myDerivs = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
    60     psArray *myCoords = psArrayAlloc(NUM_DATA_POINTS);
    61     myCoords->n = NUM_DATA_POINTS;
    62     psVector *y = psVectorAlloc(NUM_DATA_POINTS, PS_TYPE_F32);
    63     myParams->n = NUM_PARAMS;
    64     myDerivs->n = NUM_PARAMS;
    65     y->n = NUM_DATA_POINTS;
    66 
    67     for (psS32 i=0;i<NUM_DATA_POINTS;i++) {
    68         myCoords->data[i] = (psPtr *) psVectorAlloc(2, PS_TYPE_F32);
    69         ((psVector *) (myCoords->data[i]))->data.F32[0] = (float) (i+10);
    70         ((psVector *) (myCoords->data[i]))->data.F32[1] = (float) (i+3);
    71         ((psVector *) (myCoords->data[i]))->n = 2;
    72         psTrace(__func__, 5, "x[%d] is vector (%f, %f)\n", i, ((psVector *) (myCoords->data[i]))->data.F32[0],
    73                 ((psVector *) (myCoords->data[i]))->data.F32[1]);
    74         y->data.F32[i] = (float) i;
    75     }
    76     for (psS32 i=0;i<NUM_PARAMS;i++) {
    77         expectedParm[i] = 2.42 + (float) (2 * i);
    78         myParams->data.F32[i] = (float) (2 * i);
    79     }
    80 
    81     psBool rc = psMinimizeLMChi2(min, NULL, myParams, NULL, myCoords, y, NULL,
    82                                  (psMinimizeLMChi2Func) myFunc);
    83     if (rc == false) {
     70    psArray *ordinates = psArrayAlloc(NUM_DATA_POINTS);
     71    psVector *coordinates = psVectorAlloc(NUM_DATA_POINTS, PS_TYPE_F32);
     72    psVector *errors = psVectorAlloc(NUM_DATA_POINTS, PS_TYPE_F32);
     73    ordinates->n = NUM_DATA_POINTS;
     74    coordinates->n = NUM_DATA_POINTS;
     75    errors->n = NUM_DATA_POINTS;
     76    psVector *params = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
     77    params->n = NUM_PARAMS;
     78    psVector *trueParams = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
     79    trueParams->n = NUM_PARAMS;
     80
     81    trueParams->data.F32[0] = 100.0;    // Normalisation
     82    trueParams->data.F32[1] = 0.1;      // Shape
     83    trueParams->data.F32[2] = 10.0;     // Background
     84
     85    // Set parameters
     86    for (long i = 0; i < NUM_PARAMS; i++) {
     87        // So we're not starting right on the true value:
     88        params->data.F32[i] = trueParams->data.F32[i] * (1.0 - psRandomGaussian(rng) / 10.0);
     89    }
     90
     91    for (long i = 0; i < NUM_DATA_POINTS; i++) {
     92        psVector *x = psVectorAlloc(2, PS_TYPE_F32);
     93        x->data.F32[0] = 10.0 * psRandomUniform(rng) - 5.0;
     94        x->data.F32[1] = 10.0 * psRandomUniform(rng) - 5.0;
     95        ordinates->data[i] = x;
     96        coordinates->data.F32[i] = function(params, x) + 0.1 * psRandomGaussian(rng); // Add some noise
     97        errors->data.F32[i] = 0.1;
     98        printf("Data %ld: (%f, %f) --> %f\n", i, x->data.F32[0], x->data.F32[1], coordinates->data.F32[i]);
     99    }
     100
     101    if (!psMinimizeLMChi2(min, NULL, params, NULL, ordinates, coordinates, errors,
     102                          (psMinimizeLMChi2Func)fitFunc)) {
    84103        printf("TEST ERROR: psMinimizeLMChi2() returned FALSE.\n");
    85104        fflush(stdout);
    86105        testStatus = false;
    87106    } else {
    88         printf("\nThe value of the function at the minimum is %f\n", min->value);
    89         for (psS32 i=0;i<NUM_DATA_POINTS;i++) {
    90             float myFuncValue = (float)(myFunc(myDerivs, myParams, (psVector *) myCoords->data[i]));
    91             myFuncValue += 0.001;
    92             printf("The minimum for data point number %d: f is %.2f\n",
    93                    i, myFuncValue);
     107        printf("Minimisation took %d iterations\n", min->iter);
     108        printf("chi^2 at the minimum is %f\n", min->value);
     109        for (long i = 0; i < NUM_PARAMS; i++) {
     110            printf("Parameter %ld at the minimum is %f, expected: %f\n", i,
     111                   params->data.F32[i], trueParams->data.F32[i]);
    94112            fflush(stdout);
    95113        }
    96 
    97         for (psS32 i=0;i<NUM_PARAMS;i++) {
    98             printf("Parameter %d at the minimum is %.1f (expected: %.1f)\n", i,
    99                    myParams->data.F32[i], expectedParm[i]);
     114        float diff = 0.0;
     115        for (long i = 0; i < NUM_DATA_POINTS; i++) {
     116            psVector *x = ordinates->data[i];
     117            float fitted = function(trueParams, x);
     118            float expected = function(params, x);
     119            diff += (fitted - expected) / fabsf(expected);
     120            printf("Data point %ld: Fitted: %f, expected: %f\n", i, fitted, expected);
    100121            fflush(stdout);
    101122        }
     123        printf("Mean relative difference is %f\n", diff/(float)NUM_DATA_POINTS);
     124
    102125    }
    103126
    104127    psFree(min);
    105     psFree(myCovar);
    106     psFree(myParams);
    107     psFree(myDerivs);
    108     psFree(myCoords);
    109     psFree(y);
     128    psFree(params);
     129    psFree(trueParams);
     130    psFree(ordinates);
     131    psFree(coordinates);
     132    psFree(errors);
     133    psFree(rng);
    110134    psMemCheckCorruption(1);
    111135    psS32 memLeaks = psMemCheckLeaks(currentId, NULL, NULL, false);
Note: See TracChangeset for help on using the changeset viewer.