00001 /*************************************************************************** 00002 * @file gnn_node.c 00003 * @brief gnn_node Implementation File. 00004 * 00005 * @date : 11-08-03 22:45 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 00027 /** 00028 * @brief The underlying basic building block for composite gradient machines. 00029 * @defgroup gnn_node_doc gnn_node : Basic Building Block for Gradient Machines. 00030 * @ingroup libgnn_node 00031 * 00032 * This is the basic building block for \ref libgnn's trainable functions. 00033 * The \ref gnn_node data type and its programming interface provide the 00034 * machinery for the construction, composition, evaluation and training 00035 * of vector functions. The \ref gnn_node structure is optimized for the 00036 * evaluation of its gradient (with respect to its inputs and its parameters) 00037 * using the error-backpropagation scheme (a type of 00038 * cascade-gradient-evaluation). 00039 * 00040 * \ref gnn_node shouldn't be used by themself. Instead, new node types extend 00041 * the \ref gnn_node data type. 00042 * 00043 * The conventions for notation used throughout this documentation is: 00044 * 00045 * A \ref gnn_node implements a set \f$\mathbb{F}\f$ of vectorial functions 00046 * \f$f: \mathbb{R}^n \rightarrow \mathbb{R}^m\f$ that map an input vector 00047 * \f$x\f$ of size \f$n \times 1\f$ to an ouput vector \f$y\f$ of size 00048 * \f$m \times 1\f$. 00049 * This set can be a singleton, or, 00050 * optionally, it can have a vector of adjustable parameters 00051 * \f$w \in \mathbb{R}^l\f$ of size \f$l \times 1\f$ so that 00052 * \f[ \mathbb{F} = 00053 * \{ f(\cdot) | f(\cdot) = F(\cdot, w), w\in \mathbb{R}^l \} 00054 * \f] 00055 * In this case, we will talk about the "generic" function 00056 * \f$F : \mathbb{R}^{n+l} \rightarrow \mathbb{R}^m\f$ as the "Machine" or 00057 * the "Model". 00058 * 00059 * A general machine \f$F\f$ can be built by connecting several subfunctions 00060 * in a variety of forms. The resulting function can then be feed with inputs 00061 * to compute its output. Since \ref libgnn's main purpose is to offer a 00062 * unified way to train this function using the error-backpropagation scheme 00063 * to compute the function's gradient with respect to its parameters 00064 * \f$\frac{\partial E}{\partial w}\f$, the \ref gnn_node structure has 00065 * been designed to provide a simple yet powerful extendable skeleton 00066 * for the implementation of highly customized models. 00067 * 00068 * The evaluation of the result is the <b>Forward Evaluation</b>, triggered 00069 * by the \ref gnn_node_evaluate_f function, and the computation of both 00070 * gradient is called <b>Backward Evaluation</b>, triggered (in order) by 00071 * \ref gnn_node_evaluate_dx and \ref gnn_node_evaluate_dw . 00072 * 00073 * <img src="images/gnn_node1.png" border="0"> 00074 * 00075 * In order to compute the result and the gradients for one (and only one!) 00076 * given input example, you should call, in order: 00077 * 00078 * -# \ref gnn_node_evaluate_init : Cleans the old parameter gradient. 00079 * -# \ref gnn_node_evaluate_f : Evaluates the output. 00080 * -# \ref gnn_node_evaluate_dx : Computes the gradient with respect to 00081 * its inputs. 00082 * -# \ref gnn_node_evaluate_dw : Computes the gradient with respect to 00083 * its outputs. 00084 * 00085 * The order function calling sequence above must be respected, 00086 * and repeated for each input example. Nevertheless, it isn't mandatory 00087 * to perform all steps in the sequence, i.e. if you want to compute only 00088 * the output, perform only the first two steps; if you don't need the 00089 * gradient with respect to the paremeters, then don't call 00090 * \ref gnn_node_evaluate_dw . 00091 * 00092 * 00093 * <b>More about extensions:</b> 00094 * 00095 * Although all specific extensions have their own specific features, they all 00096 * are (or can be casted to) a \ref gnn_node. A \ref gnn_node can be manipulated 00097 * with the following APIs: 00098 * 00099 * - Basic API: This interface provides the basic functionality, such as 00100 * retrieving the internal attributes, evaluating an input and 00101 * evaluating its gradients \f$\frac{\partial E}{\partial x}\f$ 00102 * and \f$\frac{\partial E}{\partial w}\f$. 00103 * - \ref gnn_node_param_doc : Offers the functionality to change the node's 00104 * parameters. 00105 * - \ref gnn_node_ext_doc : This interface provides the functions needed for 00106 * extending a \ref gnn_node for your particular purposes. 00107 * - \ref gnn_node_sub_doc : This last interface is also an extension API, but 00108 * it offers the functions for connecting and traversing a tree of 00109 * nodes. This is only needed when you want to implement a 00110 * construction node (a node which groups other nodes). 00111 * 00112 * 00113 */ 00114 00115 /** 00116 * @brief Atomic Nodes. 00117 * @defgroup gnn_atomic_doc Atomic Nodes. 00118 * @ingroup libgnn_node 00119 * 00120 * Atomic nodes are implementations of the \ref gnn_node interface that 00121 * do not depend on subnodes to compute its result and gradients. Most 00122 * node types are <b>atomic</b>. 00123 */ 00124 00125 /** 00126 * @brief Constructor Nodes. 00127 * @defgroup gnn_constructor_doc Constructor Nodes. 00128 * @ingroup libgnn_node 00129 * 00130 * Constructor nodes are nodes that do depend on subnodes in order to compute 00131 * the represented function's result and gradients. They usually provide a 00132 * way to compose modules, like the \ref gnn_serial or \ref gnn_parallel 00133 * constructor nodes. 00134 * 00135 * Constructor nodes are the glue of Gradient Backpropagation Machines. 00136 * 00137 */ 00138 00139 00140 00141 /******************************************/ 00142 /* Include Files */ 00143 /******************************************/ 00144 00145 #include <assert.h> 00146 #include <stdarg.h> 00147 #include <gsl/gsl_block.h> 00148 #include <string.h> 00149 #include "gnn_utilities.h" 00150 #include "gnn_node.h" 00151 00152 00153 /******************************************/ 00154 /* Static Definitions */ 00155 /******************************************/ 00156 00157 00158 static void 00159 gnn_node_destroy_structure (gnn_node *node); 00160 00161 static int 00162 gnn_node_default_f (gnn_node *node, 00163 const gsl_vector *x, 00164 const gsl_vector *w, 00165 gsl_vector *y ); 00166 00167 static int 00168 gnn_node_default_dx (gnn_node *node, 00169 const gsl_vector *x, 00170 const gsl_vector *w, 00171 const gsl_vector *dy, 00172 gsl_vector *dx ); 00173 00174 static int 00175 gnn_node_default_dw (gnn_node *node, 00176 const gsl_vector *x, 00177 const gsl_vector *w, 00178 const gsl_vector *dy, 00179 gsl_vector *dw ); 00180 00181 static void 00182 gnn_node_default_destructor (gnn_node *node); 00183 00184 static int 00185 gnn_node_sub_search_params_recurse (gnn_node *node, 00186 const char *type, 00187 gnn_pbundle *pb); 00188 00189 00190 00191 /******************************************/ 00192 /* Static Implementations */ 00193 /******************************************/ 00194 00195 /** 00196 * @brief Destroys a \ref gnn_node. 00197 * @ingroup gnn_node_ext_doc 00198 * 00199 * This function destroys the underlying \ref gnn_node structure by freeing 00200 * the memory associated to the fields of the node and freeing the structure 00201 * itself. It also calls the \ref gnn_node_destroy function on all subnodes. 00202 * 00203 * This function should not be called directly. Instead, \ref gnn_node_destroy 00204 * should be called instead in order to free also additional resources that 00205 * could have been allocated specifically for the node's type. Please read also 00206 * the details available in \ref gnn_node_destroy's documentation. 00207 * 00208 * @param node A pointer to a \ref gnn_node. 00209 */ 00210 static void 00211 gnn_node_destroy_structure (gnn_node *node) 00212 { 00213 int i; 00214 gnn_node *subnode; 00215 00216 assert (node != NULL); 00217 00218 /* destroy subnodes */ 00219 for (i=0; i<node->nsub; ++i) 00220 { 00221 node->sub[i]->super = NULL; 00222 gnn_node_destroy (node->sub[i]); 00223 } 00224 00225 /* destroy fields */ 00226 gnn_pbundle_destroy (node->pb); 00227 gnn_phandle_unref (node->ph); 00228 free ((char *) node->type); 00229 00230 if (node->sub != NULL) 00231 free (node->sub); 00232 00233 /* free node memory */ 00234 free (node); 00235 } 00236 00237 /** 00238 * @brief Default evaluation function. 00239 * @ingroup gnn_node_ext_doc 00240 * 00241 * This is the default evaluation function for a \ref gnn_node when initialized 00242 * with NULL in \ref gnn_node_init. It computes 00243 * \f[ y = [x,x,x,\ldots]^t \f] 00244 * that is, it copies the input vector \f$x\f$ several times into the output 00245 * vector until it is completely filled. 00246 * 00247 * @param node A pointer to a \ref gnn_node. 00248 * @param x The input vector \f$x\f$. 00249 * @param w The node's parameter vector \f$w\f$. 00250 * @param y The output vector \f$y\f$ where the result should be placed. 00251 * @return 0 if succeeded. 00252 */ 00253 static int 00254 gnn_node_default_f (gnn_node *node, 00255 const gsl_vector *x, 00256 const gsl_vector *w, 00257 gsl_vector *y ) 00258 { 00259 int i; 00260 int j; 00261 00262 assert (node != NULL); 00263 00264 /* copy input to output several times */ 00265 j = 0; 00266 while (j < node->m) 00267 { 00268 i = 0; 00269 while (i < node->n && j < node->m) 00270 { 00271 gsl_vector_set (y, j, gsl_vector_get (x, i)); 00272 ++j; 00273 ++i; 00274 } 00275 } 00276 00277 return 0; 00278 } 00279 00280 /** 00281 * @brief Default \f$\frac{\partial E}{\partial x}\f$ evaluation function. 00282 * @ingroup gnn_node_ext_doc 00283 * 00284 * This is the default \f$\frac{\partial E}{\partial x}\f$ evaluation function 00285 * for a \ref gnn_node when initialized with NULL in \ref gnn_node_init. It 00286 * computes 00287 * \f[ ? \f] 00288 * @todo Not implemented yet. 00289 * 00290 * @param node A pointer to a \ref gnn_node. 00291 * @param x The input vector \f$x\f$ where the gradient should be evaluated. 00292 * @param w The function's parameters \f$w\f$ where the gradient should be 00293 * evaluated at. 00294 * @param dy The vector \f$\frac{\partial E}{\partial y}\f$ that should 00295 * be retropropagated. 00296 * @param dx A sufficiently large vector for storing the resulting 00297 * \f$\frac{\partial E}{\partial x}\f$ should be placed at. 00298 * @return 0 if succeeded. 00299 */ 00300 static int 00301 gnn_node_default_dx (gnn_node *node, 00302 const gsl_vector *x, 00303 const gsl_vector *w, 00304 const gsl_vector *dy, 00305 gsl_vector *dx ) 00306 { 00307 return 0; 00308 } 00309 00310 /** 00311 * @brief Default \f$\frac{\partial E}{\partial w}\f$ evaluation function. 00312 * @ingroup gnn_node_ext_doc 00313 * 00314 * This is the default \f$\frac{\partial E}{\partial w}\f$ evaluation function 00315 * for a \ref gnn_node when initialized with NULL in \ref gnn_node_init. It 00316 * computes 00317 * \f[ ? \f] 00318 * @todo Not implemented yet. 00319 * 00320 * @param node A pointer to a \ref gnn_node. 00321 * @param x The input vector \f$x\f$ where the gradient should be evaluated. 00322 * @param w The function's parameters \f$w\f$ where the gradient should be 00323 * evaluated at. 00324 * @param dy The vector \f$\frac{\partial E}{\partial y}\f$ that should 00325 * be retropropagated. 00326 * @param dw A sufficiently large vector for storing the resulting 00327 * \f$\frac{\partial E}{\partial w}\f$ should be placed at. 00328 * @return 0 if succeeded. 00329 */ 00330 static int 00331 gnn_node_default_dw (gnn_node *node, 00332 const gsl_vector *x, 00333 const gsl_vector *w, 00334 const gsl_vector *dy, 00335 gsl_vector *dw ) 00336 { 00337 return 0; 00338 } 00339 00340 /** 00341 * @brief Default \ref gnn_node destructor. 00342 * @ingroup gnn_node_ext_doc 00343 * 00344 * This is the default destructor for a \ref gnn_node when initialized 00345 * with NULL in \ref gnn_node_init. It asumes that the current \ref gnn_node 00346 * type hasn't allocated any additional memory nor contains any other specific 00347 * info other than a \ref gnn_node's default. 00348 * 00349 * Consecuently, it doesn't anything than just return. 00350 * 00351 * @param node A pointer to a \ref gnn_node. 00352 */ 00353 static void 00354 gnn_node_default_destructor (gnn_node *node) 00355 { 00356 assert (node != NULL); 00357 return; 00358 } 00359 00360 /** 00361 * @brief The recursive function for parameters searchs. 00362 * @ingroup gnn_node_sub_doc 00363 * 00364 * This function is invoked by \ref gnn_node_sub_search_params. 00365 * 00366 * @param node A pointer to a \ref gnn_node. 00367 * @param type A string identifying the searched nodes. 00368 * @param pb A pointer to a \ref gnn_pbundle. 00369 * @return 0 if succeeded. 00370 */ 00371 static int 00372 gnn_node_sub_search_params_recurse (gnn_node *node, 00373 const char *type, 00374 gnn_pbundle *pb) 00375 { 00376 size_t i; 00377 00378 assert (node != NULL); 00379 00380 /* insert parameter handle into parameter bundle if type matches */ 00381 if (strcmp (node->type, type) == 0) 00382 gnn_pbundle_insert (pb, node->ph, 1); 00383 00384 /* base case : no more subnodes available */ 00385 if (node->nsub == 0) 00386 return 0; 00387 00388 /* recursion case : search all subtrees */ 00389 for (i=0; i<node->nsub; ++i) 00390 gnn_node_sub_search_params_recurse (node->sub[i], type, pb); 00391 00392 return 0; 00393 } 00394 00395 00396 00397 /******************************************/ 00398 /* Public Interface */ 00399 /******************************************/ 00400 00401 /*************/ 00402 /* Basic API */ 00403 /*************/ 00404 00405 /** 00406 * @brief Check if node is root node. 00407 * @ingroup gnn_node_doc 00408 * 00409 * This function returns 1 if the current node is a root node, or 0 if not. 00410 * 00411 * @param node A \ref gnn_node. 00412 * @return 1 if root node, 0 if not. 00413 */ 00414 int 00415 gnn_node_is_root (gnn_node *node) 00416 { 00417 assert (node != NULL); 00418 if (node->super == NULL) 00419 return 1; 00420 else 00421 return 0; 00422 } 00423 00424 /** 00425 * @brief Get the node's type. 00426 * @ingroup gnn_node_doc 00427 * 00428 * This function returns the node's type: an unique string 00429 * which identifies a node's type. 00430 * 00431 * Generally speaking, the type depends on which constructor function was used 00432 * to instantiate the node. Per example, gnn_weight_new () creates a 00433 * "gnn_weight" node, gnn_tanh_new () creates a "gnn_tanh" node. 00434 * 00435 * The returned string is owned by the node and should not be freed or 00436 * manipulated in any other way. 00437 * 00438 * @param node A \ref gnn_node. 00439 * @return A string containing n integer identifying the layer's type. 00440 */ 00441 const char * 00442 gnn_node_get_type_name (gnn_node *node) 00443 { 00444 assert (node != NULL); 00445 return node->type; 00446 } 00447 00448 /** 00449 * @brief Get the node's input size. 00450 * @ingroup gnn_node_doc 00451 * 00452 * This function returns the size \f$n\f$ of the input vector \f$x\f$ that 00453 * the current node's function \f$f\f$ demands for computing its output 00454 * \f$y\f$. 00455 * 00456 * @param node A pointer to an \ref gnn_node. 00457 * @return The input size. 00458 */ 00459 int 00460 gnn_node_input_get_size (gnn_node *node) 00461 { 00462 assert (node != NULL); 00463 return node->n; 00464 } 00465 00466 /** 00467 * @brief Get the node's output size. 00468 * @ingroup gnn_node_doc 00469 * 00470 * This function returns the size \f$m\f$ of the output vector \f$y\f$ that 00471 * the current node's function \f$f\f$ computes. 00472 * 00473 * @param node A pointer to an \ref gnn_node. 00474 * @return The output size. 00475 */ 00476 int 00477 gnn_node_output_get_size (gnn_node *node) 00478 { 00479 assert (node != NULL); 00480 return node->m; 00481 } 00482 00483 /** 00484 * @brief Destroys the current node. 00485 * @ingroup gnn_node_doc 00486 * 00487 * This function detroys the node given as a parameter: it calls first the 00488 * installed destructor and the \ref gnn_node_destroy_structure to destroy 00489 * itself. 00490 * 00491 * This is a virtual function: the specific destruction of the node is given 00492 * by the installed \ref gnn_node::destroy function, and the destruction of 00493 * the underlying's node structure by itself is performed by 00494 * \ref gnn_node_destroy_structure. 00495 * 00496 * @warning Only root nodes can be destroyed. 00497 * 00498 * @param node A pointer to an \ref gnn_node. 00499 * @return Returns 0 if succeeded. 00500 */ 00501 int 00502 gnn_node_destroy (gnn_node *node) 00503 { 00504 int i; 00505 gnn_node *subnode; 00506 00507 assert (node != NULL); 00508 00509 /* check that node isn't subnode */ 00510 if (node->super != NULL) 00511 GSL_ERROR ("only root nodes can be destroyed", GSL_EINVAL); 00512 00513 /* call destructor */ 00514 node->destroy (node); 00515 00516 /* destroy subyacent node structure */ 00517 gnn_node_destroy_structure (node); 00518 00519 return 0; 00520 } 00521 00522 /** 00523 * @brief Evaluates the output of the function recursively. 00524 * @ingroup gnn_node_doc 00525 * 00526 * This function computes the output of the node's function. First, it sets the 00527 * appropiate values for initiating the recursive evaluation, and then calls 00528 * \ref gnn_node_eval_f. 00529 * 00530 * @warning: If you want to compute \f$\frac{\partial E}{\partial x}\f$, then 00531 * you should not change the content of the input buffer \f$x\f$. 00532 * 00533 * @param node A pointer to an \ref gnn_node. 00534 * @param x The input vector \f$x\f$ of the correct size that should be 00535 * evaluated. 00536 * @param y A gsl_vector, where the result should be placed. 00537 * @return Returns 0 if suceeded. 00538 */ 00539 int 00540 gnn_node_evaluate_f (gnn_node *node, const gsl_vector *x, gsl_vector *y) 00541 { 00542 assert (node != NULL); 00543 00544 /* check sizes */ 00545 if ( (x == NULL && node->n != 0) 00546 || (x != NULL && node->n != x->size)) 00547 GSL_ERROR ("incorrect size of x vector", GSL_EINVAL); 00548 00549 if ( (y == NULL && node->m != 0) 00550 || (y != NULL && node->m != y->size)) 00551 GSL_ERROR ("incorrect size of y vector", GSL_EINVAL); 00552 00553 /* clear y vector */ 00554 gsl_vector_set_zero (y); 00555 00556 /* call evaluation */ 00557 gnn_node_eval_f (node, x, y); 00558 00559 return 0; 00560 } 00561 00562 /** 00563 * @brief Initializes the evaluations. 00564 * @ingroup gnn_node_doc 00565 * 00566 * This function initializes the gradient evaluation routines. It should be 00567 * called before \ref gnn_node_eval_f, for every single pattern or input 00568 * evaluation. The complete sequence for evaluations is: 00569 * 00570 * - \ref gnn_node_evaluate_init 00571 * - \ref gnn_node_evaluate_f 00572 * - \ref gnn_criterion_e 00573 * - \ref gnn_criterion_de 00574 * - \ref gnn_node_evaluate_dx 00575 * - \ref gnn_node_evaluate_dw 00576 * 00577 * @param node A pointer to an \ref gnn_node. 00578 * @return Returns 0 if suceeded. 00579 */ 00580 int 00581 gnn_node_evaluate_init (gnn_node *node) 00582 { 00583 assert (node != NULL); 00584 00585 /* clear gradient */ 00586 gnn_pbundle_set_dw_all (node->pb, 0.0); 00587 00588 return 0; 00589 } 00590 00591 /** 00592 * @brief Evaluates the gradient \f$\frac{\partial E}{\partial x}\f$. 00593 * @ingroup gnn_node_doc 00594 * 00595 * This function computes \f$\frac{\partial E}{\partial x}\f$ of the node's 00596 * function. First, it sets the 00597 * appropiate values for initiating the recursive evaluation, and then calls 00598 * \ref gnn_node_eval_dx. 00599 * 00600 * @warning: The \f$\frac{\partial E}{\partial x}\f$ gradient will be evaluated 00601 * at \f$(x,w)\f$, where \f$x\f$ is the last evaluated input vector, 00602 * and \f$w\f$ is the last parameter vector. That is, the last values 00603 * given at \ref gnn_node_evaluate_f. 00604 * 00605 * @param node A pointer to an \ref gnn_node. 00606 * @param dy The \f$\frac{\partial E}{\partial y}\f$ vector. 00607 * @param dx A gsl_vector, where the result should be placed. 00608 * @return Returns 0 if suceeded. 00609 */ 00610 int 00611 gnn_node_evaluate_dx (gnn_node *node, 00612 const gsl_vector *dy, 00613 gsl_vector *dx) 00614 { 00615 assert (node != NULL); 00616 assert (dy != NULL); 00617 assert (dx != NULL); 00618 00619 /* check sizes */ 00620 if (dy->size != node->m) 00621 GSL_ERROR ("incorrect size of dy vector", GSL_EINVAL); 00622 00623 if (dx->size != node->n) 00624 GSL_ERROR ("incorrect size of dx vector", GSL_EINVAL); 00625 00626 /* clear dx vector */ 00627 gsl_vector_set_zero (dx); 00628 00629 /* call gradient evaluation */ 00630 return gnn_node_eval_dx (node, dy, dx); 00631 } 00632 00633 /** 00634 * @brief Evaluates the gradient \f$\frac{\partial E}{\partial w}\f$. 00635 * @ingroup gnn_node_doc 00636 * 00637 * This function computes \f$\frac{\partial E}{\partial w}\f$ of the node's 00638 * function. First, it sets the 00639 * appropiate values for initiating the recursive evaluation, and then calls 00640 * \ref gnn_node_eval_dw. 00641 * 00642 * @warning: The \f$\frac{\partial E}{\partial w}\f$ gradient will be evaluated 00643 * at \f$(x,w)\f$, where \f$x\f$ is the last evaluated input vector, 00644 * and \f$w\f$ is the last parameter vector. Also, it will use 00645 * the last given \f$\frac{\partial E}{\partial x}\f$ for its 00646 * error-backpropagation. In other words, the buffers used for 00647 * both \ref gnn_node_evaluate_f and \ref gnn_node_evaluate_dx 00648 * shouldn't have changed! 00649 * 00650 * @param node A pointer to an \ref gnn_node. 00651 * @param dw A gsl_vector, where the result should be placed. 00652 * @return Returns 0 if suceeded. 00653 */ 00654 int 00655 gnn_node_evaluate_dw (gnn_node *node, 00656 gsl_vector *dw) 00657 { 00658 int size; 00659 00660 assert (node != NULL); 00661 assert (dw != NULL); 00662 00663 /* get bundle size */ 00664 size = gnn_pbundle_get_size (node->pb); 00665 00666 /* check sizes */ 00667 if (size == 0) 00668 GSL_ERROR ("node doesn't contain any parameters", GSL_EINVAL); 00669 00670 if (size != dw->size) 00671 GSL_ERROR ("incorrect size of dw vector", GSL_EINVAL); 00672 00673 /* call recursive gradient evaluation */ 00674 gnn_node_eval_dw (node); 00675 00676 /* copy gradient result */ 00677 gnn_pbundle_get_dw (node->pb, dw); 00678 00679 return 0; 00680 } 00681 00682 00683 00684 /*****************/ 00685 /* Parameter API */ 00686 /*****************/ 00687 00688 /** 00689 * @brief Set of functions for the manipulation of a node's parameters. 00690 * @defgroup gnn_node_param_doc gnn_node Parameters API 00691 * @ingroup gnn_node_doc 00692 * 00693 * The Parameter API (Applicaction Programming Interface) provides 00694 * extended functionality to manipulate a \ref gnn_node's parameters. 00695 * 00696 * Every \ref gnn_node contains a set of parameters (it can be empty of 00697 * course). By changing them, the function's behaviour is changed. Formally, 00698 * the parameters allow the model to be adapted to a particular case. 00699 * It is, therefore, very important to provide extended functionality for 00700 * manipulating them. 00701 * 00702 * Every node contains two types of parameters: 00703 * 00704 * - The node's own parameters. 00705 * - The node's total parameters, which are formed by all parameters in the 00706 * tree rooted at the current node. 00707 * 00708 * Schematically, this can be depicted as (for an atomic node): 00709 * 00710 * <img src="images/gnn_node2.png" border="0"> 00711 * 00712 * When two nodes <i>A</i> and <i>B</i> are composed using a third node 00713 * <i>C</i>, then <i>C</i> will be at the root, and will provide direct 00714 * access to all parameters (that is, the parameters of the whole tree): 00715 * 00716 * <img src="images/gnn_node3.png" border="0"> 00717 * 00718 * This is absolutely transparent to the programmer. Note that each node 00719 * knows exactly which ones are its local parameters, but to get direct 00720 * access to them, <b>use the extension API</b>. 00721 * 00722 * Note that in general, a node which is not a leaf rarely posseses its own 00723 * parameters. 00724 * 00725 * The good thing here is that you gain direct access to the new 00726 * (concatenated) parameter as it were a single vector. 00727 * 00728 * There are two more objects you should know of: the gradient with respect 00729 * to the parameters, and the freeze flags, both vectors of the same size 00730 * as the parameter vector. The first is a buffer, were the gradient should 00731 * be computed. The second is a special flag vector: they specify if a given 00732 * parameter is actually free to be changed (free parameter) of if it has 00733 * been frozen (and can't be changed). These additional vectors can also be 00734 * manipulated using this interface. 00735 * 00736 * 00737 * 00738 * <b>Some technical details:</b> 00739 * 00740 * So, the node accesses its local parameters (which are some kind of "global" 00741 * and independent entities that can perfectly be shared with other nodes) 00742 * through a parameter handle. 00743 * 00744 * Simultaneously, the node also posseses a special parameter bundle, which 00745 * gives him access to the whole tree's parameters. 00746 * 00747 * Although it can be useful to know about the internal details of the 00748 * parameter managing and its implementation, the \ref gnn_node_param_doc 00749 * provides a transparent set of functions to manipulate them. The important 00750 * things to note are: 00751 * 00752 * - Each node has local and total parameters. 00753 * 00754 */ 00755 00756 00757 00758 /** 00759 * @brief Returns the size of the parameter vector. 00760 * @ingroup gnn_node_param_doc 00761 * 00762 * This function returns \f$l\f$, the size of the parameter vector. 00763 * 00764 * @param node A pointer to an \ref gnn_node. 00765 * @return The size of the parameter vector \f$w\f$. 00766 */ 00767 int 00768 gnn_node_param_get_size (gnn_node *node) 00769 { 00770 assert (node != NULL); 00771 return gnn_pbundle_get_size (node->pb); 00772 } 00773 00774 /** 00775 * @brief Get the node's parameters. 00776 * @ingroup gnn_node_param_doc 00777 * 00778 * This function fills the input buffer w with the node's parameter values. 00779 * 00780 * Implementation Note: The parameter vector is build with the node's 00781 * parameter bundle. 00782 * 00783 * @param node A pointer to an \ref gnn_node. 00784 * @param w A gsl_vector sufficiently large to store the values. 00785 * @return Returns 0 if suceeded. 00786 */ 00787 int 00788 gnn_node_param_get (gnn_node *node, gsl_vector *w) 00789 { 00790 assert (node != NULL); 00791 return gnn_pbundle_get_w (node->pb, w); 00792 } 00793 00794 /** 00795 * @brief Sets new values for the parameter vector. 00796 * @ingroup gnn_node_param_doc 00797 * 00798 * This function sets new values for the node's parameter vector. The new 00799 * values are taken by the buffer w (of the correct size) given as input 00800 * argument. 00801 * 00802 * @param node A pointer to an \ref gnn_node. 00803 * @param w A gsl_vector containing the new values for the parameter vector. 00804 * @return Returns 0 if suceeded. 00805 */ 00806 int 00807 gnn_node_param_set (gnn_node *node, const gsl_vector *w) 00808 { 00809 assert (node != NULL); 00810 return gnn_pbundle_set_w (node->pb, w); 00811 } 00812 00813 /** 00814 * @brief Get the freeze flags. 00815 * @ingroup gnn_node_param_doc 00816 * 00817 * This function fills the given integer vector \a f with the node's freeze 00818 * flags. 00819 * 00820 * Implementation Note: The parameter vector is build with the node's 00821 * parameter bundle. 00822 * 00823 * @param node A pointer to an \ref gnn_node. 00824 * @param f A \c gsl_vector_int sufficiently large to store the values. 00825 * @return Returns 0 if suceeded. 00826 */ 00827 int 00828 gnn_node_param_freeze_flags_get (gnn_node *node, gsl_vector_int *f) 00829 { 00830 assert (node != NULL); 00831 return gnn_pbundle_get_f (node->pb, f); 00832 } 00833 00834 /** 00835 * @brief Sets new freeze flags. 00836 * @ingroup gnn_node_param_doc 00837 * 00838 * This function sets new freeze flags for the node. They should be given 00839 * as a \c gsl_vector_int, where 1=freeze and 0=free-parameter. 00840 * 00841 * @param node A pointer to an \ref gnn_node. 00842 * @param f A \c gsl_vector_int containing the new values for the 00843 * parameter vector. 00844 * @return Returns 0 if suceeded. 00845 */ 00846 int 00847 gnn_node_param_freeze_flags_set (gnn_node *node, const gsl_vector_int *f) 00848 { 00849 assert (node != NULL); 00850 return gnn_pbundle_set_f (node->pb, f); 00851 } 00852 00853 /** 00854 * @brief Freeze the i-th parameter. 00855 * @ingroup gnn_node_param_doc 00856 * 00857 * This function freezes the i-th parameter. 00858 * 00859 * @param node A pointer to an \ref gnn_node. 00860 * @param i The index of the parameter to be frozen. 00861 * @return Returns 0 if suceeded. 00862 */ 00863 int 00864 gnn_node_param_freeze (gnn_node *node, int i) 00865 { 00866 assert (node != NULL); 00867 return gnn_pbundle_set_f_at (node->pb, i, 1); 00868 } 00869 00870 /** 00871 * @brief Unfreeze the i-th parameter. 00872 * @ingroup gnn_node_param_doc 00873 * 00874 * This function unfreezes the i-th parameter. 00875 * 00876 * @param node A pointer to an \ref gnn_node. 00877 * @param i The index of the parameter to be unfrozen. 00878 * @return Returns 0 if suceeded. 00879 */ 00880 int 00881 gnn_node_param_unfreeze (gnn_node *node, int i) 00882 { 00883 assert (node != NULL); 00884 return gnn_pbundle_set_f_at (node->pb, i, 0); 00885 } 00886 00887 /** 00888 * @brief Check if the i-th parameter is frozen. 00889 * @ingroup gnn_node_param_doc 00890 * 00891 * This function returns 1 if the i-th parameter is frozen. 00892 * 00893 * @param node A pointer to an \ref gnn_node. 00894 * @param i The index of the parameter to be checked. 00895 * @return Returns 1 if frozen, 0 if not. 00896 */ 00897 int 00898 gnn_node_param_is_frozen (gnn_node *node, int i) 00899 { 00900 assert (node != NULL); 00901 return gnn_pbundle_get_f_at (node->pb, i); 00902 } 00903 00904 /** 00905 * @brief Check if all the node's parameters are frozen. 00906 * @ingroup gnn_node_param_doc 00907 * 00908 * This function returns 1 if all parameters are frozen. 00909 * 00910 * @param node A pointer to an \ref gnn_node. 00911 * @return Returns 1 if frozen, 0 if not. 00912 */ 00913 int 00914 gnn_node_param_are_frozen (gnn_node *node) 00915 { 00916 assert (node != NULL); 00917 if (gnn_pbundle_get_n_free (node->pb) == 0) 00918 return 1; 00919 else 00920 return 0; 00921 } 00922 00923 /** 00924 * @brief Freeze all parameters. 00925 * @ingroup gnn_node_param_doc 00926 * 00927 * This function freezes all the node's parameters. 00928 * 00929 * @param node A pointer to an \ref gnn_node. 00930 * @return Returns 0 if suceeded. 00931 */ 00932 int 00933 gnn_node_param_freeze_all (gnn_node *node) 00934 { 00935 assert (node != NULL); 00936 return gnn_pbundle_set_f_all (node->pb, 1); 00937 } 00938 00939 /** 00940 * @brief Unfreeze all parameters. 00941 * @ingroup gnn_node_param_doc 00942 * 00943 * This function unfreezes all the node's parameters. 00944 * 00945 * @param node A pointer to an \ref gnn_node. 00946 * @return Returns 0 if suceeded. 00947 */ 00948 int 00949 gnn_node_param_unfreeze_all (gnn_node *node) 00950 { 00951 assert (node != NULL); 00952 return gnn_pbundle_set_f_all (node->pb, 0); 00953 } 00954 00955 /** 00956 * @brief Share the node's parameters. 00957 * @ingroup gnn_node_param_doc 00958 * 00959 * This function share the node's parameters with the client node. 00960 * 00961 * @warning: This function should be called on nodes that aren't connected only. 00962 * 00963 * @param node A pointer to an \ref gnn_node. 00964 * @param client A pointer to an \ref gnn_node. 00965 * @return Returns 0 if suceeded. 00966 */ 00967 int 00968 gnn_node_param_share (const gnn_node *node, gnn_node *client) 00969 { 00970 assert (node != NULL); 00971 assert (client != NULL); 00972 00973 /* check if both nodes haven't any parent nor children */ 00974 if ( (node->super != NULL) 00975 || (node->sub != NULL) 00976 || (client->super != NULL) 00977 || (client->sub != NULL)) 00978 GSL_ERROR ("can't share a connected node's parameters", GSL_EINVAL); 00979 00980 /* check parameter sizes */ 00981 if (gnn_phandle_get_size (node->ph) != gnn_phandle_get_size (client->ph)) 00982 GSL_ERROR ("can't share parameters of distinct size", GSL_EINVAL); 00983 00984 /* free the client's parameters */ 00985 gnn_pbundle_destroy (client->pb); 00986 gnn_phandle_unref (client->ph); 00987 00988 /* share parameters */ 00989 client->pb = node->pb; 00990 client->ph = node->ph; 00991 00992 return 0; 00993 } 00994 00995 00996 00997 /*****************/ 00998 /* Extension API */ 00999 /*****************/ 01000 01001 /** 01002 * @brief A set of functions for implementing an extension of gnn_node. 01003 * @defgroup gnn_node_ext_doc gnn_node Extension API 01004 * @ingroup gnn_node_doc 01005 * 01006 * The Extension API (Applicaction Programming Interface) provides 01007 * extended functionality to program new \ref libgnn node. 01008 * 01009 * <b>What is the Extension API's purpose?</b> 01010 * 01011 * The Extension API has been designed in order to provide a framework 01012 * to include custom node types, i.e. nodes that compute a specific 01013 * function that isn't included in the \ref libgnn distribution. 01014 * 01015 * The node types included in the distribution have also been built upon 01016 * this programming interface. 01017 * 01018 * <b>Basics</b> 01019 * 01020 * Creating a new node type requires the programmer to implement at least 01021 * 4 functions, which describe/incarnate the behaviour of the node, and 01022 * are attached to the new node type. 01023 * 01024 * All node types should built upon a basic node type: the \ref gnn_node. 01025 * The C structure which will implement the node type should contain, as 01026 * it's first field, a \ref gnn_node, followed by the additional data field 01027 * the node might need. Per example: 01028 * 01029 * \code 01030 // it's always nice to have a type definition 01031 typedef struct _myNodeType myNodeType; 01032 01033 // the structure definition 01034 struct _myNodeType 01035 { 01036 gnn_node node; // the underlying gnn_node 01037 01038 // now comes the rest 01039 int exampleField1; 01040 double exampleField2; 01041 ... 01042 } 01043 \endcode 01044 * 01045 * To create a custom node, you should provide a constructor. The constructor 01046 * should take the needed info to describe your new instance fully. The 01047 * constructor should allocate memory for the new structure, and initialize 01048 * the underlying \ref gnn_node, by calling the \ref gnn_node_init function: 01049 * 01050 * <i>Example for an Atomic Node Type:</i> 01051 * 01052 \code 01053 // you should return a gnn_node pointer to the new instance 01054 gnn_node * 01055 my_node_new (int input_size, int output_size, int param_size, ...) 01056 { 01057 gnn_node *node; 01058 myNodeType *mynode; 01059 01060 // allocate memory for your node type 01061 mynode = (myNodeType *) malloc (sizeof (myNodeType)); 01062 01063 // get a pointer to the instance, but viewed as a gnn_node : 01064 node = (gnn_node *) mynode; 01065 01066 // call the initialization function 01067 gnn_node_init ( node, 01068 "myNodeType", 01069 my_node_type_f, 01070 my_node_type_dx, 01071 my_node_type_dw, 01072 my_node_type_dest 01073 ); 01074 01075 // if this node were a constructor node, 01076 // then install the subnodes HERE! In example, calling 01077 // gnn_node_sub_install_node_vector ... 01078 01079 // initialize the node sizes 01080 gnn_node_set_sizes (node, input_size, output_size, param_size); 01081 01082 // initialize the rest your node type might need 01083 ... 01084 01085 // finally, return a pointer to the your instance as a gnn_node 01086 return node; 01087 } 01088 01089 \endcode 01090 * 01091 * The \ref gnn_node_init function takes a pointer to the node, a string 01092 * which describes the node type, plus 4 additional functions: 01093 * 01094 * -# The evaluation of the function. (\ref gnn_node_f) 01095 * -# The gradient with respect to the inputs evaluation function. 01096 * (\ref gnn_node_df) 01097 * -# The gradient with respect to the parameters evaluation function. 01098 * (\ref gnn_node_df) 01099 * -# The destructor, which frees the memory. (\ref gnn_node_destructor) 01100 * 01101 * Basically, all these functions have specific datatypes that you should 01102 * respect. All these functions shouldn't access the underlying \ref gnn_node's 01103 * fields <b>ONLY</b> through the Extension API. 01104 * 01105 * <b>Coding Standards</b> 01106 * 01107 * The \ref libgnn library has been coded respecting a coding standard that 01108 * hasn't been documented yet :-) . But basically, you should look at 01109 * its source code and try to code as similar as posible. Some things you 01110 * <b>must</b> respect: 01111 * 01112 * -# Always provide a \c .h and a \c .c file. The first should contain 01113 * the public interface definition, and the second, the implementation. 01114 * Always protect the header file with \c #ifdef construct from multiple 01115 * inclusion. The implementation should depend <b>only</b> on those 01116 * files that it <b>really</b> needs. 01117 * -# Provide all necessary parameter manipulation functions. This is 01118 * very important. Most nodes do have a differente way to view the 01119 * parameters, i.e. not as a single vector, but as a vector and a 01120 * matrix per example. Then, provide function calls to set new 01121 * values and to freeze/unfreeze them. After <b>any</b> manipulation 01122 * of parameters, gradients and/or freeze flags, you should call 01123 * the \ref gnn_node_local_update routine. 01124 * -# Be very carefull when you try to optimize the evaluation routines. 01125 * It is better to take and use only the objects that have been passed 01126 * as arguments. <b>It is a very bad idea to use buffers for speeding up 01127 * the cascade-evaluation of gradients!</b> If the gradients <b>do need</b> 01128 * values that have been computed previously, then <b>recompute them</b>. 01129 * -# Document your heavily! There's nothing worse than undocumented source 01130 * code, or <b>bad</b> documented code. If you don't want to find yourself 01131 * in hell, then provide rich and intelligent documentation. Use the 01132 * Doxygen commands to enhance and format. 01133 * 01134 */ 01135 01136 01137 01138 /** 01139 * @brief Initializes a \ref gnn_node structure. 01140 * @ingroup gnn_node_ext_doc 01141 * 01142 * This function initializes a \ref gnn_node structure. The memory for 01143 * the structure should be allocated manually. The sizes should be set after 01144 * calling this function. 01145 * 01146 * An example of its use is the following: 01147 * 01148 \code 01149 gnn_node * 01150 gnn_mifunction (int input_size, int output_size, int param_size) 01151 { 01152 gnn_node *node; 01153 01154 node = (gnn_node *) malloc (sizeof (*node)); 01155 gnn_node_init ( node, 01156 "gnn_mifunction", 01157 gnn_mifunction_f, 01158 gnn_mifunction_dx, 01159 gnn_mifunction_dw, 01160 gnn_mifunction_dest); 01161 01162 gnn_node_set_sizes (input_size, output_size, param_size); 01163 01164 // initialize the rest 01165 ... 01166 \endcode 01167 * 01168 * If one of the function pointers is NULL, then it installs the 01169 * default functions: 01170 * - \ref gnn_node_default_f for 'f = NULL' 01171 * - \ref gnn_node_default_dedw for 'dedw = NULL' 01172 * - \ref gnn_node_default_dedx for 'dedx = NULL' 01173 * - \ref gnn_node_default_destructor for 'dest = NULL' 01174 * 01175 * @param node A pointer to the node to be initialized. 01176 * @param type A string containing the name of the layer's type. The 01177 * node will build a copy. 01178 * @param f A pointer to the evaluation function. 01179 * @param dx A pointer to the \f$\frac{\partial E}{\partial x}\f$ function. 01180 * @param dw A pointer to the \f$\frac{\partial E}{\partial w}\f$ function. 01181 * @param dest A pointer to the destroy function. 01182 * @return 0 on success. 01183 */ 01184 int 01185 gnn_node_init (gnn_node *node, 01186 const char *type, 01187 gnn_node_f f, 01188 gnn_node_df dx, 01189 gnn_node_df dw, 01190 gnn_node_destructor dest) 01191 { 01192 assert (node != NULL); 01193 01194 /* set fields */ 01195 node->type = strdup (type); 01196 node->n = 0; 01197 node->m = 0; 01198 node->super = NULL; 01199 node->nsub = 0; 01200 node->sub = NULL; 01201 node->f = gnn_node_default_f; 01202 node->dx = gnn_node_default_dx; 01203 node->dw = gnn_node_default_dw; 01204 node->destroy = gnn_node_default_destructor; 01205 01206 /* set parameters */ 01207 node->pb = gnn_pbundle_new (); 01208 node->ph = NULL; 01209 01210 /* set functions */ 01211 if (f != NULL) 01212 node->f = f; 01213 01214 if (dx != NULL) 01215 node->dx = dx; 01216 01217 if (dx != NULL) 01218 node->dw = dw; 01219 01220 if (dest != NULL) 01221 node->destroy = dest; 01222 01223 return 0; 01224 } 01225 01226 /** 01227 * @brief Set the node's sizes. 01228 * @ingroup gnn_node_ext_doc 01229 * 01230 * This function sets the node's sizes for its input, output and parameter 01231 * vector. It should be called after calling the \ref gnn_node_init (and 01232 * the \ref gnn_node_sub_install in case of a constructor node) function. 01233 * 01234 * @warning It is not allowed to call this function twice for the same node. 01235 * 01236 * @param node A pointer to an \ref gnn_node. 01237 * @param n The size of the node's input. 01238 * @param m The size of the node's output. 01239 * @param l The size of the node's parameter vector. 01240 * @return Returns 0 if succeeded. 01241 */ 01242 int 01243 gnn_node_set_sizes (gnn_node *node, int n, int m, int l) 01244 { 01245 assert (node != NULL); 01246 01247 node->n = n; 01248 node->m = m; 01249 01250 /* check if parameters aren't installed yet */ 01251 if (node->ph != NULL) 01252 GSL_ERROR ("parameters are already installed", GSL_EINVAL); 01253 01254 /* set parameters */ 01255 node->ph = gnn_phandle_new (l); 01256 if (l > 0) 01257 gnn_pbundle_insert (node->pb, node->ph, 1); 01258 01259 return 0; 01260 } 01261 01262 /** 01263 * @brief Get local parameters. 01264 * @ingroup gnn_node_ext_doc 01265 * 01266 * This function returns a pointer to the node's own parameters. 01267 * The returning vector is the parameter vector itself and its values can 01268 * be freely changed. When finished, call \ref gnn_node_local_update. 01269 * 01270 * @param node A pointer to an \ref gnn_node. 01271 * @return Returns a pointer to the internal parameter vector \f$w\f$. 01272 */ 01273 gsl_vector * 01274 gnn_node_local_get_w (gnn_node *node) 01275 { 01276 assert (node != NULL); 01277 return gnn_phandle_get_w (node->ph); 01278 } 01279 01280 /** 01281 * @brief Get local parameter gradients. 01282 * @ingroup gnn_node_ext_doc 01283 * 01284 * This function returns a pointer to the node's own parameters gradient 01285 * \f$\frac{\partial E}{\partial w}\f$. 01286 * The returning vector is the gradient itself and its values can 01287 * be freely changed. When finished, call \ref gnn_node_local_update. 01288 * 01289 * @param node A pointer to an \ref gnn_node. 01290 * @return Returns a pointer to the internal 01291 * \f$\frac{\partial E}{\partial w}\f$ vector. 01292 */ 01293 gsl_vector * 01294 gnn_node_local_get_dw (gnn_node *node) 01295 { 01296 assert (node != NULL); 01297 return gnn_phandle_get_dw (node->ph); 01298 } 01299 01300 /** 01301 * @brief Get local parameters frozen flags. 01302 * @ingroup gnn_node_ext_doc 01303 * 01304 * This function returns a pointer to the node's own parameters frozen flags. 01305 * The returning vector is the flags vector itself and its values can be freely 01306 * changed. When finished, call \ref gnn_node_local_update. 01307 * 01308 * The values should be binary: 0 means that the parameter is free, and 01309 * 1 (non-zero) means that the parameter is frozen (fixed). 01310 * 01311 * @param node A pointer to an \ref gnn_node. 01312 * @return Returns a pointer to the internal flags vector. 01313 */ 01314 gsl_vector_int * 01315 gnn_node_local_get_f (gnn_node *node) 01316 { 01317 assert (node != NULL); 01318 return gnn_phandle_get_f (node->ph); 01319 } 01320 01321 /** 01322 * @brief Get local parameters. 01323 * @ingroup gnn_node_ext_doc 01324 * 01325 * This function updates the local parameters and its changes. This function 01326 * should be called after any change in the parameters to make them effective. 01327 * 01328 * @param node A pointer to an \ref gnn_node. 01329 * @return Returns a pointer to the internal parameter vector \f$w\f$. 01330 */ 01331 int 01332 gnn_node_local_update (gnn_node *node) 01333 { 01334 assert (node != NULL); 01335 return gnn_phandle_update (node->ph); 01336 } 01337 01338 /** 01339 * @brief Evaluates the output of the function recursively. 01340 * @ingroup gnn_node_ext_doc 01341 * 01342 * This function calls the installed \ref gnn_node::f function with the 01343 * appropiate arguments. 01344 * 01345 * This function should only be called from construction node's evaluation 01346 * functions. If you want to evaluate it from outside, you should call 01347 * \gnn_node_eval_f instead, which initiates the recursion parameters 01348 * appropiatelly. 01349 * 01350 * @param node A pointer to an \ref gnn_node. 01351 * @param x The input vector to be evaluated. 01352 * @param y A gsl_vector, where the result should be placed. 01353 * @return Returns 0 if suceeded. 01354 */ 01355 int 01356 gnn_node_eval_f (gnn_node *node, const gsl_vector *x, gsl_vector *y) 01357 { 01358 int status; 01359 01360 assert (node != NULL); 01361 01362 /* set pointer to last input */ 01363 node->x = *x; 01364 01365 /* call evaluation */ 01366 status = node->f (node, &(node->x), gnn_phandle_get_w (node->ph), y); 01367 if (status) 01368 GSL_ERROR ("error computing y", GSL_ERANGE); 01369 01370 return 0; 01371 } 01372 01373 /** 01374 * @brief Evaluates \f$\frac{\partial E}{\partial x}\f$ recursively. 01375 * @ingroup gnn_node_ext_doc 01376 * 01377 * This function calls the installed \ref gnn_node::dx function with the 01378 * appropiate arguments. 01379 * 01380 * This function should only be called from construction node's evaluation 01381 * functions. If you want to evaluate it from outside, you should call 01382 * \gnn_node_eval_dx instead, which initiates the recursion parameters 01383 * appropiatelly. 01384 * 01385 * @param node A pointer to an \ref gnn_node. 01386 * @param dx A gsl_vector, where the result should be placed. 01387 * @return Returns 0 if suceeded. 01388 */ 01389 int 01390 gnn_node_eval_dx (gnn_node *node, const gsl_vector *dy, gsl_vector *dx) 01391 { 01392 int status; 01393 01394 assert (node != NULL); 01395 01396 /* set pointer to last input */ 01397 node->dy = *dy; 01398 01399 /* compute input gradient */ 01400 status = node->dx (node, 01401 &(node->x), 01402 gnn_phandle_get_w (node->ph), 01403 &(node->dy), 01404 dx); 01405 if (status) 01406 GSL_ERROR ("error computing dw", GSL_ERANGE); 01407 01408 return 0; 01409 } 01410 01411 /** 01412 * @brief Evaluates \f$\frac{\partial E}{\partial w}\f$ recursively. 01413 * @ingroup gnn_node_ext_doc 01414 * 01415 * This function calls the installed \ref gnn_node::dw function with the 01416 * appropiate arguments. 01417 * 01418 * This function should only be called from construction node's evaluation 01419 * functions. If you want to evaluate it from outside, you should call 01420 * \gnn_node_eval_dw instead, which initiates the recursion parameters 01421 * appropiatelly. 01422 * 01423 * @param node A pointer to an \ref gnn_node. 01424 * @return Returns 0 if suceeded. 01425 */ 01426 int 01427 gnn_node_eval_dw (gnn_node *node) 01428 { 01429 int status; 01430 01431 assert (node != NULL); 01432 01433 /* if there aren't any free parameters, 01434 and the node is a leaf, return */ 01435 if (node->sub == NULL && gnn_phandle_get_free (node->ph) == 0) 01436 return 0; 01437 01438 /* compute parameter gradient */ 01439 status = node->dw (node, 01440 &(node->x), 01441 gnn_phandle_get_w (node->ph), 01442 &(node->dy), 01443 gnn_phandle_get_dw (node->ph)); 01444 01445 if (status) 01446 GSL_ERROR ("error computing dw", GSL_ERANGE); 01447 01448 return 0; 01449 } 01450 01451 01452 01453 /****************/ 01454 /* Subnodes API */ 01455 /****************/ 01456 01457 /** 01458 * @brief The API for connecting and traversing trees of nodes. 01459 * @defgroup gnn_node_sub_doc gnn_node Subnodes API 01460 * @ingroup gnn_node_doc 01461 * 01462 * This API provides the functionality for connecting and traversing 01463 * \ref gnn_node trees. 01464 * 01465 * Every \ref gnn_node can be connected to another node, forming a node tree. 01466 * A node can have a single parent node, called "supernode", and can also 01467 * have several children nodes, called "subnodes" in \ref libgnn. 01468 * 01469 * A node that contains subnodes is a node that computes a function whose 01470 * output depends on the result of each of the subnode's functions. Per 01471 * example, a \ref gnn_stack node is a special node who computes the 01472 * composition of each of its subnode's functions. 01473 * 01474 * In general, nodes that can have subnodes rarely have own parameters. 01475 * In \ref libgnn, these nodes are called "constructor" nodes, due to its 01476 * nature. 01477 * 01478 * Leaf nodes, that is, nodes that can't have subnodes (because it wouldn't 01479 * make any sense for them) are called "atomic" nodes, because they can't 01480 * be splitted into simpler nodes. 01481 * 01482 * There are several alternatives to install subnodes. The recommended scheme 01483 * is the following. First, declare a function with variable number of 01484 * arguments, that takes the \ref gnn_node to be installed. Then, call 01485 * the \ref gnn_node_sub_install function, like in this example code: 01486 * 01487 * \code 01488 // include the header file for variable 01489 // number of function arguments 01490 #include <stdarg.h> 01491 01492 ... 01493 01494 // Constructor for my own node type 01495 int 01496 gnn_mynode_new (int amount_subnodes, ...) 01497 { 01498 va_list argptr; // special data type for argument list 01499 int status; 01500 01501 va_start (argptr, amount_subnodes); 01502 status = gnn_node_sub_install (node, amount_subnodes, argptr); 01503 va_end (argptr); 01504 01505 // do the rest 01506 ... 01507 * \endcode 01508 * 01509 * Once installed, a subnode at the i-th index can be recovered by calling the 01510 * \ref gnn_node_sub_get_node_at function. 01511 * 01512 * When destroying a node with \ref gnn_node_destroy, its subnodes are 01513 * automatically uninstalled. 01514 */ 01515 01516 01517 /** 01518 * @brief Install subnodes. 01519 * @ingroup gnn_node_sub_doc 01520 * 01521 * This function installs the given nodes as subnodes. 01522 * 01523 * @param node A pointer to an \ref gnn_node. 01524 * @param nsub The number of subnodes. 01525 * @param ... A list of subnodes to be installed. 01526 * @return Returns 0 if suceeded. 01527 */ 01528 int 01529 gnn_node_sub_install_specific (gnn_node *node, int nsub, ...) 01530 { 01531 va_list argptr; 01532 int status; 01533 01534 assert (node != NULL); 01535 01536 va_start (argptr, nsub); 01537 status = gnn_node_sub_install (node, nsub, argptr); 01538 va_end (argptr); 01539 01540 return status; 01541 } 01542 01543 /** 01544 * @brief Install subnodes. 01545 * @ingroup gnn_node_sub_doc 01546 * 01547 * This function installs the given nodes as subnodes. 01548 * 01549 * @param node A pointer to an \ref gnn_node. 01550 * @param nsub The number of subnodes in the list. 01551 * @param subs A va_list (C Standard Library) containing pointers to the 01552 * subnodes to be installed. 01553 * @return Returns 0 if suceeded. 01554 */ 01555 int 01556 gnn_node_sub_install (gnn_node *node, int nsub, va_list subs) 01557 { 01558 int i; 01559 gnn_node *ptr; 01560 01561 assert (node != NULL); 01562 assert (nsub > 0); 01563 01564 /* create node array */ 01565 node->sub = (gnn_node **) calloc (sizeof (gnn_node *), nsub); 01566 if (node->sub == NULL) 01567 GSL_ERROR ("failed to create subnode array", GSL_ENOMEM); 01568 01569 /* set number of subnodes */ 01570 node->nsub = nsub; 01571 01572 /* fill subnode array */ 01573 for (i=0; i<nsub; ++i) 01574 { 01575 /* get the node from the parameter list */ 01576 node->sub[i] = (gnn_node *) va_arg (subs, gnn_node *); 01577 01578 if (node->sub[i] == NULL) 01579 GSL_ERROR ("error installing subnodes", GSL_EINVAL); 01580 01581 /* set the "super" pointer */ 01582 node->sub[i]->super = node; 01583 01584 /* merge parameter bundles */ 01585 gnn_pbundle_join (node->pb, node->sub[i]->pb); 01586 } 01587 01588 return 0; 01589 } 01590 01591 /** 01592 * @brief Install the nodes in the node vector as subnodes. 01593 * @ingroup gnn_node_sub_doc 01594 * 01595 * This function installs the non-NULL nodes in the node vector as subnodes. 01596 * 01597 * @param node A pointer to an \ref gnn_node. 01598 * @param vector A pointer to a \ref gnn_node_vector. 01599 * @return Returns 0 if suceeded. 01600 */ 01601 int 01602 gnn_node_sub_install_node_vector (gnn_node *node, gnn_node_vector *vector) 01603 { 01604 size_t i; 01605 size_t j; 01606 size_t count; 01607 gnn_node *ptr; 01608 01609 assert (node != NULL); 01610 01611 /* count the number of non-null nodes */ 01612 count = gnn_node_vector_count_nodes (vector); 01613 01614 if (count < 1) 01615 GSL_ERROR ("the given vector doesn't contain any valid gnn_node", 01616 GSL_EINVAL); 01617 01618 /* create node array */ 01619 node->sub = (gnn_node **) calloc (sizeof (gnn_node *), count); 01620 if (node->sub == NULL) 01621 GSL_ERROR ("failed to create subnode array", GSL_ENOMEM); 01622 01623 /* set number of subnodes */ 01624 node->nsub = count; 01625 01626 /* fill subnode array */ 01627 j = 0; 01628 for (i=0; i<vector->size; ++i) 01629 { 01630 /* check if there is a valid node */ 01631 if (gnn_node_vector_get (vector, i) == NULL) 01632 continue; 01633 01634 /* get node and install */ 01635 node->sub[j] = gnn_node_vector_get (vector, i); 01636 01637 /* set the "super" pointer */ 01638 node->sub[j]->super = node; 01639 01640 /* merge parameter bundles */ 01641 gnn_pbundle_join (node->pb, node->sub[j]->pb); 01642 01643 /* advance to next subnode element */ 01644 j++; 01645 } 01646 01647 return 0; 01648 } 01649 01650 01651 /** 01652 * @brief Get the number of subnodes. 01653 * @ingroup gnn_node_sub_doc 01654 * 01655 * This function returns the number of direct subnodes of the node. 01656 * 01657 * @param node A pointer to an \ref gnn_node. 01658 * @return Returns the number of subnodes. 01659 */ 01660 int 01661 gnn_node_sub_get_number (gnn_node *node) 01662 { 01663 assert (node != NULL); 01664 return node->nsub; 01665 } 01666 01667 /** 01668 * @brief Get's the node's i-th subnode. 01669 * @ingroup gnn_node_sub_doc 01670 * 01671 * This function returns a pointer to the i-th subnode. 01672 * 01673 * @param node A pointer to an \ref gnn_node. 01674 * @param i The index of the subnode to be retrieved. 01675 * @return The pointer to the i-th subnode or NULL if failed. 01676 */ 01677 gnn_node * 01678 gnn_node_sub_get_node_at (gnn_node *node, int i) 01679 { 01680 assert (node != NULL); 01681 assert (node->sub != NULL); 01682 assert (0 <= i && i < node->nsub); 01683 01684 return node->sub[i]; 01685 } 01686 01687 /** 01688 * @brief Get all subnodes of a given type. 01689 * @ingroup gnn_node_sub_doc 01690 * 01691 * This function searches the whole node three for nodes of the given type, 01692 * and returns a parameter bundle of all their parameters. 01693 * 01694 * @param node A pointer to an \ref gnn_node. 01695 * @param type A string containing the type of the subnodes to be retrieved. 01696 * @return A \ref gnn_pbundle. 01697 */ 01698 gnn_pbundle * 01699 gnn_node_sub_search_params (gnn_node *node, const char *type) 01700 { 01701 gnn_pbundle *pb; 01702 01703 assert (node != NULL); 01704 01705 /* create new parameter bundle */ 01706 pb = gnn_pbundle_new (); 01707 01708 /* call recursive function */ 01709 gnn_node_sub_search_params_recurse (node, type, pb); 01710 01711 return pb; 01712 } 01713 01714 01715 01716
1.2.18