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

gnn_gaussian.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *  @file gnn_gaussian.c
00003  *  @brief Gaussian Kernel transfer function.
00004  *
00005  *  @date   : 18-09-03 10:33
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  * @defgroup gnn_gaussian_doc gnn_gaussian : Gaussian Kernel Activation Function.
00027  * @ingroup gnn_atomic_doc
00028  *
00029  * This node type implements a Gaussian Kernel activation function given
00030  * by:
00031  * \f[ y_i = a_i e^{-\frac{x_i^2}{v_i}} \f]
00032  * where the index \f$i = 1,\ldots,n\f$ runs over all inputs / outputs, and
00033  * \f$v_i = \sigma_i^2\f$
00034  *
00035  * This function is a member of the more general class of kernel functions.
00036  * They are intended to work in combination with a prototype node
00037  * (\ref gnn_prototype).
00038  *
00039  * The function's gradients are:
00040  * \f[ \frac{\partial E}{\partial x_i}
00041  *     = - \frac{2 x_i y_i}{v_i} \frac{\partial E}{\partial y_i}
00042  * \f]
00043  * with respect to its inputs, and
00044  * \f[ \frac{\partial E}{\partial a_i}
00045  *     = \frac{y_i}{a_i} \frac{\partial E}{\partial y_i}
00046  * \f]
00047  * \f[ \frac{\partial E}{\partial v_i}
00048  *     = \frac{x_i^2 y_i}{v_i^2} \frac{\partial E}{\partial y_i}
00049  * \f]
00050  * with respect to its parameters.
00051  */
00052 
00053 
00054 /******************************************/
00055 /* Include Files                          */
00056 /******************************************/
00057 
00058 #include "gnn_gaussian.h"
00059 #include <math.h>
00060 
00061 
00062 
00063 /******************************************/
00064 /* Static Declaration                     */
00065 /******************************************/
00066 
00067 static int
00068 gnn_gaussian_f (gnn_node *node,
00069                 const gsl_vector *x,
00070                 const gsl_vector *w,
00071                 gsl_vector *y);
00072 
00073 static int
00074 gnn_gaussian_dx (gnn_node *node,
00075                  const gsl_vector *x,
00076                  const gsl_vector *w,
00077                  const gsl_vector *dy,
00078                  gsl_vector *dx);
00079 
00080 static int
00081 gnn_gaussian_dw (gnn_node *node,
00082                  const gsl_vector *x,
00083                  const gsl_vector *w,
00084                  const gsl_vector *dy,
00085                  gsl_vector *dw);
00086 
00087 static void
00088 gnn_gaussian_destroy (gnn_node *node);
00089 
00090 
00091 
00092 /******************************************/
00093 /* Static Implementation                  */
00094 /******************************************/
00095 
00096 /**
00097  * @brief Computes the output.
00098  * @ingroup gnn_gaussian_doc
00099  *
00100  * This functions evaluates the Gaussian Kernel activation function.
00101  *
00102  * @param   node A pointer to the \ref gnn_gaussian node.
00103  * @param x The input vector \f$x\f$.
00104  * @param w The parameter vector \f$w\f$.
00105  * @param y The output buffer vector \f$y\f$.
00106  * @return Returns 0 on success.
00107  */
00108 static int
00109 gnn_gaussian_f (gnn_node *node,
00110                 const gsl_vector *x,
00111                 const gsl_vector *w,
00112                 gsl_vector *y)
00113 {
00114     size_t i;
00115     size_t size;
00116     gnn_gaussian *gnode;
00117 
00118     /* get the size */
00119     size = gnn_node_input_get_size (node);
00120 
00121     /* get views */
00122     gnode = (gnn_gaussian *) node;
00123 
00124     /* evaluate */
00125     for (i=0; i<size; ++i)
00126     {
00127         double xi;
00128         double yi;
00129         double ai;
00130         double vi;
00131 
00132         xi  = gsl_vector_get (x, i);
00133         ai  = gsl_vector_get (gnode->a, i);
00134         vi  = gsl_vector_get (gnode->v, i);
00135         yi  = ai * exp (- xi * xi / vi);
00136         gsl_vector_set (gnode->y, i, yi);
00137     }
00138     /* copy to outputs */
00139     gsl_vector_memcpy (y, gnode->y);
00140 
00141     return 0;
00142 }
00143 
00144 /**
00145  * @brief Computes \f$ \frac{\partial E}{\partial x} \f$.
00146  * @ingroup gnn_gaussian_doc
00147  *
00148  * This functions computes the gradient with respect to the inputs of the
00149  * Gaussian Kernel function.
00150  *
00151  * @param    node A pointer to the \ref gnn_gaussian node.
00152  * @param x  The input vector \f$x\f$.
00153  * @param w  The parameter vector \f$w\f$.
00154  * @param dy The vector \f$\frac{\partial E}{\partial y}\f$.
00155  * @param dx The output buffer vector \f$\frac{\partial E}{\partial x}\f$.
00156  * @return Returns 0 on success.
00157  */
00158 static int
00159 gnn_gaussian_dx (gnn_node *node,
00160                  const gsl_vector *x,
00161                  const gsl_vector *w,
00162                  const gsl_vector *dy,
00163                  gsl_vector *dx)
00164 {
00165     size_t i;
00166     size_t size;
00167     gnn_gaussian *gnode;
00168 
00169     /* get the size */
00170     size = gnn_node_input_get_size (node);
00171 
00172     /* get views */
00173     gnode = (gnn_gaussian *) node;
00174 
00175     /* evaluate */
00176     for (i=0; i<size; ++i)
00177     {
00178         double xi;
00179         double yi;
00180         double vi;
00181         double dxi;
00182         double dyi;
00183 
00184         xi  = gsl_vector_get (x, i);
00185         yi  = gsl_vector_get (gnode->y, i);
00186         vi  = gsl_vector_get (gnode->v, i);
00187         //dxi = gsl_vector_get (dx, i);
00188         dyi = gsl_vector_get (dy, i);
00189 
00190         //dxi += - 2 * xi * yi / vi * dyi;
00191         dxi = - 2 * xi * yi / vi * dyi;
00192         gsl_vector_set (dx, i, dxi);
00193     }
00194 
00195     return 0;
00196 }
00197 
00198 /**
00199  * @brief Computes \f$ \frac{\partial E}{\partial w} \f$.
00200  * @ingroup gnn_gaussian_doc
00201  *
00202  * This functions computes the gradient with respect to the parameters of the
00203  * Gaussian Kernel function. That is, it computes
00204  * \f$\frac{\partial E}{\partial a_i}\f$ and
00205  * \f$\frac{\partial E}{\partial v_i}\f$.
00206  *
00207  * @param    node A pointer to the \ref gnn_gaussian node.
00208  * @param x  The input vector \f$x\f$.
00209  * @param w  The parameter vector \f$w\f$.
00210  * @param dy The vector \f$\frac{\partial E}{\partial y}\f$.
00211  * @param dx The output buffer vector \f$\frac{\partial E}{\partial w}\f$.
00212  * @return Returns 0 on success.
00213  */
00214 static int
00215 gnn_gaussian_dw (gnn_node *node,
00216                  const gsl_vector *x,
00217                  const gsl_vector *w,
00218                  const gsl_vector *dy,
00219                  gsl_vector *dw)
00220 {
00221     size_t i;
00222     size_t size;
00223     gnn_gaussian *gnode;
00224 
00225     /* get the size */
00226     size = gnn_node_input_get_size (node);
00227 
00228     /* get views */
00229     gnode = (gnn_gaussian *) node;
00230 
00231     /* evaluate */
00232     for (i=0; i<size; ++i)
00233     {
00234         double xi;
00235         double yi;
00236         double ai;
00237         double vi;
00238         double dyi;
00239         double dai;
00240         double dvi;
00241 
00242         xi  = gsl_vector_get (x, i);
00243         yi  = gsl_vector_get (gnode->y, i);
00244         ai  = gsl_vector_get (gnode->a, i);
00245         vi  = gsl_vector_get (gnode->v, i);
00246         dyi = gsl_vector_get (dy, i);
00247         dai = gsl_vector_get (gnode->da, i);
00248         dvi = gsl_vector_get (gnode->dv, i);
00249 
00250         dai += (yi / ai) * dyi;
00251         dvi += (xi * xi * yi / (vi * vi)) * dyi;
00252 
00253         gsl_vector_set (gnode->da, i, dai);
00254         gsl_vector_set (gnode->dv, i, dvi);
00255     }
00256 
00257     return 0;
00258 }
00259 
00260 /**
00261  * @brief Computes the output.
00262  * @ingroup gnn_gaussian_doc
00263  *
00264  * This is the destructor for a \ref gnn_gaussian node.
00265  *
00266  * @param   node A pointer to the \ref gnn_gaussian node.
00267  */
00268 static void
00269 gnn_gaussian_destroy (gnn_node *node)
00270 {
00271     gnn_gaussian *gnode;
00272 
00273     gnode = (gnn_gaussian *) node;
00274     
00275     if (gnode->y != NULL)
00276         gsl_vector_free (gnode->y);
00277 }
00278 
00279 
00280 
00281 /******************************************/
00282 /* Public Interface                       */
00283 /******************************************/
00284 
00285 /**
00286  * @brief Creates a Gaussian Kernel Activation Function node.
00287  * @ingroup gnn_gaussian_doc
00288  *
00289  * This function creates a node of the gnn_gaussian type. All kernels are
00290  * initialized with the same amplitude and variance.
00291  *
00292  * @param input_size The input size \f$n\f$.
00293  * @param a The \f$a\f$ (amplitude) factor.
00294  * @param v The variance \f$\sigma^2\f$.
00295  * @return A pointer to a new \ref gnn_divergence node.
00296  */
00297 gnn_node *
00298 gnn_gaussian_new (int input_size, double a, double v)
00299 {
00300     int status;
00301     gnn_node *node;
00302     gnn_gaussian *gnode;
00303     gsl_vector *w;
00304     gsl_vector *dw;
00305     gsl_vector_int *f;
00306 
00307     /* check if sizes are positive */
00308     if (input_size < 1)
00309     {
00310         GSL_ERROR_VAL ("input size should be strictly positive",
00311                        GSL_EINVAL, NULL);
00312     }
00313     
00314     /* check amplitude */
00315     if (a <= 0.0)
00316     {
00317         GSL_ERROR_VAL ("amplitude factor a should be stricly positive",
00318                        GSL_EINVAL, NULL);
00319     }
00320 
00321     /* check variance */
00322     if (v <= 0.0)
00323     {
00324         GSL_ERROR_VAL ("variance factor a should be stricly positive",
00325                        GSL_EINVAL, NULL);
00326     }
00327 
00328     /* allocate the node */
00329     gnode = (gnn_gaussian *) malloc (sizeof (gnn_gaussian));
00330     if (gnode == NULL)
00331     {
00332         GSL_ERROR_VAL ("could not allocate memory for gnn_gaussian node",
00333                        GSL_ENOMEM, NULL);
00334     }
00335     
00336     /* get view as a gnn_node */
00337     node = (gnn_node *) gnode;
00338 
00339     /* Initialize the node */
00340     status = gnn_node_init (node,
00341                             "gnn_gaussian",
00342                             gnn_gaussian_f,
00343                             gnn_gaussian_dx,
00344                             gnn_gaussian_dw,
00345                             gnn_gaussian_destroy);
00346     if (status)
00347     {
00348         GSL_ERROR_VAL ("could not initialize gnn_gaussian node",
00349                        GSL_EFAILED, NULL);
00350     }
00351 
00352     status = gnn_node_set_sizes (node, input_size, input_size, 2 * input_size);
00353     if (status)
00354     {
00355         GSL_ERROR_VAL ("could not set sizes for gnn_gaussian node",
00356                        GSL_EFAILED, NULL);
00357     }
00358 
00359     /* create buffer */
00360     gnode->y = gsl_vector_alloc (input_size);
00361     if (gnode->y == NULL)
00362     {
00363         gnn_node_destroy (node);
00364         GSL_ERROR_VAL ("could not allocate buffer for gnn_gaussian node",
00365                        GSL_ENOMEM, NULL);
00366     }
00367 
00368     /* get parameter views */
00369     w  = gnn_node_local_get_w (node);
00370     dw = gnn_node_local_get_dw (node);
00371     f  = gnn_node_local_get_f (node);
00372     
00373     gnode->a_view  = gsl_vector_subvector (w,  0, input_size);
00374     gnode->da_view = gsl_vector_subvector (dw, 0, input_size);
00375     gnode->af_view = gsl_vector_int_subvector (f, 0, input_size);
00376                                            
00377     gnode->v_view  = gsl_vector_subvector (w, input_size, input_size);
00378     gnode->dv_view = gsl_vector_subvector (dw, input_size, input_size);
00379     gnode->vf_view = gsl_vector_int_subvector (f, input_size, input_size);
00380 
00381     gnode->a  = &(gnode->a_view.vector);
00382     gnode->da = &(gnode->da_view.vector);
00383     gnode->af = &(gnode->af_view.vector);
00384 
00385     gnode->v  = &(gnode->v_view.vector);
00386     gnode->dv = &(gnode->dv_view.vector);
00387     gnode->vf = &(gnode->vf_view.vector);
00388 
00389     /* initialize values */
00390     gsl_vector_set_all (gnode->a, a);
00391     gsl_vector_set_all (gnode->v, v);
00392 
00393     /* update parameters */
00394     gnn_node_local_update (node);
00395     
00396     return node;
00397 }
00398 
00399 /**
00400  * @brief Creates a standard Gaussian Kernel Activation Function node.
00401  * @ingroup gnn_gaussian_doc
00402  *
00403  * This function creates a node of the gnn_gaussian type. All kernels are
00404  * initialized with amplitude \f$a_i = 1\f$ and variance \f$v_i = 1\f$.
00405  *
00406  * @param input_size The input size \f$n\f$.
00407  * @return A pointer to a new \ref gnn_tanh node.
00408  */
00409 gnn_node *
00410 gnn_gaussian_standard_new (int input_size)
00411 {
00412     return gnn_gaussian_new (input_size, 1.0, 1.0);
00413 }
00414 

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