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

gnn_quadric.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *  @file gnn_quadric.c
00003  *  @brief Quadric Discriminant Transfer Function.
00004  *
00005  *  @date   : 06-08-03 18:17, 22-08-03 23:04
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_quadric_doc gnn_quadric : Quadric Discriminant Activation Function.
00027  * @ingroup gnn_atomic_doc
00028  *
00029  * This node type takes the \f$n\f$ input variables \f$x_1, x_2, \ldots, x_n\f$
00030  * and produces \f$m = \frac{ n(n+1) }{2}\f$ outputs, corresponding to the
00031  * cross-multiplication of the inputs:
00032  * \f[ y_k = x_i x_j \f]
00033  * where \f$ k = n(i-1)+j-i? \f$, 
00034  * \f$ i? = 1 + 2 + 3 + \cdots + i= \sum_{j=1}^i j = \frac{ n(n+1) }{2}\f$.
00035  *
00036  * Example:
00037  * \f[ F([x_1, x_2, x_3]^t) =
00038  *      [x_1^2, x_1 x_2, x_1 x_3, x_2^2, x_2 x_3, x_3^2 ]^t \f]
00039  *
00040  * The resulting terms, combinend with a linear transform, can model quadric
00041  * decision boundaries (parabola, hyperbola, ellipsoids and spheres), which
00042  * are richer in structure than classic linear discriminants.
00043  *
00044  * Note: \f[ k(i,j) = \frac{2ni - 2n - i^2 + i}{2} + j
00045  *                  = n(i-1) + \frac{i(1-i)}{2} + j \f]
00046  */
00047 
00048 
00049 /******************************************/
00050 /* Include Files                          */
00051 /******************************************/
00052 
00053 #include "gnn_quadric.h"
00054 #include <math.h>
00055 
00056 
00057 
00058 /******************************************/
00059 /* Static Declaration                     */
00060 /******************************************/
00061 
00062 static int
00063 gnn_quadric_f (gnn_node *node,
00064                const gsl_vector *x,
00065                const gsl_vector *w,
00066                gsl_vector *y);
00067 
00068 static int
00069 gnn_quadric_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_quadric_doc
00084  *
00085  * This functions evaluates the Quadric Discriminant Transfer function.
00086  *
00087  * @param  node A pointer to a \ref gnn_quadric node.
00088  * @param x    The input vector \f$x\f$.
00089  * @param w    The current parameter vector \f$w\f$.
00090  * @param y    An output vector \f$y\f$ where the result should be stored.
00091  * @return 0 if succeeded.
00092  */
00093 static int
00094 gnn_quadric_f (gnn_node *node,
00095                const gsl_vector *x,
00096                const gsl_vector *w,
00097                gsl_vector *y)
00098 {
00099     int i;
00100     int j;
00101     int k;
00102     int size;
00103 
00104     /* get the size */
00105     size = gnn_node_input_get_size (node);
00106 
00107     /* evaluate */
00108     k = 0;
00109     for (i=0; i<size; ++i)
00110     {
00111         for (j=i; j<size; ++j)
00112         {
00113             double xi;
00114             double xj;
00115             double yk;
00116 
00117             xi = gsl_vector_get (x, i);
00118             xj = gsl_vector_get (x, j);
00119             yk = xi * xj;
00120             gsl_vector_set (y, k, yk);
00121             
00122             k++;
00123         }
00124     }
00125 
00126     return 0;
00127 }
00128 
00129 /**
00130  * @brief Computes \f$ \frac{\partial E}{\partial x} \f$.
00131  * @ingroup gnn_quadric_doc
00132  *
00133  * This functions computes the gradient of the Quadric Discriminant activation
00134  * function, given dy (\f$ \frac{\partial E}{\partial y} \f$). The function
00135  * is,
00136  * \f[ \frac{\partial E}{\partial x_i} =
00137  *     \sum_{j=1, j \neq i}^n x_j \frac{\partial E}{\partial y_{k(i,j)}}
00138  *     + 2 x_i \frac{\partial E}{\partial y_{k(i,i)}}
00139  * \f]
00140  *
00141  * @param  node A pointer to a \ref gnn_quadric node.
00142  * @param x    The input vector \f$x\f$.
00143  * @param w    The current parameter vector \f$w\f$.
00144  * @param dy   The error-backpropagation vector
00145  *             \f$\frac{\partial E}{\partial y}\f$
00146  * @param dx   An output vector where the result
00147  *             \f$\frac{\partial E}{\partial x}\f$ should be stored.
00148  * @return 0 if suceeded.
00149  */
00150 static int
00151 gnn_quadric_dx (gnn_node *node,
00152                 const gsl_vector *x,
00153                 const gsl_vector *w,
00154                 const gsl_vector *dy,
00155                 gsl_vector *dx)
00156 {
00157     int i;
00158     int j;
00159     int N;
00160     int k;
00161 
00162     /* get the size */
00163     N = gnn_node_input_get_size (node);
00164 
00165     /* compute the dx vector - Caution: The simmetry involved allows
00166        us to write a faster routine. */
00167     k = 0;
00168     for (i=0; i<N; ++i)
00169     {
00170         for (j=i; j<N; ++j)
00171         {
00172             double xi;
00173             double xj;
00174             double dyk;
00175             double dxi;
00176             double dxj;
00177 
00178             xi  = gsl_vector_get (x, i);
00179             xj  = gsl_vector_get (x, j);
00180             dyk = gsl_vector_get (dy, k);
00181             
00182             dxi = xj * dyk;
00183             gsl_vector_set (dx, i, dxi);
00184 
00185             dxj = gsl_vector_get (dx, j);
00186             dxj += xi * dyk;
00187             gsl_vector_set (dx, j, dxj);
00188             
00189             k++;
00190         }
00191     }
00192 
00193     return 0;
00194 }
00195 
00196 
00197 /******************************************/
00198 /* Public Interface                       */
00199 /******************************************/
00200 
00201 /**
00202  * @brief Creates a Quadric Discriminant Transfer function node.
00203  * @ingroup gnn_quadric_doc
00204  *
00205  * This function creates a node of the gnn_quadric type. This node
00206  * produces the second-order terms of its inputs. For a complete review,
00207  * see \ref gnn_quadric_doc.
00208  *
00209  * @param input_size The input size \f$n\f$.
00210  * @return A pointer to a new \ref gnn_quadric node.
00211  */
00212 gnn_node *
00213 gnn_quadric_new (int input_size)
00214 {
00215     int status;
00216     int output_size;
00217     gnn_node *node;
00218 
00219     /* check if sizes are positive */
00220     if (input_size < 1)
00221     {
00222         GSL_ERROR_VAL ("size for gnn_quadric should be greater than 1",
00223                        GSL_EINVAL, NULL);
00224     }
00225 
00226     /* allocate node */
00227     node = (gnn_node *) malloc (sizeof (gnn_node));
00228     if (node == NULL)
00229     {
00230         GSL_ERROR_VAL ("could not allocate memory for gnn_quadric",
00231                        GSL_ENOMEM, NULL);
00232     }
00233 
00234     /* initialize node */
00235     status = gnn_node_init (node,
00236                             "gnn_quadric",
00237                             gnn_quadric_f,
00238                             gnn_quadric_dx,
00239                             NULL,
00240                             NULL);
00241     if (status)
00242     {
00243         free (node);
00244         GSL_ERROR_VAL ("could not initialize gnn_quadric node",
00245                        GSL_EFAILED, NULL);
00246     }
00247 
00248     /* set sizes */
00249     output_size = (input_size * (input_size + 1)) / 2;
00250     gnn_node_set_sizes (node, input_size, output_size, 0);
00251 
00252     return node;
00253 }
00254 
00255 

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