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

gnn_softmax.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *  @file gnn_mse.h
00003  *  @brief Softmax Activation Function.
00004  *
00005  *  @date   : 03-09-03 20:41
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_softmax_doc gnn_softmax : Softmax Activation Function.
00027  * @ingroup gnn_atomic_doc
00028  *
00029  * The \ref gnn_softmax datatype implements a node that computes the function:
00030  * \f[ y_i = \frac{ \exp(x_i) }{ \sum_k^n \exp(x_k) } \f]
00031  * where \f$i = 1,\ldots,n\f$.
00032  *
00033  * The different outputs \f$y_i\f$ of the softmax function are normalized:
00034  * they sum all up to 1. Softmax outputs lie in the interval \f$[0;1]\f$, and
00035  * they can be interpreted as probabilities.
00036  *
00037  * @warning This node should be fed with small values.
00038  */
00039 
00040 
00041 
00042 /******************************************/
00043 /* Include Files                          */
00044 /******************************************/
00045 
00046 #include "gnn_softmax.h"
00047 #include <math.h>
00048 
00049 
00050 
00051 /******************************************/
00052 /* Static Declaration                     */
00053 /******************************************/
00054 
00055 typedef struct _gnn_softmax
00056 {
00057     gnn_node node;
00058     gsl_vector *e;
00059     gsl_vector *y;
00060 } gnn_softmax;
00061 
00062 static int
00063 gnn_softmax_f (gnn_node *node,
00064                const gsl_vector *x,
00065                const gsl_vector *w,
00066                gsl_vector *y);
00067 
00068 static int
00069 gnn_softmax_dx (gnn_node *node,
00070                 const gsl_vector *x,
00071                 const gsl_vector *w,
00072                 const gsl_vector *dy,
00073                 gsl_vector *dx);
00074 
00075 
00076 
00077 /******************************************/
00078 /* Static Implementation                  */
00079 /******************************************/
00080 
00081 /**
00082  * @brief Computes the output.
00083  * @ingroup gnn_softmax_doc
00084  *
00085  * This functions evaluates the softmax function.
00086  *
00087  * @param node  A pointer to a \ref gnn_softmax node.
00088  * @param x The input vector \f$x\f$.
00089  * @param w The parameter vector \f$w\f$ (which is empty in this case).
00090  * @param y The output buffer vector \f$y\f$.
00091  * @return Returns 0 on success.
00092  */
00093 static int
00094 gnn_softmax_f (gnn_node *node,
00095                const gsl_vector *x,
00096                const gsl_vector *w,
00097                gsl_vector *y)
00098 {
00099     size_t i;
00100     size_t size;
00101     double sum = 0.0;
00102     gnn_softmax *snode;
00103 
00104     /* get the size */
00105     size = gnn_node_input_get_size (node);
00106 
00107     /* get the view as a softmax node */
00108     snode = (gnn_softmax *) node;
00109     
00110     /* hold a pointer to the output vector */
00111     snode->y = y;
00112 
00113     /* evaluate */
00114     for (i=0; i<size; ++i)
00115     {
00116         double xi;
00117         double ei;
00118 
00119         xi = gsl_vector_get (x, i);
00120         ei = exp (xi);
00121         gsl_vector_set (snode->e, i, ei);
00122         sum += ei;
00123     }
00124     for (i=0; i<size; ++i)
00125     {
00126         double ei;
00127         double yi;
00128 
00129         ei = gsl_vector_get (snode->e, i);
00130         yi = ei / sum;
00131         gsl_vector_set (y, i, yi);
00132     }
00133 
00134     return 0;
00135 }
00136 
00137 /**
00138  * @brief Computes \f$ \frac{\partial E}{\partial X} \f$.
00139  * @ingroup gnn_softmax_doc
00140  *
00141  * This functions computes the gradient of the softmax function,
00142  * given \f$ \frac{\partial E}{\partial Y} \f$ (dy). The function is,
00143  * \f[ \frac{\partial E}{\partial x_i}
00144  *     = \sum_j y_j (\delta_{ji} - y_i) \frac{\partial E}{\partial y_j}
00145  * \f]
00146  *
00147  * @param node  A pointer to a \ref gnn_softmax node.
00148  * @param x  The input vector \f$x\f$.
00149  * @param w  The parameter vector \f$w\f$ (which is empty in this case).
00150  * @param dy The vector \f$\frac{\partial E}{\partial y}\f$.
00151  * @param dx The output buffer vector \f$\frac{\partial E}{\partial x}\f$.
00152  * @return Returns 0 on success.
00153  */
00154 static int
00155 gnn_softmax_dx (gnn_node *node,
00156                 const gsl_vector *x,
00157                 const gsl_vector *w,
00158                 const gsl_vector *dy,
00159                 gsl_vector *dx)
00160 {
00161     size_t i;
00162     size_t j;
00163     size_t size;
00164     gnn_softmax *snode;
00165 
00166     /* get the size */
00167     size = gnn_node_input_get_size (node);
00168 
00169     /* get the view as a softmax node */
00170     snode = (gnn_softmax *) node;
00171 
00172     /* evaluate */
00173     for (i=0; i<size; ++i)
00174     {
00175         double yi;
00176         double dxi;
00177 
00178         dxi = 0.0;
00179         yi  = gsl_vector_get (snode->y, i);
00180         
00181         for (j=0; j<size; ++j)
00182         {
00183             double yj;
00184             double dyj;
00185 
00186             yj   = gsl_vector_get (snode->y, j);
00187             dyj  = gsl_vector_get (dy, j);
00188             
00189             dxi += (i==j)?    yj * (1.0 - yi) * dyj
00190                           : - yj * yi * dyj;
00191         }
00192 
00193         gsl_vector_set (dx, i, dxi);
00194     }
00195     
00196     return 0;
00197 }
00198 
00199 /**
00200  * @brief Destroys the \ref gnn_softmax specific data.
00201  * @ingroup gnn_softmax_doc
00202  *
00203  * This is the destructor for \ref gnn_softmax nodes.
00204  *
00205  * @param node A pointer to a \ref gnn_softmax node.
00206  */
00207 static void
00208 gnn_softmax_destroy (gnn_node *node)
00209 {
00210     gnn_softmax *snode;
00211     
00212     assert (node != NULL);
00213     
00214     snode = (gnn_softmax *) node;
00215     if (snode->e != NULL)
00216         gsl_vector_free (snode->e);
00217         
00218     return;
00219 }
00220 
00221 
00222 
00223 /******************************************/
00224 /* Public Interface                       */
00225 /******************************************/
00226 
00227 /**
00228  * @brief Creates a Softmax activation function node.
00229  * @ingroup gnn_softmax_doc
00230  *
00231  * This function creates a node of the \ref gnn_softmax type.
00232  *
00233  * @param input_size The input size \f$n\f$.
00234  * @param a The \f$a\f$ factor.
00235  * @param b The \f$b\f$ factor.
00236  * @return A pointer to a new \ref gnn_softmax node.
00237  */
00238 gnn_node *
00239 gnn_softmax_new (int input_size)
00240 {
00241     int status;
00242     gnn_node *node;
00243     gnn_softmax *snode;
00244 
00245     /* check if sizes are positive */
00246     if (input_size < 1)
00247     {
00248         GSL_ERROR_VAL ("size should be strictly positive for gnn_softmax node",
00249                        GSL_ENOMEM, NULL);
00250         return NULL;
00251     }
00252 
00253     /* allocate the node */
00254     node = (gnn_node *) malloc (sizeof (gnn_softmax));
00255     if (node == NULL)
00256     {
00257         GSL_ERROR_VAL ("could not allocate memory for gnn_softmax node",
00258                        GSL_ENOMEM, NULL);
00259     }
00260     
00261     /* Initialize the node */
00262     status = gnn_node_init (node,
00263                             "gnn_softmax",
00264                             gnn_softmax_f,
00265                             gnn_softmax_dx,
00266                             NULL,
00267                             gnn_softmax_destroy);
00268     if (status)
00269     {
00270         GSL_ERROR_VAL ("could not initialize gnn_softmax node",
00271                        GSL_EFAILED, NULL);
00272     }
00273     
00274     status = gnn_node_set_sizes (node, input_size, input_size, 0);
00275     if (status)
00276     {
00277         GSL_ERROR_VAL ("could not set sizes for gnn_softmax node",
00278                        GSL_EFAILED, NULL);
00279     }
00280     
00281     /* build buffer */
00282     snode = (gnn_softmax *) node;
00283     snode->e = gsl_vector_alloc (input_size);
00284     if (snode->e == NULL)
00285     {
00286         gnn_node_destroy (node);
00287         GSL_ERROR_VAL ("could not allocate memory gnn_softmax buffer",
00288                        GSL_ENOMEM, NULL);
00289     }
00290 
00291     return node;
00292 }
00293 
00294 
00295 
00296 
00297 

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