00001 /*************************************************************************** 00002 * @file gnn_cross_entropy.c 00003 * @brief Cross Entropy Error Criterion. 00004 * 00005 * @date : 25-08-03 23:20 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 * @brief Cross Entropy Error function. 00027 * @defgroup gnn_cross_entropy_doc gnn_cross_entropy : Cross-Entropy Error Criterion. 00028 * @ingroup gnn_criterion_doc 00029 * 00030 * This datatype implements the Cross-Entropy criterion, given by 00031 * \f[ E(y,t) = 00032 - \sum_i^m \left ( 00033 t_i \ln y_i + (1 - t_i) \ln (1 - y_i) 00034 \right ) 00035 \f] 00036 * As it can be easily seen, the cross entropy cost function depends on the 00037 * relative error (instead of the absolute error like in MSE), thus giving 00038 * to small and large errors te same weight. 00039 * 00040 * The cross entropy criterion fits well in classification problems, where 00041 * the output encodes the class using binary values; that is, where 00042 * \f$y_c = 1\f$ and \f$y_i = 0\f$ for all \f$i \neq c\f$ if the input 00043 * \f$x\f$ corresponds to the \f$c\f$-th class. 00044 * 00045 */ 00046 00047 00048 00049 /******************************************/ 00050 /* Include Files */ 00051 /******************************************/ 00052 00053 #include <math.h> 00054 #include "gnn_cross_entropy.h" 00055 00056 00057 00058 /******************************************/ 00059 /* Static Declaration */ 00060 /******************************************/ 00061 00062 typedef gnn_criterion gnn_cross_entropy; 00063 00064 double 00065 gnn_cross_entropy_e (gnn_criterion *crit, 00066 const gsl_vector *y, 00067 const gsl_vector *t); 00068 00069 int 00070 gnn_cross_entropy_dy (gnn_criterion *crit, 00071 const gsl_vector *y, 00072 const gsl_vector *t, 00073 gsl_vector * dy); 00074 00075 00076 00077 /******************************************/ 00078 /* Static Implementation */ 00079 /******************************************/ 00080 00081 /** 00082 * @brief The evaluation function. 00083 * @ingroup gnn_cross_entropy_doc 00084 * 00085 * This function corresponds to the evaluation of the cross entropy criterion. 00086 * 00087 * @param crit A pointer to a \ref gnn_cross_entropy criterion. 00088 * @param y A pointer to an estimation vector \f$y\f$. 00089 * @param t A pointer to the desired target vector \f$t\f$. 00090 * @return A real number corresponding to the value of the criterion. 00091 */ 00092 double 00093 gnn_cross_entropy_e (gnn_criterion *crit, 00094 const gsl_vector *y, 00095 const gsl_vector *t) 00096 { 00097 int i; 00098 double E; 00099 00100 assert (crit != NULL); 00101 assert (y != NULL); 00102 assert (t != NULL); 00103 00104 /* check sizes */ 00105 if (y->size != t->size) 00106 GSL_ERROR_VAL ("vector sizes should be the same", GSL_EINVAL, 0.0); 00107 00108 /* compute error */ 00109 E = 0.0; 00110 for (i=0; i<y->size; ++i) 00111 { 00112 double yi; 00113 double ti; 00114 double ei; 00115 00116 yi = gsl_vector_get (y, i); 00117 ti = gsl_vector_get (t, i); 00118 00119 ei = (yi < GNN_CROSS_ENTROPY_EPS)? 00120 ti * log (GNN_CROSS_ENTROPY_EPS) 00121 : ti * log (yi); 00122 00123 ei += (1.0 - yi < GNN_CROSS_ENTROPY_EPS)? 00124 (1.0 - ti) * log (1.0 - GNN_CROSS_ENTROPY_EPS) 00125 : (1.0 - ti) * log (1.0 - yi); 00126 00127 E -= ei; 00128 } 00129 00130 return E; 00131 } 00132 00133 /** 00134 * @brief The gradient evaluation function. 00135 * @ingroup gnn_cross_entropy_doc 00136 * 00137 * This function implements the \ref gnn_cross_entropy criterion's gradient 00138 * evaluation function given by 00139 * 00140 * \f[ \frac{\partial E}{\partial y_i} = 00141 - \frac{y_i - t_i}{y_i (1 - y_i)} \f] 00142 * 00143 * @param crit A pointer to a \ref gnn_cross_entropy criterion. 00144 * @param y A pointer to an estimation vector \f$y\f$. 00145 * @param t A pointer to the desired target vector \f$t\f$. 00146 * @param dy A pointer to a buffer vector where the result should be placed. 00147 * @return Returns 0 if succeeded. 00148 */ 00149 int 00150 gnn_cross_entropy_dy (gnn_criterion *crit, 00151 const gsl_vector *y, 00152 const gsl_vector *t, 00153 gsl_vector * dy) 00154 { 00155 int i; 00156 00157 assert (crit != NULL); 00158 assert (y != NULL); 00159 assert (t != NULL); 00160 assert (dy != NULL); 00161 00162 /* check sizes */ 00163 if (y->size != t->size || y->size != dy->size) 00164 GSL_ERROR ("vector sizes should be the same", GSL_EINVAL); 00165 00166 /* compute dy */ 00167 for (i=0; i<y->size; ++i) 00168 { 00169 double yi; 00170 double ti; 00171 double dyi; 00172 00173 yi = gsl_vector_get (y, i); 00174 ti = gsl_vector_get (t, i); 00175 dyi = gsl_vector_get (dy, i); 00176 00177 yi = (yi > 1.0 - GNN_CROSS_ENTROPY_EPS)? 00178 (1.0 - GNN_CROSS_ENTROPY_EPS) 00179 : yi; 00180 yi = (yi < GNN_CROSS_ENTROPY_EPS)? 00181 GNN_CROSS_ENTROPY_EPS 00182 : yi; 00183 00184 dyi += (yi - ti) / (yi * (1.0 - yi)); 00185 00186 gsl_vector_set (dy, i, dyi); 00187 } 00188 00189 return 0; 00190 } 00191 00192 00193 /******************************************/ 00194 /* Public Interface */ 00195 /******************************************/ 00196 00197 /** 00198 * @brief Creates a new \ref gnn_cross_entropy criterion. 00199 * @ingroup gnn_cross_entropy_doc 00200 * 00201 * This function creates a new \ref gnn_cross_entropy criterion of the given 00202 * size. 00203 * 00204 * @param size The size of the estimation and the target vector \f$y\f$ 00205 * and \f$t\f$. 00206 * @return Returns a pointer to a new \ref gnn_cross_entropy or NULL if failed. 00207 */ 00208 gnn_criterion * 00209 gnn_cross_entropy_new (size_t size) 00210 { 00211 int status; 00212 gnn_criterion *crit; 00213 00214 /* check size */ 00215 if (size < 1) 00216 GSL_ERROR_VAL ("size should be strictly positive", GSL_EINVAL, NULL); 00217 00218 /* alloc memory */ 00219 crit = (gnn_criterion *) malloc (sizeof (*crit)); 00220 if (crit == NULL) 00221 GSL_ERROR_VAL ("couldn't alloc memory for gnn_cross_entropy", 00222 GSL_ENOMEM, NULL); 00223 00224 /* initialize */ 00225 status = gnn_criterion_init (crit, 00226 "gnn_cross_entropy", 00227 size, 00228 gnn_cross_entropy_e, 00229 gnn_cross_entropy_dy, 00230 NULL); 00231 if (status) 00232 { 00233 gnn_criterion_destroy (crit); 00234 GSL_ERROR_VAL ("couldn't initialize gnn_cross_entropy", 00235 GSL_EFAILED, NULL); 00236 } 00237 00238 return crit; 00239 } 00240 00241 00242
1.2.18