Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

gnn_criterion.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *  @file gnn_criterion.h
00003  *  @brief Basic Structure for Criterions.
00004  *
00005  *  @date   : 24-08-03 19:28
00006  *  @author : Pedro Ortega C. <peortega@dcc.uchile.cl>
00007  *  Copyright  2003  Pedro Ortega C.
00008  ****************************************************************************/
00009 /*
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00023  */
00024 
00025 /**
00026  * @brief The common (underlying) data structure for criterions.
00027  * @defgroup gnn_criterion_doc gnn_criterion : Basic Criterion Function.
00028  * @ingroup libgnn_criterion
00029  * @todo 1) Document the datatypes... gnn_criterion and its function types...
00030  *       2) Implement "evaluate" and "eval"
00031  *
00032  * A criterion is a special structure used for measuring the quality of a given
00033  * model. It implements a function
00034  * \f$E: \mathbb{R}^m \times \mathbb{R}^m \rightarrow \mathbb{R}\f$ that takes
00035  * two input vectors \f$y \in \mathbb{R}^m\f$ and \f$t \in \mathbb{R}^m\f$ as
00036  * arguments, and computes a cost value \f$ E(y,t) \f$ that should be minimized
00037  * during training.
00038  *
00039  * Normally, \f$E(y,t)\f$ measures the error or distance between the vectors
00040  * \f$y\f$ and \f$t\f$. This is important, because when modelling, the aim
00041  * is to minimize the error of the Model, that is, the estimation
00042  * \f[ F(x, w) = y \f]
00043  * should be similar to the desired output \f$t\f$.
00044  *
00045  * In order to use the criterion during training, which is almost always an
00046  * optimization process which uses the gradient
00047  * \f$\frac{\partial E}{\partial w}\f$, the function's gradient with respect
00048  * to \f$y\f$, that is, \f$\frac{\partial E}{\partial y}\f$, should be
00049  * available.
00050  *
00051  * \ref libgnn provides a common structure for criterions with the
00052  * \ref gnn_criterion and its associated functions. The \ref gnn_criterion
00053  * data type is a generic structure, which needs to be extended in order to be
00054  * usable. Basically, the structure should be equipped with an evaluation
00055  * function and a gradient evaluation function.
00056  *
00057  * To create a new criterion, you have two options:
00058  * - use one of the ready-to-use criterions
00059  * - implement your own criterion
00060  *
00061  * To use one of the available criterions, just create it using its constructor
00062  * function. In example, to create a \ref gnn_mean_square criterion, invoke
00063  * \code
00064    gnn_criterion *crit;
00065    
00066    crit = gnn_mean_square_new (10);
00067  * \endcode
00068  * which creates a new criterion of size 10.
00069  *
00070  * All criterion conform to a common interface, which is:
00071  * - \ref gnn_criterion_evaluate_e : Evaluates the criterion given a vector
00072  *   \f$y\f$ and a target \f$t\f$.
00073  * - \ref gnn_criterion_evaluate_dy : Evaluates the gradient
00074  *   \f$ \frac{\partial E}{\partial y} \f$ for the last evaluated \f$ y \f$
00075  *   and \f$ t \f$ vectors.
00076  * - \ref gnn_criterion_destroy : Destroys a criterion (by freeing its memory).
00077  * Each of these functions behave different for the specific type of criterion.
00078  *
00079  *
00080  * To implement a new criterion, you have to provide 3 specific functions
00081  * to be called by those mentioned above and install them into the
00082  * \ref gnn_criterion structure using the \ref gnn_criterion_init function.
00083  *
00084  * The 3 specific functions are of the following types:
00085  * - \ref gnn_criterion_e : A function that computes the value of the criterion
00086  *   or cost using \f$y\f$ and \f$t\f$.
00087  * - \ref gnn_criterion_dy : A function that computes the gradient
00088  *   \f$\frac{\partial E}{\partial y}\f$
00089  * - \ref gnn_criterion_destructor : A destructor for the specific extension's
00090  *   data.
00091  *
00092  * If your own criterion need additional resources, such as additional
00093  * parameters, then you have to extend the \ref gnn_criterion with the
00094  * additional fields that are needed. Remember to deallocate the specific
00095  * memory in your destructor, like in a \ref gnn_node.
00096  *
00097  * Another different form of a \ref gnn_criterion is a regularizator.
00098  * It performs a regularization of the error function, in the form:
00099  *
00100  * \f[ \widetilde{E} = E + \nu \Omega \f]
00101  *
00102  * where \f$E\f$ is an error criterion, called the "subcriterion" in
00103  * \ref libgnn, and \f$\Omega\f$ is a regularization term. The scalar
00104  * \f$\nu\f$ is called the regularization coefficient, which determines
00105  * the extent in which the regularization term affects the overall resulting
00106  * error \f$\widetilde{E}\f$. Regularization do limit the \ref gnn_node's
00107  * function complexity in order to perform better in generalization.
00108  * A regularization term usually penalizes the curvature of the output
00109  * mapping. Some of them (e.g. \em Weight \em Decay) depend directly on
00110  * the values of the function's parameters. They do coexist with a
00111  * \ref gnn_criterion, and need an error function upon construction.
00112  */
00113 
00114 
00115 
00116 /******************************************/
00117 /* Include Files                          */
00118 /******************************************/
00119 
00120 #include <string.h>
00121 #include "gnn_criterion.h"
00122 
00123 
00124 
00125 /******************************************/
00126 /* Public Interface                       */
00127 /******************************************/
00128 
00129 /**
00130  * @brief Initializes a \ref gnn_criterion.
00131  * @ingroup gnn_criterion_doc
00132  *
00133  * This function initializes a \ref gnn_criterion by setting its size and
00134  * installing the specific functions for \f$ E \f$,
00135  * \f$ \frac{\partial E}{\partial y} \f$ and the destructor.
00136  *
00137  * It is mandatory to provide:
00138  * - A size that is stricly positive.
00139  * - The evaluation function.
00140  * - The gradient evaluation function.
00141  *
00142  * If the destructor is ommitted (by giving NULL as argument), then it will
00143  * be assumed that no special deallocation is necessary for the extension.
00144  *
00145  * In example, suppose you want to implement a criterion called "my_criterion"
00146  * and that you have already coded the evaluation function and the gradient
00147  * function, which you called "my_criterion_e" and "my_criterion_dy"
00148  * respectivelly. Your criterion doesn't need any additional data to compute
00149  * them, so you didn't extend the basic \ref gnn_criterion. Then, the
00150  * code would be a template for the constructor:
00151  * \code
00152    gnn_criterion *
00153    my_criterion_new (size_t size)
00154    {
00155        int status;
00156        gnn_criterion *crit;
00157        
00158        // allocate memory for the criterion
00159        crit = (gnn_criterion *) malloc (sizeof (gnn_criterion));
00160        
00161        // initialize
00162        status = gnn_criterion_init (crit, "my criterion", size,
00163                        my_criterion_e, my_criterion_dy, my_criterion_destroy);
00164        if (status)
00165            print_an_error_message_and_return_null ();
00166 
00167        // return
00168        return crit;
00169    }
00170  * \endcode
00171  *
00172  * @param  crit    A pointer to a \ref gnn_criterion.
00173  * @param  type    A string containing the name of the criterion.
00174  * @param  size    The size of the input vectors \f$ y \f$ and \f$ t \f$.
00175  * @param  e       A pointer to the evaluation function.
00176  * @param  dy      A pointer to the gradient evaluation function.
00177  * @param  destroy A pointer to the destructor function.
00178  * @return Returns 0 if the initialization could be performed with success.
00179  */
00180 int
00181 gnn_criterion_init (gnn_criterion *crit,
00182                     const char    *type,
00183                     size_t         size,
00184                     gnn_criterion_e          e,
00185                     gnn_criterion_dy         dy,
00186                     gnn_criterion_destructor destroy)
00187 {
00188     int status;
00189     
00190     assert (crit != NULL);
00191     assert (type != NULL);
00192     
00193     /* check size */
00194     if (size < 1)
00195         GSL_ERROR ("gnn_criterion size should be stricly positive", GSL_EINVAL);
00196     
00197     /* set the criterion's fields */
00198     crit->type    = strdup (type);
00199     crit->m       = size;
00200     crit->e       = NULL;
00201     crit->dy      = NULL;
00202     crit->destroy = NULL;
00203     
00204     /* install functions */
00205     if (e == NULL)
00206     {
00207         GSL_ERROR ("gnn_criterion should have an evaluation function",
00208                    GSL_EINVAL);
00209     }
00210     else
00211         crit->e = e;
00212         
00213     if (dy == NULL)
00214     {
00215         GSL_ERROR ("gnn_criterion should have a gradient function",
00216                    GSL_EINVAL);
00217     }
00218     else
00219         crit->dy = dy;
00220 
00221     if (destroy != NULL)
00222         crit->destroy = destroy;
00223     
00224     return 0;
00225 }
00226 
00227 /**
00228  * @brief Returns a criterion's size.
00229  * @ingroup gnn_criterion_doc
00230  *
00231  * This functions returns the size \f$m\f$of the vectors \f$y\f$ and \f$t\f$.
00232  *
00233  * @param  crit A pointer to a \ref gnn_criterion.
00234  * @return Returns the size.
00235  */
00236 size_t
00237 gnn_criterion_get_size (gnn_criterion *crit)
00238 {
00239     assert (crit != NULL);
00240     
00241     return crit->m;
00242 }
00243 
00244 /**
00245  * @brief Returns the name of the criterion.
00246  * @ingroup gnn_criterion_doc
00247  *
00248  * This functions returns a string which identifies uniquely the current
00249  * criterion's type.
00250  *
00251  * @param  crit A pointer to a \ref gnn_criterion.
00252  * @return Returns a non-modifiable string.
00253  */
00254 const char *
00255 gnn_criterion_get_type (gnn_criterion *crit)
00256 {
00257     assert (crit != NULL);
00258     
00259     return crit->type;
00260 }
00261 
00262 /**
00263  * @brief Evaluates the criterion.
00264  * @ingroup gnn_criterion_doc
00265  *
00266  * This function evaluates the criterion for the given vectors "y" and "t",
00267  * which are (usually) the Models output \f$ y \f$ and the desired target
00268  * vector \f$ t \f$.
00269  *
00270  * It will call the specific evaluation function for the criterion, which
00271  * was previosly installed.
00272  *
00273  * @param  crit A pointer to a \ref gnn_criterion.
00274  * @param  y    A pointer to a vector (the estimation).
00275  * @param  t    A pointer to a vector (the target).
00276  * @return The value of the criterion.
00277  */
00278 double
00279 gnn_criterion_evaluate_e (gnn_criterion *crit,
00280                           const gsl_vector *y,
00281                           const gsl_vector *t)
00282 {
00283     assert (crit != NULL);
00284 
00285     /* store vectors */
00286     crit->y = y;
00287     crit->t = t;
00288 
00289     /* evaluate */
00290     return crit->e (crit, y, t);
00291 }
00292 
00293 /**
00294  * @brief Evaluates the criterion's gradient.
00295  * @ingroup gnn_criterion_doc
00296  *
00297  * This function evaluates the criterion's gradient with respect to the
00298  * last evaluated estimation \f$y\f$ and target \f$t\f$. The gradient always
00299  * is of the same size. Internally, it clears the buffer "dy" (where the
00300  * resulting gradient should be placed in) and then calls
00301  * \ref gnn_criterion_evaluate.
00302  *
00303  * @param  crit A pointer to a \ref gnn_criterion.
00304  * @param  dy   A pointer to a buffer vector of the correct size for
00305  *              storing the gradient.
00306  * @return Returns 0 if succeeded.
00307  */
00308 int
00309 gnn_criterion_evaluate_dy (gnn_criterion *crit,
00310                            gsl_vector *dy)
00311 {
00312     assert (crit != NULL);
00313 
00314     /* clear buffer */
00315     gsl_vector_set_zero (dy);
00316 
00317     /* evaluate */
00318     return gnn_criterion_eval_dy (crit, dy);
00319 }
00320 
00321 /**
00322  * @brief Evaluates the criterion's gradient.
00323  * @ingroup gnn_criterion_doc
00324  *
00325  * This function evaluates the criterion's gradient with respect to the
00326  * last evaluated estimation \f$y\f$ and target \f$t\f$ and ADDS the result
00327  * to the vector pointed by "dy". It is important to note the following rules:
00328  *
00329  * - This function is called by \ref gnn_criterion_evaluate_dy.
00330  * - Composed criterions, which depend on inner subcriterions often need
00331  *   to compute their gradient as the result of summing up their subgradients.
00332  *
00333  * This is why the evaluation of the gradient has been split up into the
00334  * base function \ref gnn_criterion_evaluate_dy (which clears the buffer
00335  * "dy" first) and this function.
00336  *
00337  * This function calls the criterion's specific gradient function.
00338  *
00339  * @param  crit A pointer to a \ref gnn_criterion.
00340  * @param  dy   A pointer to a buffer vector of the correct size where the
00341  *              gradient \f$\frac{\partial E}{\partial y}\f$ is added up.
00342  * @return Returns 0 if succeeded.
00343  */
00344 int
00345 gnn_criterion_eval_dy (gnn_criterion *crit,
00346                            gsl_vector *dy)
00347 {
00348     /* evaluate */
00349     return crit->dy (crit, crit->y, crit->t, dy);
00350 }
00351 
00352 /**
00353  * @brief Destroys the criterion.
00354  * @ingroup gnn_criterion_doc
00355  *
00356  * This function destroys a given criterion structure by freeing its memory.
00357  *
00358  * It will call the specific destroy function (if any) for the criterion, which
00359  * was previosly installed. Then it frees the fields of \ref gnn_criterion and
00360  * the structure itself.
00361  *
00362  * @param  crit A pointer to a \ref gnn_criterion.
00363  */
00364 void
00365 gnn_criterion_destroy (gnn_criterion *crit)
00366 {
00367     assert (crit != NULL);
00368     
00369     if (crit->destroy != NULL)
00370         crit->destroy (crit);
00371     
00372     free ((char *) crit->type);
00373     free (crit);
00374 }
00375 

Generated on Sun Jun 13 20:50:11 2004 for libgnn Gradient Retropropagation Machine Library by doxygen1.2.18