lcsom.c

Go to the documentation of this file.
00001 /*
00002 *    Copyright (c) 2007. The BATI team. All right reserved.
00003 *
00004 *    This file is part of BATI library.
00005 *
00006 *    BATI library is free software: you can redistribute it and/or modify
00007 *    it under the terms of the GNU General Public License as published by
00008 *    the Free Software Foundation, either version 3 of the License, or
00009 *    (at your option) any later version.
00010 *
00011 *    BATI library  is distributed in the hope that it will be useful,
00012 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 *    GNU General Public License for more details.
00015 *
00016 *    You should have received a copy of the GNU General Public License
00017 *    along with BATI library.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00026 /*----------------------------------------------------------------*/
00027 /*                                                                */
00028 /* Kohonen Circular Self Organizing Map Neural Network            */
00029 /*                                                                */
00030 /* author: Petre Rodan <rodan@subdimension.com>                   */
00031 /*                                                                */
00032 /* -------------------------------------------------------------- */
00033 
00034 /* CSOM Neural Network library
00035     Description : Circular Self-Organizing Map (CSOM) (Kohonen et al) Neural Network library for the segmentation of streams
00036     It takes multiple (float *) streams of the same dimension and delivers a segmented output.
00037     @author Petre Rodan 
00038     @version 1.0 (07/03/02)
00039     @see www.cis.hut.fi/teuvo
00040 */
00041 
00042 
00047 #include "image.h"
00048 #include "proto2D.h"
00049 #include "lcsom.h"
00050 #include <math.h>
00051 #include <time.h>
00052 #include <stdlib.h>
00053 #include <stdarg.h>
00054 
00055 //---------------------------------------------------------------------------
00056 
00057 /* *************************  LECTURE  *******************************/
00075 param *csom_lect( csom_t *csom, param *ptp, char *debq)
00076 {
00077   char question[500];
00078   //  unsigned int i;
00079 
00080   sprintf(question, "%s input_neurons (unsigned int)", debq); 
00081   lec_param(question, ptp);
00082   csom->input_neurons = (int)atoi(ptp->rep);
00083   ptp = ptp->next;
00084 
00085   sprintf(question, "%s output_neurons (unsigned int)", debq); 
00086   lec_param(question, ptp);
00087   csom->output_neurons = (int)atoi(ptp->rep);
00088   ptp = ptp->next;
00089 
00090 //  sprintf(question, "%s size of input space (unsigned int)", debq); 
00091 //  lec_param(question, ptp);
00092 //  csom->element = (int)atoi(ptp->rep);
00093 //  ptp = ptp->next;
00094 
00095   sprintf(question, "%s max_neigh (unsigned int)", debq); 
00096   lec_param(question, ptp);
00097   csom->max_neigh = (int)atoi(ptp->rep);
00098   while ((float)csom->max_neigh>(float)(csom->output_neurons/2.00))
00099     {printf("WARNING: max_neigh must be < %f   (output_neurons/2)",(float)(csom->output_neurons/2.00));
00100     sprintf(question, "%s max_neigh (unsigned int)", debq); 
00101     lec_param(question, ptp);
00102     csom->max_neigh = (int)atoi(ptp->rep);
00103     }
00104   ptp = ptp->next;
00105 
00106   sprintf(question, "%s max_learn_rate (float)", debq); 
00107   lec_param(question, ptp);
00108   csom->max_learn_rate = (float)atof(ptp->rep);
00109   ptp = ptp->next;
00110 
00111   sprintf(question, "%s max_epoch (unsigned int)", debq); 
00112   lec_param(question, ptp);
00113   csom->max_epoch = (int)atoi(ptp->rep);
00114   ptp = ptp->next;
00115 
00116   sprintf(question, "%s random init or not? (1/0)", debq); 
00117   lec_param(question, ptp);
00118   csom->random_init = (int)atoi(ptp->rep);
00119   ptp = ptp->next; 
00120 
00121   sprintf(question, "%s rescale the input space or not? (1/0)", debq);
00122   lec_param(question, ptp);
00123   csom->rescale_sw = (int)atoi(ptp->rep);
00124   ptp = ptp->next;
00125   
00126   return(ptp);
00127 }
00128 
00129 
00130 
00131 /* *************************  INITIALIZATION  *******************************/
00132 
00139 int csom_init(csom_t *csom)
00140 {
00141 
00142   unsigned int i,j;
00143 
00144   /* malloc for the attribute space */
00145   if( (csom->x=(float **)malloc((csom->input_neurons)*sizeof(float*))) == NULL )
00146     {printf ("\n fatal error: a.13 allocation  impossible\n");  exit(1);}
00147   if( (csom->x[0]=(float *)malloc((csom->input_neurons)*(csom->element)*sizeof(float))) == NULL )
00148     {printf ("\n fatal error: a.14 allocation  impossible\n");  exit(1);}
00149   for (i=1;i<csom->input_neurons;i++)
00150     {csom->x[i]=csom->x[0]+((csom->element)*i);}
00151 
00152   /* mem allocation for the coefficients */
00153   if( (csom->w=(float **)malloc((csom->input_neurons)*sizeof(float*))) == NULL )
00154     {printf ("\n fatal error: a.01 allocation  impossible\n");  exit(1);}
00155   if( (csom->w[0]=(float *)malloc((csom->input_neurons)*(csom->output_neurons)*sizeof(float))) == NULL )
00156     {printf ("\n fatal error: a.02 allocation  impossible\n");  exit(1);}
00157   for (i=1;i<csom->input_neurons;i++)
00158     {csom->w[i]=csom->w[0]+((csom->output_neurons)*i);}
00159 
00160   /* mem allocation for new coefficients */
00161   if( (csom->w_new=(float **)malloc((csom->input_neurons)*sizeof(float*))) == NULL )
00162     {printf ("\n fatal error: a.03 allocation  impossible\n");  exit(1);}
00163   if( (csom->w_new[0]=(float *)malloc((csom->input_neurons)*(csom->output_neurons)*sizeof(float))) == NULL )
00164     {printf ("\n fatal error: a.04 allocation  impossible\n");  exit(1);}
00165   for (i=1;i<csom->input_neurons;i++)
00166     {csom->w_new[i]=csom->w_new[0]+((csom->output_neurons)*i);}
00167 
00168   /* mem allocation for distances */
00169   if( (csom->d=(float *)malloc((csom->output_neurons)*sizeof(float))) == NULL)
00170     {printf ("\n fatal error: a.05 allocation  impossible\n");  exit(1);}
00171 
00172   /* other mem hungry allocations */
00173 
00174 #ifdef DEBUG
00175   if( (csom->activations=(int *)malloc((csom->output_neurons)*sizeof(int))) == NULL)
00176     {printf ("\n fatal error: a.06 allocation  impossible\n");  exit(1);}
00177 #endif
00178 
00179   if( (csom->neigh_rate=(float *)malloc((csom->max_epoch)*sizeof(float))) == NULL)
00180     {printf ("\n fatal error: a.07 allocation  impossible\n");  exit(1);}
00181   if( (csom->learn_rate=(float *)malloc((csom->max_epoch)*sizeof(float))) == NULL)
00182     {printf ("\n fatal error: a.08 allocation  impossible\n");  exit(1);}
00183   if( (csom->csom_out=(int *)malloc((csom->element)*sizeof(int))) == NULL)
00184     {printf ("\n fatal error: a.09 allocation  impossible\n");  exit(1);}
00185 
00186   /* the neighborhood rate function */
00187   for (i=0;i<csom->max_epoch;i++) 
00188     {csom->neigh_rate[i]=ceil((float)-(csom->max_neigh*1.00/csom->max_epoch*1.00)*i*1.00 + csom->max_neigh);}
00189   /* DIV by 0 protection */
00190   csom->neigh_rate[csom->max_epoch-1]=1;
00191 
00192   /* the learning rate function */
00193   for (i=0;i<csom->max_epoch;i++) { csom->learn_rate[i]=csom->max_learn_rate*(pow((0.01/csom->max_learn_rate),((float)i/csom->max_epoch)));}
00194 
00195   /* the coefficients space init */
00196   //srand(0);
00197   srand((unsigned int) time(NULL));
00198 
00199   for (i=0;i<csom->output_neurons;i++)
00200     { 
00201       if (csom->random_init)
00202         {for (j=0;j<csom->input_neurons;j++)
00203           {csom->w[j][i]=(int)(255 *(double)rand() / RAND_MAX);}
00204         }
00205       else
00206         {for (j=0;j<csom->input_neurons;j++)
00207           {csom->w[j][i]=(float)i*254.00/csom->output_neurons;}
00208         }
00209     }
00210       
00211   return 0;
00212 }
00213 
00214 /* *************************  CALCUL  *******************************/
00221 int csom_calc(csom_t *csom)
00222 {
00224   int i,j;        
00226   float d_min; 
00228   int winner=0;
00230   int winner_df; 
00232   char keep_training; 
00234   int vector_no;
00236   int st,dr;
00238   float min_input,max_input,rescale_factor;
00239 
00240   /* START */
00241   csom->epoch=0;
00242   keep_training=1;
00243 
00244   /* rescale the input space if needed*/
00245   if (csom->rescale_sw) 
00246     {
00247       for (j=0;j<csom->input_neurons;j++)
00248         {max_input=csom->x[j][0];
00249         min_input=csom->x[j][0];
00250         for (i=1;i<csom->element;i++) 
00251           {if (csom->x[j][i]>max_input) {max_input=csom->x[j][i];}
00252           if (csom->x[j][i]<min_input) {min_input=csom->x[j][i];}
00253           }
00254         rescale_factor=255.00/(max_input-min_input);
00255         for (i=0;i<csom->element;i++) 
00256           {csom->x[j][i]=csom->x[j][i]*rescale_factor;}
00257         }       
00258     }
00259 
00260   while (keep_training) /* STOP condition*/
00261     {
00262       //step 1. initializations
00263       //step 2. the current vector is applied to the input ( x(current_epoch) )
00264       //step 3. the distances between x(current_epoch) and every w(i,j) is computed 
00265       //step 4. the winning neuron is selected ( by establishing the smallest distance )
00266       //step 5. new w's are computed for the winning neuron and for the neighbours
00267       //step 6. current_epoch+=1, goto 2 ( until csom->max_epoch is reached )
00268 
00269       //printf("epoch %d\n",csom->epoch);
00270       csom->evolution=0;
00271 #ifdef DEBUG   
00272       for (j=0;j<csom->output_neurons;j++) {csom->activations[j]=0;}
00273 #endif
00274       for (vector_no=0; vector_no<csom->element; vector_no++)
00275         {d_min=99999999.99;
00276         csom->element_current=vector_no;
00277         //euclidian distances from input vector to the coefficients
00278         for (j=0;j<csom->output_neurons;j++)
00279           {
00280             csom->d[j]=0;
00281             {for (i=0;i<csom->input_neurons;i++)
00282               {csom->d[j]+=(csom->x[i][vector_no] - csom->w[i][j])*(csom->x[i][vector_no] - csom->w[i][j]);}
00283             }
00284             //who is the winner for this vector?
00285             if (csom->d[j]<d_min) {d_min=csom->d[j]; winner=j;}
00286           }
00287         //declare the winner
00288         csom->csom_out[csom->element_current]=winner;
00289 #ifdef DEBUG
00290         csom->activations[winner]++;
00291 #endif
00292         //share the winning
00293          
00294         winner_df=0;
00295         st=winner;
00296         dr=winner;
00297         
00298         
00299         while (winner_df<csom->neigh_rate[csom->epoch])
00300           {
00301             for (i=0;i<csom->input_neurons;i++)
00302               {
00303                 /* refine the coefficients on the right side of the winner */
00304                 csom->w_new[i][dr]=csom->w[i][dr]+csom->learn_rate[csom->epoch]*(1-(winner_df*1.000000001/csom->neigh_rate[csom->epoch]))*(csom->x[i][vector_no]-csom->w[i][dr]);
00305 #ifdef DEBUG
00306                 csom->evolution+=pow(csom->w_new[i][dr]-csom->w[i][dr],2);
00307 #endif
00308                 csom->w[i][dr]=csom->w_new[i][dr];
00309 
00310                 /* refine the coefficients on the left side of the winner */
00311                 csom->w_new[i][st]=csom->w[i][st]+csom->learn_rate[csom->epoch]*(1-(winner_df*1.000000001/csom->neigh_rate[csom->epoch]))*(csom->x[i][vector_no]-csom->w[i][st]);
00312 #ifdef DEBUG
00313                 csom->evolution+=pow(csom->w_new[i][st]-csom->w[i][st],2);
00314 #endif
00315                 csom->w[i][st]=csom->w_new[i][st];
00316               }
00317 
00318             if (st==0) {st=csom->output_neurons;}
00319             if (dr==csom->output_neurons-1) {dr=-1;}
00320 
00321             st--; dr++; winner_df++;
00322           } /* done with the sharing */
00323         } /* all vector space computed */
00324       /* a new epoch */
00325       csom->epoch++;
00326 #ifdef DEBUG
00327       printf("epoch %d\n",csom->epoch);
00328 #endif
00329       /* the STOP condition */
00330       if (csom->epoch>=csom->max_epoch) {keep_training=0;}
00331     } //epoch
00332 
00333   /* karma += 1 */
00334   return 0;
00335 }
00336 
00337 //---------------------------------------------------------------------------
00338 /* *************************  DESTRUCT  *******************************/
00344 int csom_destruct(csom_t *csom)
00345 {
00346   //  int i;
00347 
00348   //  for (i=0;i<csom->input_neurons;i++) {free(csom->x[i]);}
00349   free (csom->x[0]);
00350   free (csom->x);
00351 
00352   //free a.01 & a.02
00353   //for (i=0;i<csom->input_neurons;i++) {free(csom->w[i]);csom->w[i]=NULL;}
00354   free (csom->w[0]);
00355   free (csom->w);
00356   csom->w=NULL;
00357 
00358   //free a.03 & a.04
00359   //for (i=0;i<csom->input_neurons;i++) {free(csom->w_new[i]);csom->w_new[i]=NULL;}
00360   free (csom->w_new[0]);
00361   free (csom->w_new); csom->w_new=NULL;
00362 
00363   //free a.05
00364   free(csom->d); csom->d=NULL;
00365 
00366 #ifdef DEBUG
00367   //free a.06
00368   free(csom->activations); csom->activations=NULL;
00369 #endif
00370 
00371   //free a.07
00372   free(csom->neigh_rate); csom->neigh_rate=NULL;
00373 
00374   //free a.08
00375   free(csom->learn_rate); csom->learn_rate=NULL;
00376 
00377   //free a.09
00378   free(csom->csom_out); csom->csom_out=NULL;
00379 
00380   /*
00381   csom->input_neurons=-1;
00382   csom->output_neurons=-1;
00383   csom->element=-1;
00384   csom->element_current=-1;
00385   csom->epoch=-1;
00386   csom->max_epoch=-1;
00387   csom->evolution=-1;
00388   csom->max_neigh=-1;
00389   csom->rescale_sw=-1;
00390   */
00391 
00392   return 0;
00393 }
00394 
00395 //---------------------------------------------------------------------------
00396 /* *************************  imau1tocsomvect  *******************************/
00404 int imau1tocsomvect(float **data, int nb_attr, ...)
00405 {
00406 
00407   int i,j,k;
00408   va_list ap;
00409   imau1 imag;
00410 
00411   va_start(ap, nb_attr);
00412 
00413   for (i=0; i<nb_attr; i++)
00414     {
00415       imag=va_arg(ap, imau1);
00416       for(j=0; j<imag.nr; j++)
00417         for(k=0; k<imag.nc; k++)
00418           {data[i][k+j*imag.nc]=(float)imag.p[j][k]*1.00;}
00419     }
00420 
00421   va_end(ap);
00422   return 0;
00423 }
00424 
00425 //---------------------------------------------------------------------------
00426 /* *************************  csomvecttoimau1   *******************************/
00435 int csomvecttoimau1(csom_t *csom, int dimX, int dimY, imau1 *imres)
00436 {
00437   unsigned char  *colormap; /* gray level for output pixels */
00438   int eticheta;
00439   int i,j;
00440 
00441   if( (colormap=(unsigned char *)malloc((csom->output_neurons)*sizeof(unsigned char))) == NULL)
00442     {printf ("\n fatal error: a.05 allocation  impossible\n");  exit(1);}
00443 
00444   /* if the output vector will be a 8bit picture, this is his colormap */
00445   //for (i=0;i<csom->output_neurons;i++) {csom->colormap[i]=(int)show_layer[i]*floor(i*254/(csom->output_neurons-1));}
00446   for (i=0;i<csom->output_neurons;i++) {colormap[i]=floor(i*254/(csom->output_neurons-1));}
00447 
00448   imres->nc = dimX;
00449   imres->nr = dimY;
00450   sprintf(imres->nom, "csom_out");
00451 
00452   alloc_imau1(imres);
00453 
00454   for(j=0; j<imres->nr; j++)
00455     for(i=0; i<imres->nc; i++)
00456       {eticheta=csom->csom_out[i+j*imres->nc]; 
00457       imres->p[j][i] = colormap[eticheta]; 
00458       }
00459         
00460   free(colormap);
00461   colormap=NULL;
00462   return 0;
00463 }
00464 
00465 //---------------------------------------------------------------------------

Generated on Tue Apr 22 13:31:02 2008 for donnee1D by  doxygen 1.5.3