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

gnn_convergence.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *  @file gnn_convergence.c
00003  *  @brief gnn_convergence Implementation.
00004  *
00005  *  @date   : 28-09-03 13: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_convergence_doc gnn_convergence : Input Convergence.
00027  * @ingroup gnn_atomic_doc
00028  *
00029  * The \ref gnn_convergence node is a special node that takes a big input
00030  * vector and slices it into mini-vectors that fit into the output. This
00031  * can be viewed a if the input where in reality a concatenation of subvectors
00032  * of the same size.
00033  *
00034  * The function implemented by this node is given by:
00035  *
00036  * \f[ y_j =
00037  * \frac{1}{S} \left ( x_j + x_{m+j} + x_{2m+j} + \ldots + x_{(S-1)m+j} \right )
00038  *         = \frac{1}{S} \sum_{k=0}^{S-1} x_{km+j}
00039  * \f]
00040  *
00041  * In other words, it slices the input vector \f$x\f$ into several subvectors
00042  * of size \f$m \times 1\f$ and sums them up, divided by the total amount
00043  * of resulting pieces \f$S\f$. Remember that \f$m\f$ is the output size.
00044  *
00045  * If the input vector's
00046  * size isn't a multiple of the output vector's size,
00047  * that is, if \f$n\f$ can't be written as \f$km\f$, then the last vector slice
00048  * will consider only the remaining terms, e.g.
00049  * if \f$x=[x_0, \ldots, x_5]^T\f$ and \f$y\f$ is of size
00050  * \f$4 \times 1\f$ then
00051  *
00052  * \f[ y = 1/2 \left [ \begin{array}{c}
00053  *                     (x_0 + x_4) \\
00054  *                     (x_1 + x_5) \\
00055  *                      x_2 \\
00056  *                      x_3 \\
00057  *         \end{array} \right ]
00058  * \f]
00059  *
00060  * Schematically, this idea can be depicted as
00061  *
00062  * <img src="images/gnn_convergence1.png">
00063  *
00064  * The function's gradient is:
00065  * \f[ \frac{\partial E}{\partial x_i}
00066  *     = S \frac{\partial E}{\partial x_{km+j}}
00067  *     = S \frac{\partial E}{\partial y_j}
00068  * \f]
00069  *
00070  *
00071  */
00072 
00073 
00074 /******************************************/
00075 /* Include Files                          */
00076 /******************************************/
00077 
00078 #include "gnn_convergence.h"
00079 
00080 
00081 
00082 /******************************************/
00083 /* Static Declaration                     */
00084 /******************************************/
00085 
00086 static int
00087 gnn_convergence_f (gnn_node *node,
00088                    const gsl_vector *x,
00089                    const gsl_vector *w,
00090                    gsl_vector *y);
00091 
00092 static int
00093 gnn_convergence_dx (gnn_node *node,
00094                     const gsl_vector *x,
00095                     const gsl_vector *w,
00096                     const gsl_vector *dy,
00097                     gsl_vector *dx);
00098 
00099 static int
00100 gnn_convergence_dw (gnn_node *node,
00101                     const gsl_vector *x,
00102                     const gsl_vector *w,
00103                     const gsl_vector *dy,
00104                     gsl_vector *dw);
00105 
00106 static void
00107 gnn_convergence_destroy (gnn_node *node);
00108 
00109 
00110 
00111 /******************************************/
00112 /* Static Implementation                  */
00113 /******************************************/
00114 
00115 /**
00116  * @brief Computes the output.
00117  * @ingroup gnn_convergence_doc
00118  *
00119  * @param   node A pointer to the \ref gnn_convergence node.
00120  * @param x The input vector \f$x\f$.
00121  * @param w The parameter vector \f$w\f$.
00122  * @param y The output buffer vector \f$y\f$.
00123  * @return Returns 0 on success.
00124  */
00125 static int
00126 gnn_convergence_f (gnn_node *node,
00127                    const gsl_vector *x,
00128                    const gsl_vector *w,
00129                    gsl_vector *y)
00130 {
00131     size_t n;
00132     size_t m;
00133     size_t k;
00134     gnn_convergence *cnode;
00135 
00136     /* get views */
00137     cnode = (gnn_convergence *) node;
00138 
00139     /* get input and output size */
00140     n = gnn_node_input_get_size (node);
00141     m = gnn_node_output_get_size (node);
00142 
00143     /* evaluate */
00144     gsl_vector_set_zero (y);
00145     for (k=0; k<n; ++k)
00146     {
00147         size_t j;
00148         double yj;
00149         
00150         j   = k % m;
00151         yj  = gsl_vector_get (y, j);
00152         yj += 1.0/cnode->rep * gsl_vector_get (x, k);
00153         gsl_vector_set (y, j, yj);
00154     }
00155 
00156     return 0;
00157 }
00158 
00159 /**
00160  * @brief Computes \f$ \frac{\partial E}{\partial x} \f$.
00161  * @ingroup gnn_convergence_doc
00162  *
00163  * @param    node A pointer to the \ref gnn_convergence node.
00164  * @param x  The input vector \f$x\f$.
00165  * @param w  The parameter vector \f$w\f$.
00166  * @param dy The vector \f$\frac{\partial E}{\partial y}\f$.
00167  * @param dx The output buffer vector \f$\frac{\partial E}{\partial x}\f$.
00168  * @return Returns 0 on success.
00169  */
00170 static int
00171 gnn_convergence_dx (gnn_node *node,
00172                     const gsl_vector *x,
00173                     const gsl_vector *w,
00174                     const gsl_vector *dy,
00175                     gsl_vector *dx)
00176 {
00177     size_t n;
00178     size_t m;
00179     size_t k;
00180     gnn_convergence *cnode;
00181 
00182     /* get views */
00183     cnode = (gnn_convergence *) node;
00184 
00185     /* get input and output size */
00186     n = gnn_node_input_get_size (node);
00187     m = gnn_node_output_get_size (node);
00188 
00189     /* evaluate */
00190     for (k=0; k<n; ++k)
00191     {
00192         size_t j;
00193         double dxk;
00194         
00195         j   = k % m;
00196         dxk = cnode->rep * gsl_vector_get (dy, j);
00197         gsl_vector_set (dx, k, dxk);
00198     }
00199 
00200     return 0;
00201 }
00202 
00203 /**
00204  * @brief Computes \f$ \frac{\partial E}{\partial w} \f$.
00205  * @ingroup gnn_convergence_doc
00206  *
00207  * @param    node A pointer to the \ref gnn_convergence 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_convergence_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     return 0;
00222 }
00223 
00224 
00225 
00226 /******************************************/
00227 /* Public Interface                       */
00228 /******************************************/
00229 
00230 /**
00231  * @brief Creates an input convergence node.
00232  * @ingroup gnn_convergence_doc
00233  *
00234  * This function creates a node of the \ref gnn_convergence type.
00235  *
00236  * @param input_size  The input size \f$n\f$.
00237  * @param output_size The output size \f$m\f$.
00238  * @return A pointer to a new \ref gnn_convergence node.
00239  */
00240 gnn_node *
00241 gnn_convergence_new (size_t input_size, size_t output_size)
00242 {
00243     int status;
00244     size_t k;
00245     gnn_node *node;
00246     gnn_convergence *cnode;
00247 
00248     /* check sizes */
00249     if (output_size < 1)
00250     {
00251         GSL_ERROR_VAL ("output size should be strictly positive",
00252                        GSL_EINVAL, NULL);
00253     }
00254     if (input_size < output_size)
00255     {
00256         GSL_ERROR_VAL ("input size should be greater than the output size",
00257                        GSL_EINVAL, NULL);
00258     }
00259 
00260     /* allocate the node */
00261     cnode = (gnn_convergence *) malloc (sizeof (gnn_convergence));
00262     if (cnode == NULL)
00263     {
00264         GSL_ERROR_VAL ("could not allocate memory for gnn_convergence node",
00265                        GSL_ENOMEM, NULL);
00266     }
00267 
00268     /* get view as a gnn_node */
00269     node = (gnn_node *) cnode;
00270 
00271     /* Initialize the node */
00272     status = gnn_node_init (node,
00273                             "gnn_convergence",
00274                             gnn_convergence_f,
00275                             gnn_convergence_dx,
00276                             gnn_convergence_dw,
00277                             NULL);
00278     if (status)
00279     {
00280         GSL_ERROR_VAL ("could not initialize gnn_convergence node",
00281                        GSL_EFAILED, NULL);
00282     }
00283 
00284     status = gnn_node_set_sizes (node, input_size, output_size, 0);
00285     if (status)
00286     {
00287         GSL_ERROR_VAL ("could not set sizes for gnn_convergence node",
00288                        GSL_EFAILED, NULL);
00289     }
00290 
00291     /* compute amount of replications */
00292     cnode->rep = input_size / output_size;
00293     cnode->rep += (input_size % output_size == 0)? 0 : 1;
00294 
00295     return node;
00296 }
00297 
00298 

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