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
1.2.18