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

gnn_affine.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *  @file gnn_affine.c
00003  *  @brief gnn_affine Implementation.
00004  *
00005  *  @date   : 05-10-03 11:56
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_affine_doc gnn_affine : Affine Activation Function.
00027  * @ingroup gnn_atomic_doc
00028  *
00029  * This node type implements an Affine activatino function given by:
00030  *
00031  * \f[ y_i = a_i x_i + b_i \f]
00032  *
00033  * where the index \f$i = 1,\ldots,n\f$ runs over all inputs / outputs.
00034  * The amplitude factors \f$a_i\f$ and the biases \f$b_i\f$ are independent
00035  * and can be trained. Usually, this activation function is placed after
00036  * a non-linear activation function which is limited in its output range,
00037  * like a gaussian, logistic sigmoid or a hyperbolic tangent activation
00038  * function, to scale the outputs to the correct magnitudes.
00039  *
00040  * The function's gradients are:
00041  * \f[ \frac{\partial E}{\partial x_i}
00042  *     = a_i \frac{\partial E}{\partial y_i}
00043  * \f]
00044  * with respect to its inputs, and
00045  * \f[ \frac{\partial E}{\partial a_i}
00046  *     = x_i \frac{\partial E}{\partial y_i}
00047  * \f]
00048  * \f[ \frac{\partial E}{\partial b_i}
00049  *     = \frac{\partial E}{\partial y_i}
00050  * \f]
00051  * with respect to its parameters.
00052  */
00053 
00054 
00055 /******************************************/
00056 /* Include Files                          */
00057 /******************************************/
00058 
00059 #include "gnn_affine.h"
00060 #include <math.h>
00061 
00062 
00063 
00064 /******************************************/
00065 /* Static Declaration                     */
00066 /******************************************/
00067 
00068 static int
00069 gnn_affine_f (gnn_node *node,
00070                 const gsl_vector *x,
00071                 const gsl_vector *w,
00072                 gsl_vector *y);
00073 
00074 static int
00075 gnn_affine_dx (gnn_node *node,
00076                  const gsl_vector *x,
00077                  const gsl_vector *w,
00078                  const gsl_vector *dy,
00079                  gsl_vector *dx);
00080 
00081 static int
00082 gnn_affine_dw (gnn_node *node,
00083                  const gsl_vector *x,
00084                  const gsl_vector *w,
00085                  const gsl_vector *dy,
00086                  gsl_vector *dw);
00087 
00088 static void
00089 gnn_affine_destroy (gnn_node *node);
00090 
00091 
00092 
00093 /******************************************/
00094 /* Static Implementation                  */
00095 /******************************************/
00096 
00097 /**
00098  * @brief Computes the output.
00099  * @ingroup gnn_affine_doc
00100  *
00101  * @param   node A pointer to the \ref gnn_affine node.
00102  * @param x The input vector \f$x\f$.
00103  * @param w The parameter vector \f$w\f$.
00104  * @param y The output buffer vector \f$y\f$.
00105  * @return Returns 0 on success.
00106  */
00107 static int
00108 gnn_affine_f (gnn_node *node,
00109               const gsl_vector *x,
00110               const gsl_vector *w,
00111               gsl_vector *y)
00112 {
00113     size_t i;
00114     size_t size;
00115     gnn_affine *anode;
00116 
00117     /* get the size */
00118     size = gnn_node_input_get_size (node);
00119 
00120     /* get views */
00121     anode = (gnn_affine *) node;
00122 
00123     /* evaluate */
00124     gsl_vector_memcpy (y, x);
00125     gsl_vector_mul (y, anode->a);
00126     gsl_vector_add (y, anode->b);
00127 
00128     return 0;
00129 }
00130 
00131 /**
00132  * @brief Computes \f$ \frac{\partial E}{\partial x} \f$.
00133  * @ingroup gnn_affine_doc
00134  *
00135  * @param    node A pointer to the \ref gnn_affine node.
00136  * @param x  The input vector \f$x\f$.
00137  * @param w  The parameter vector \f$w\f$.
00138  * @param dy The vector \f$\frac{\partial E}{\partial y}\f$.
00139  * @param dx The output buffer vector \f$\frac{\partial E}{\partial x}\f$.
00140  * @return Returns 0 on success.
00141  */
00142 static int
00143 gnn_affine_dx (gnn_node *node,
00144                  const gsl_vector *x,
00145                  const gsl_vector *w,
00146                  const gsl_vector *dy,
00147                  gsl_vector *dx)
00148 {
00149     size_t i;
00150     size_t size;
00151     gnn_affine *anode;
00152 
00153     /* get the size */
00154     size = gnn_node_input_get_size (node);
00155 
00156     /* get views */
00157     anode = (gnn_affine *) node;
00158 
00159     /* evaluate */
00160     gsl_vector_memcpy (dx, anode->a);
00161     gsl_vector_mul (dx, dy);
00162 
00163     return 0;
00164 }
00165 
00166 /**
00167  * @brief Computes \f$ \frac{\partial E}{\partial w} \f$.
00168  * @ingroup gnn_affine_doc
00169  *
00170  * @param    node A pointer to the \ref gnn_affine node.
00171  * @param x  The input vector \f$x\f$.
00172  * @param w  The parameter vector \f$w\f$.
00173  * @param dy The vector \f$\frac{\partial E}{\partial y}\f$.
00174  * @param dx The output buffer vector \f$\frac{\partial E}{\partial w}\f$.
00175  * @return Returns 0 on success.
00176  */
00177 static int
00178 gnn_affine_dw (gnn_node *node,
00179                  const gsl_vector *x,
00180                  const gsl_vector *w,
00181                  const gsl_vector *dy,
00182                  gsl_vector *dw)
00183 {
00184     size_t i;
00185     size_t size;
00186     gnn_affine *anode;
00187 
00188     /* get the size */
00189     size = gnn_node_input_get_size (node);
00190 
00191     /* get views */
00192     anode = (gnn_affine *) node;
00193 
00194     /* evaluate */
00195     gsl_vector_memcpy (anode->buf, x);
00196     gsl_vector_mul (anode->buf, dy);
00197     gsl_vector_add (anode->da, anode->buf);
00198     
00199     gsl_vector_add (anode->db, dy);
00200 
00201     return 0;
00202 }
00203 
00204 /**
00205  * @brief Destructor function.
00206  * @ingroup gnn_affine_doc
00207  *
00208  * @param node A pointer to the \ref gnn_affine node.
00209  */
00210 static void
00211 gnn_affine_destroy (gnn_node *node)
00212 {
00213     gnn_affine *anode;
00214 
00215     anode = (gnn_affine *) node;
00216 
00217     if (anode->buf != NULL)
00218         gsl_vector_free (anode->buf);
00219 }
00220 
00221 
00222 
00223 /******************************************/
00224 /* Public Interface                       */
00225 /******************************************/
00226 
00227 /**
00228  * @brief Creates an Affine Activation Function node.
00229  * @ingroup gnn_affine_doc
00230  *
00231  * This function creates a node of the gnn_affine type. Although the parameters
00232  * \f$a_i\f$ and \f$b_i\f$, \f$i=1,\ldots,n=m\f$ are all equal initially, they
00233  * change during training.
00234  *
00235  * @param input_size The input size \f$n\f$.
00236  * @param a The \f$a_i\f$ (amplitude) factors.
00237  * @param v The biases \f$b_i\f$.
00238  * @return A pointer to a new \ref gnn_divergence node.
00239  */
00240 gnn_node *
00241 gnn_affine_new (int input_size, double a, double b)
00242 {
00243     int status;
00244     gnn_node *node;
00245     gnn_affine *anode;
00246     gsl_vector *w;
00247     gsl_vector *dw;
00248     gsl_vector_int *f;
00249 
00250     /* check if sizes are positive */
00251     if (input_size < 1)
00252     {
00253         GSL_ERROR_VAL ("input size should be strictly positive",
00254                        GSL_EINVAL, NULL);
00255     }
00256 
00257     /* check amplitude */
00258     if (a <= 0.0)
00259     {
00260         GSL_ERROR_VAL ("amplitude factor a should be stricly positive",
00261                        GSL_EINVAL, NULL);
00262     }
00263 
00264     /* allocate the node */
00265     anode = (gnn_affine *) malloc (sizeof (gnn_affine));
00266     if (anode == NULL)
00267     {
00268         GSL_ERROR_VAL ("could not allocate memory for gnn_affine node",
00269                        GSL_ENOMEM, NULL);
00270     }
00271 
00272     /* get view as a gnn_node */
00273     node = (gnn_node *) anode;
00274 
00275     /* Initialize the node */
00276     status = gnn_node_init (node,
00277                             "gnn_affine",
00278                             gnn_affine_f,
00279                             gnn_affine_dx,
00280                             gnn_affine_dw,
00281                             NULL);
00282     if (status)
00283     {
00284         GSL_ERROR_VAL ("could not initialize gnn_affine node",
00285                        GSL_EFAILED, NULL);
00286     }
00287 
00288     status = gnn_node_set_sizes (node, input_size, input_size, 2 * input_size);
00289     if (status)
00290     {
00291         GSL_ERROR_VAL ("could not set sizes for gnn_affine node",
00292                        GSL_EFAILED, NULL);
00293     }
00294 
00295     /* create buffer */
00296     anode->buf = gsl_vector_alloc (input_size);
00297     if (anode->buf == NULL)
00298     {
00299         gnn_node_destroy (node);
00300         GSL_ERROR_VAL ("could not allocate buffer for gnn_affine node",
00301                        GSL_ENOMEM, NULL);
00302     }
00303 
00304     /* get parameter views */
00305     w  = gnn_node_local_get_w (node);
00306     dw = gnn_node_local_get_dw (node);
00307     f  = gnn_node_local_get_f (node);
00308 
00309     anode->a_view  = gsl_vector_subvector (w,  0, input_size);
00310     anode->da_view = gsl_vector_subvector (dw, 0, input_size);
00311     anode->af_view = gsl_vector_int_subvector (f, 0, input_size);
00312 
00313     anode->b_view  = gsl_vector_subvector (w, input_size, input_size);
00314     anode->db_view = gsl_vector_subvector (dw, input_size, input_size);
00315     anode->bf_view = gsl_vector_int_subvector (f, input_size, input_size);
00316 
00317     anode->a  = &(anode->a_view.vector);
00318     anode->da = &(anode->da_view.vector);
00319     anode->af = &(anode->af_view.vector);
00320 
00321     anode->b  = &(anode->b_view.vector);
00322     anode->db = &(anode->db_view.vector);
00323     anode->bf = &(anode->bf_view.vector);
00324 
00325     /* initialize values */
00326     gsl_vector_set_all (anode->a, a);
00327     gsl_vector_set_all (anode->b, b);
00328 
00329     /* update parameters */
00330     gnn_node_local_update (node);
00331 
00332     return node;
00333 }
00334 
00335 /**
00336  * @brief Creates a standard Affine Activation Function node.
00337  * @ingroup gnn_affine_doc
00338  *
00339  * This function creates a node of the gnn_affine type. The parameters
00340  * are initialized with amplitudes \f$a_i = 1\f$ and biases \f$b_i = 0\f$.
00341  *
00342  * @param input_size The input size \f$n\f$.
00343  * @return A pointer to a new \ref gnn_tanh node.
00344  */
00345 gnn_node *
00346 gnn_affine_standard_new (int input_size)
00347 {
00348     return gnn_affine_new (input_size, 1.0, 0.0);
00349 }
00350 
00351 

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