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
1.2.18