Пример #1
0
static PyObject *PyLWPR_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
   PyLWPR *self;                                                 
   int nIn,nOut;                                                 
   if (PyTuple_Size(args)==1) {                                  
      char *filename;                                            
      int ok;
                                                                 
      if (!PyArg_ParseTuple(args, "s", &filename)) return NULL;  

      self = (PyLWPR *)type->tp_alloc(type, 0);                  
                                                                 
      ok = lwpr_read_binary(&(self->model), filename);           

#if HAVE_LIBEXPAT
      if (!ok) {
         int numErrs, numWarnings;                              
         
         numErrs = lwpr_read_xml(&(self->model), filename, &numWarnings);
         if (numErrs != 0) {
            PyErr_SetString(PyExc_IOError, "Binary or XML file could not be read or parsed correctly.");
            Py_DECREF(self);
            return NULL;
         }
      }          
#else
      if (!ok) {
         PyErr_SetString(PyExc_IOError, "Binary LWPR file could not be read correctly.");
         Py_DECREF(self);
         return NULL;
      }
#endif      
      nIn = self->model.nIn;
      nOut = self->model.nOut;
   } else {
      if (!PyArg_ParseTuple(args, "ii", &nIn,&nOut)) return NULL;
   
      self = (PyLWPR *)type->tp_alloc(type, 0);

      lwpr_init_model(&self->model, nIn, nOut, NULL);
   }
    
   self->extra_in = malloc(sizeof(double) * (nIn*(nOut +1) + 3*nOut));
   self->extra_out = self->extra_in + nIn;
   self->extra_out2 = self->extra_out + nOut;
   self->extra_out3 = self->extra_out2 + nOut;
   self->extra_J = self->extra_out3 + nOut;

   return (PyObject *)self;
}
Пример #2
0
void lwpr_xml_start_element(void *userData, const char *name, const char **atts) {
   int M=0, N=0;
   const char **at;
   const char *fieldName;
   int wishM,wishN;

   LWPR_ParserData *ud = (LWPR_ParserData *) userData;
   LWPR_Model *model = ud->model;
   LWPR_SubModel *sub=NULL;
   LWPR_ReceptiveField *RF=NULL;

   ud->readN = ud->readM = ud->N = ud->M = 0;

   if (model->sub!=NULL) {
      sub = &(model->sub[ud->curSub]);
      if (sub->rf != NULL) RF = sub->rf[ud->curRF];
   }

   if (!strcmp(name,"integer")) {
      ud->curType = 1;
      if (!lwpr_xml_parse_scalar(atts,&fieldName)) {
         lwpr_xml_error(ud,"<integer> element without name.\n");
         return;
      }
   } else if (!strcmp(name,"scalar")) {
      ud->curType = 2;
      if (!lwpr_xml_parse_scalar(atts,&fieldName)) {
         lwpr_xml_error(ud,"<scalar> element without name.");
         return;
      }
   } else if (!strcmp(name,"vector")) {
      ud->curType = 3;
      if (!lwpr_xml_parse_vector(atts,&fieldName,&N)) {
         lwpr_xml_error(ud,"Parse error: <vector> element without name or length.\n");
         return;
      }
   } else if (!strcmp(name,"matrix")) {
      ud->curType = 4;
      if (!lwpr_xml_parse_matrix(atts,&fieldName,&M,&N)) {
         lwpr_xml_error(ud,"Parse error: <matrix> element without name, rows or columns.\n");
         return;
      }
   }

   if (ud->level == 0) {
      if (!strcmp(name,"LWPR")) {
         int nIn = 0,nOut = 0;
         const char *model_name = NULL;
         LWPR_Kernel kern = LWPR_GAUSSIAN_KERNEL;
         at = atts;

         ud->curType = 0;
         while (at[0]!=NULL && at[1]!=NULL) {
            if (!strcmp(at[0],"name")) {
               model_name = at[1];
            } else if (!strcmp(at[0],"nIn")) {
               nIn = atoi(at[1]);
            } else if (!strcmp(at[0],"nOut")) {
               nOut = atoi(at[1]);
            } else if (!strcmp(at[0],"kernel")) {
               kern = LWPR_GAUSSIAN_KERNEL;
               if (!strcmp(at[1],"BiSquare")) {
                  kern = LWPR_BISQUARE_KERNEL;
               } else if (!strcmp(at[1],"Bisquare")) {
                  kern = LWPR_BISQUARE_KERNEL;
               } else {
                  if (strcmp(at[1],"Gaussian")) {
                     ud->numWarnings++;
                     if (ud->errFile) fprintf(ud->errFile,"Unknown kernel, using Gaussian.\n");
                  }
               }
            }
            at+=2;
         }
         if (nIn>0 && nOut > 0) {
            lwpr_init_model(model,nIn,nOut,model_name);
            model->kernel = kern;
         } else {
            ud->numErrors++;
            if (ud->errFile) fprintf(ud->errFile,"Error parsing LWPR element.\n");
         }
         ud->level = 1;
      } else {
         lwpr_xml_report_unknown(ud,name);
      }
      return;
   }

   if (ud->level == 1) {
      if (!strcmp(name,"SubModel")) {
         int out_dim=-1;
         int numRFS=0;
         ud->curType = 0;
         at = atts;
         while (at[0]!=NULL && at[1]!=NULL) {
            if (!strcmp(at[0],"out_dim")) {
               out_dim = atoi(at[1]);
            } else if (!strcmp(at[0],"numRFS")) {
               numRFS = atoi(at[1]);
            }
            at+=2;
         }
         if (out_dim >= 0 && out_dim < model->nOut) {
            lwpr_mem_alloc_sub(&(model->sub[out_dim]), numRFS + 16);
            ud->level = 2;
            ud->curSub = out_dim;
            ud->curRF = 0;
         } else {
            ud->numErrors++;
            if (ud->errFile) fprintf(ud->errFile,"Error parsing SubModel element.\n");
         }
         return;
      }
      switch(ud->curType) {
         case 0:
            lwpr_xml_report_unknown(ud,name);
            break;
         case 1:
            ud->N = 1;
            if (!strcmp(fieldName,"n_data")) {
               ud->curPtr = (void *) &(model->n_data);
            } else if (!strcmp(fieldName,"diag_only")) {
               ud->curPtr = (void *) &(model->diag_only);
            } else if (!strcmp(fieldName,"update_D")) {
               ud->curPtr = (void *) &(model->update_D);
            } else if (!strcmp(fieldName,"meta")) {
               ud->curPtr = (void *) &(model->meta);
            } else {
               lwpr_xml_report_unknown(ud,fieldName);
            }
            break;
         case 2:
            ud->N = 1;
            if (!strcmp(fieldName,"meta_rate")) {
               ud->curPtr = (void *) &(model->meta_rate);
            } else if (!strcmp(fieldName,"penalty")) {
               ud->curPtr = (void *) &(model->penalty);
            } else if (!strcmp(fieldName,"w_gen")) {
               ud->curPtr = (void *) &(model->w_gen);
            } else if (!strcmp(fieldName,"w_prune")) {
               ud->curPtr = (void *) &(model->w_prune);
            } else if (!strcmp(fieldName,"init_lambda")) {
               ud->curPtr = (void *) &(model->init_lambda);
            } else if (!strcmp(fieldName,"final_lambda")) {
               ud->curPtr = (void *) &(model->final_lambda);
            } else if (!strcmp(fieldName,"tau_lambda")) {
               ud->curPtr = (void *) &(model->tau_lambda);
            } else if (!strcmp(fieldName,"init_S2")) {
               ud->curPtr = (void *) &(model->init_S2);
            } else if (!strcmp(fieldName,"add_threshold")) {
               ud->curPtr = (void *) &(model->add_threshold);
            } else {
               lwpr_xml_report_unknown(ud,fieldName);
            }
            break;
         case 3:
            if (!strcmp(fieldName,"mean_x")) {
               ud->curPtr = (void *) model->mean_x;
               wishN = model->nIn;
            } else if (!strcmp(fieldName,"var_x")) {
               ud->curPtr = (void *) model->var_x;
               wishN = model->nIn;
            } else if (!strcmp(fieldName,"norm_in")) {
               ud->curPtr = (void *) model->norm_in;
               wishN = model->nIn;
            } else if (!strcmp(fieldName,"norm_out")) {
               ud->curPtr = (void *) model->norm_out;
               wishN = model->nOut;
            } else {
               lwpr_xml_report_unknown(ud,fieldName);
               break;
            }
            if (wishN != N) {
               lwpr_xml_dim_error(ud,fieldName,0,wishN);
            } else {
               ud->N = N;
            }
            break;
         case 4:
            wishN = wishM = model->nIn;
            if (!strcmp(fieldName,"init_alpha")) {
               ud->curPtr = (void *) model->init_alpha;
            } else if (!strcmp(fieldName,"init_D")) {
               ud->curPtr = (void *) model->init_D;
            } else if (!strcmp(fieldName,"init_M")) {
               ud->curPtr = (void *) model->init_M;
            } else {
               lwpr_xml_report_unknown(ud,fieldName);
               break;
            }
            if (wishN != N || wishM != M) {
               lwpr_xml_dim_error(ud,fieldName,wishM,wishN);
            } else {
               ud->M = ud->N = model->nIn;
               ud->MS = model->nInStore;
            }
            break;

      }

      return;
   }
   if (ud->level == 2) {
      if (!strcmp(name,"ReceptiveField")) {
         int nReg = 0;

         at = atts;
         while (at[0]!=NULL && at[1]!=NULL) {
            if (!strcmp(at[0],"nReg")) {
               nReg = atoi(at[1]);
            }
            at+=2;
         }
         if (nReg > 0) {
            RF = lwpr_aux_add_rf(sub,nReg);
            ud->level = 3;
         } else {
            ud->numErrors++;
            if (ud->errFile) fprintf(ud->errFile,"Error parsing ReceptiveField element %d/%d.\n",ud->curSub,ud->curRF);
         }

         ud->level = 3;

         return;
      }

      ud->curPtr = NULL;
      if (ud->curType == 1 && !strcmp(fieldName,"n_pruned")) {
         ud->curPtr = (void *) &sub->n_pruned;
         ud->N = 1;
         return;
      }
      if (ud->curType == 0) {
         lwpr_xml_report_unknown(ud,name);
      } else {
         lwpr_xml_report_unknown(ud,fieldName);
      }
      return;
   }
   if (ud->level == 3) {
      ud->curPtr = NULL;
      switch(ud->curType) {
         case 0:
            lwpr_xml_report_unknown(ud,name);
            break;
         case 1:
            if (!strcmp(fieldName,"trustworthy")) {
               ud->curPtr = (void *) &RF->trustworthy;
               ud->N = 1;
            } else {
               lwpr_xml_report_unknown(ud,fieldName);
            }
            break;
         case 2:
            ud->N = 1;
            if (!strcmp(fieldName,"beta0")) {
               ud->curPtr = (void *) &RF->beta0;
            } else if (!strcmp(fieldName,"sum_e2")) {
               ud->curPtr = (void *) &RF->sum_e2;
            } else if (!strcmp(fieldName,"SSp")) {
               ud->curPtr = (void *) &RF->SSp;
            } else if (!strcmp(fieldName,"w")) {
               ud->curPtr = (void *) &RF->w;
            } else {
               lwpr_xml_report_unknown(ud,fieldName);
            }
            break;
         case 3:
            ud->N = N;
            if (!strcmp(fieldName,"beta")) {
               ud->curPtr = (void *) RF->beta;
               wishN = RF->nReg;
            } else if (!strcmp(fieldName,"c")) {
               ud->curPtr = (void *) RF->c;
               wishN = model->nIn;
            } else if (!strcmp(fieldName,"SSs2")) {
               ud->curPtr = (void *) RF->SSs2;
               wishN = RF->nReg;
            } else if (!strcmp(fieldName,"SSYres")) {
               ud->curPtr = (void *) RF->SSYres;
               wishN = RF->nReg;
            } else if (!strcmp(fieldName,"H")) {
               ud->curPtr = (void *) RF->H;
               wishN = RF->nReg;
            } else if (!strcmp(fieldName,"r")) {
               ud->curPtr = (void *) RF->r;
               wishN = RF->nReg;
            } else if (!strcmp(fieldName,"sum_w")) {
               ud->curPtr = (void *) RF->sum_w;
               wishN = RF->nReg;
            } else if (!strcmp(fieldName,"sum_e_cv2")) {
               ud->curPtr = (void *) RF->sum_e_cv2;
               wishN = RF->nReg;
            } else if (!strcmp(fieldName,"n_data")) {
               ud->curPtr = (void *) RF->n_data;
               wishN = RF->nReg;
            } else if (!strcmp(fieldName,"lambda")) {
               ud->curPtr = (void *) RF->lambda;
               wishN = RF->nReg;
            } else if (!strcmp(fieldName,"mean_x")) {
               ud->curPtr = (void *) RF->mean_x;
               wishN = model->nIn;
            } else if (!strcmp(fieldName,"var_x")) {
               ud->curPtr = (void *) RF->var_x;
               wishN = model->nIn;
            } else if (!strcmp(fieldName,"s")) {
               ud->curPtr = (void *) RF->s;
               wishN = RF->nReg;
            } else {
               lwpr_xml_report_unknown(ud,fieldName);
               return;
            }
            if (wishN != N) {
               lwpr_xml_dim_error(ud,fieldName,0,wishN);
            }
            break;
         case 4:
            ud->M = M;
            ud->N = N;
            if (!strcmp(fieldName,"D")) {
               ud->curPtr = (void *) RF->D;
               wishM = wishN = model->nIn;
            } else if (!strcmp(fieldName,"M")) {
               ud->curPtr = (void *) RF->M;
               wishM = wishN = model->nIn;
            } else if (!strcmp(fieldName,"alpha")) {
               ud->curPtr = (void *) RF->alpha;
               wishM = wishN = model->nIn;
            } else if (!strcmp(fieldName,"b")) {
               ud->curPtr = (void *) RF->b;
               wishM = wishN = model->nIn;
            } else if (!strcmp(fieldName,"h")) {
               ud->curPtr = (void *) RF->h;
               wishM = wishN = model->nIn;
            } else if (!strcmp(fieldName,"SXresYres")) {
               ud->curPtr = (void *) RF->SXresYres;
               wishM = model->nIn;
               wishN = RF->nReg;
            } else if (!strcmp(fieldName,"SSXres")) {
               ud->curPtr = (void *) RF->SSXres;
               wishM = model->nIn;
               wishN = RF->nReg;
            } else if (!strcmp(fieldName,"U")) {
               ud->curPtr = (void *) RF->U;
               wishM = model->nIn;
               wishN = RF->nReg;
            } else if (!strcmp(fieldName,"P")) {
               ud->curPtr = (void *) RF->P;
               wishM = model->nIn;
               wishN = RF->nReg;
            } else {
               lwpr_xml_report_unknown(ud,fieldName);
               return;
            }
            if (wishN != N || wishM != M) {
               lwpr_xml_dim_error(ud,fieldName,wishM,wishN);
            }
            break;
      }
   }
}
Пример #3
0
int lwpr_read_binary_fp(LWPR_Model *model, FILE *fp) {
   char str[5];
   int ok;
   int nIn,nInS,nOut;
   int i,dim;
   int version;
   
   ok = (int) fread(str, sizeof(char), 4, fp);
   if (ok!=4) return 0;
   
   str[4]=0;
   if (strcmp(str,"LWPR")!=0) return 0;  
   
   if (!lwpr_io_read_int(fp, &version)) return 0;
   
   if (version!=LWPR_BINIO_VERSION) {
      fprintf(stderr,"Sorry, version of binary LWPR file does not match this implementation.\n");
      return 0;
   }
  
   if (!lwpr_io_read_int(fp, &nIn) || !lwpr_io_read_int(fp, &nOut)) return 0;
   if (nIn<=0) return 0;
   if (nOut<=0) return 0;
   if (!lwpr_init_model(model, nIn, nOut, NULL)) return 0;
   
   ok = lwpr_io_read_int(fp, &i);
   model->kernel = (LWPR_Kernel) i;
   
   ok &= lwpr_io_read_int(fp, &i);
   
   if (i>0) {
      size_t len = (size_t) i;
      model->name = (char *) LWPR_MALLOC((len+1)*sizeof(char));
      if (model->name == NULL) return 0;
      ok &= (fread(model->name, sizeof(char), len, fp) == len)?1:0;
      model->name[i] = 0;
   }
   nInS = model->nInStore;
   
   ok &= lwpr_io_read_int(fp, &model->n_data);
   ok &= lwpr_io_read_vector(fp, nIn, model->mean_x);
   ok &= lwpr_io_read_vector(fp, nIn, model->var_x);   
   ok &= lwpr_io_read_int(fp, &model->diag_only);
   ok &= lwpr_io_read_int(fp, &model->update_D);   
   ok &= lwpr_io_read_int(fp, &model->meta);
   ok &= lwpr_io_read_scalar(fp, &model->meta_rate);
   ok &= lwpr_io_read_scalar(fp, &model->penalty);   
   ok &= lwpr_io_read_matrix(fp, nIn, nInS, nIn, model->init_alpha);
   ok &= lwpr_io_read_vector(fp, nIn, model->norm_in);
   ok &= lwpr_io_read_vector(fp, nOut, model->norm_out);   
   ok &= lwpr_io_read_matrix(fp, nIn, nInS, nIn, model->init_D);   
   ok &= lwpr_io_read_matrix(fp, nIn, nInS, nIn, model->init_M); 
   
   ok &= lwpr_io_read_scalar(fp, &model->w_gen);  
   ok &= lwpr_io_read_scalar(fp, &model->w_prune);   
   ok &= lwpr_io_read_scalar(fp, &model->init_lambda);   
   ok &= lwpr_io_read_scalar(fp, &model->final_lambda);   
   ok &= lwpr_io_read_scalar(fp, &model->tau_lambda);      
   ok &= lwpr_io_read_scalar(fp, &model->init_S2);      
   ok &= lwpr_io_read_scalar(fp, &model->add_threshold); 
   
   for (dim=0;dim<model->nOut;dim++) {
      int numRFS;
      LWPR_SubModel *sub = &model->sub[dim];   
      ok &= (fread(str, sizeof(char), 4, fp)==4)?1:0;
      str[4]=0;
      if (!ok || strcmp(str,"SUBM")!=0) {
         lwpr_free_model(model);
         return 0;
      }
      ok &= lwpr_io_read_int(fp, &i);
      ok &= (i==dim);
      ok &= lwpr_io_read_int(fp, &numRFS);      
      ok &= lwpr_io_read_int(fp, &sub->n_pruned);            
      for (i=0;i<numRFS;i++) {
         ok &= lwpr_io_read_rf(fp, sub);
      }
      ok &= (numRFS == sub->numRFS);
   }
   ok &= (fread(str, sizeof(char), 4, fp) == 4)?1:0;   
   str[4] = 0;
   if (!ok || strcmp(str,"RPWL")!=0) {
      lwpr_free_model(model);
      return 0;
   }

   return 1;
}
Пример #4
0
int main(int argc, char** argv)
{
  // Instantiate a ModelManager:
  ModelManager manager("Test LWPR");

  // Parse command-line:
  if (manager.parseCommandLine((const int)argc, (const char**)argv, "", 0, 0) == false)
    return(1);

  manager.start();

  double x[2];
  double y,yp;
  double mse;

  FILE *fp;
  LWPR_Model model;
  int i,j;

  /* This allocates some memory and sets initial values
   ** Note that the model structure itself already exists (on the stack)
   */
  lwpr_init_model(&model,2,1,"2D_Cross");

  /* Set initial distance metric to 50*(identity matrix) */
  lwpr_set_init_D_spherical(&model,50);

  /* Set init_alpha to 250 in all elements */
  lwpr_set_init_alpha(&model,250);

  /* Set w_gen to 0.2 */
  model.w_gen = 0.2;

  /* See above definition, we either use srand() on Windows or srand48 everywhere else */
  SEED_RAND();

  for (j=0;j<20;j++) {
    mse = 0.0;

    for (i=0;i<1000;i++) {
      x[0] = 2.0*URAND()-1.0;
      x[1] = 2.0*URAND()-1.0;
      y = cross(x[0],x[1]) + 0.1*URAND()-0.05;

      /* Update the model with one sample
       **
       ** x points to (x[0],x[1])  (input vector)
       ** &y points to y           (output "vector")
       ** &yp points to yp         (prediction "vector")
       **
       ** If you are interested in maximum activation, call
       ** lwpr_update(&model, x, &y, &yp, &max_w);
       */
      lwpr_update(&model, x, &y, &yp, NULL);

      mse+=(y-yp)*(y-yp);
    }
    mse/=500;
    printf("#Data = %d   #RFS = %d   MSE = %f\n",model.n_data, model.sub[0].numRFS, mse);
  }

  fp = fopen("output.txt","w");

  mse = 0.0;
  i=0;

  for (x[1]=-1.0; x[1]<=1.01; x[1]+=0.05) {
    for (x[0]=-1.0; x[0]<=1.01; x[0]+=0.05) {
      y = cross(x[0],x[1]);

      /* Use the model for predicting an output
       **
       ** x points to (x[0],x[1])     (input vector)
       ** 0.001  is the cutoff value  (clip Gaussian kernel)
       ** &yp points to yp            (prediction "vector")
       **
       ** If you are interested in confidence bounds or
       ** maximum activation, call
       ** lwpr_predict(&model, x, 0.001, &yp, &conf, &max_w);
       */
      lwpr_predict(&model, x, 0.001, &yp, NULL, NULL);

      mse += (y-yp)*(y-yp);
      i++;

      fprintf(fp,"%8.5f %8.5f %8.5f\n",x[0],x[1],yp);
    }
    fprintf(fp,"\n\n");
  }
  fclose(fp);

  printf("MSE on test data (%d) = %f\n",i,mse/(double) i);

  printf("\nTo view the output, start gnuplot, and type:\n");
  printf("   splot \"output.txt\"\n\n");

  /* Free the memory that was allocated for receptive fields etc.
   ** Note again that this does not free the LWPR_Model structure
   ** itself (but it exists on the stack, so it's automatically free'd) */
  lwpr_free_model(&model);

  // stop all our ModelComponents
  manager.stop();

  // all done!
  return 0;
}
Пример #5
0
int main() {

   double x[2],y[2],yp[2];
   double mseTr[2];
   double testErr[2],wTestErr[2];
   double binErr[2], wBinErr[2];
   double xmlErr[2], wXmlErr[2];
   double sumErr;
   
   LWPR_Model model;
   int i,j;
   int numRFS;
   
   /* This allocates some memory and sets initial values 
   ** Note that the model structure itself already exists (on the stack)
   */
   lwpr_init_model(&model,2,2,"2D_Cross");
   
   /* Set initial distance metric to 50*(identity matrix) */
   lwpr_set_init_D_spherical(&model,50);
   
   /* Set init_alpha to 250 in all elements */
   lwpr_set_init_alpha(&model,250);
   
   /* Set w_gen to 0.2 */
   model.w_gen = 0.2;

   /* See above definition, we either use srand() on Windows or srand48 everywhere else */   
   SEED_RAND();
   
   for (j=0;j<20;j++) {
      mseTr[0] = mseTr[1] = 0.0;
      
      for (i=0;i<1000;i++) {
         x[0] = 2.0*URAND()-1.0;
         x[1] = 2.0*URAND()-1.0;
         y[0] = cross(x[0],x[1]) + 0.1*URAND()-0.05;
         y[1] = y[0] + 10; /* sanity check */
         
         /* Update the model with one sample
         **
         ** x points to (x[0],x[1])  (input vector) 
         ** &y points to y           (output "vector")
         ** &yp points to yp         (prediction "vector")
         **
         ** If you are interested in maximum activation, call
         ** lwpr_update(&model, x, &y, &yp, &max_w); 
         */
         lwpr_update(&model, x, y, yp, NULL);
         
         mseTr[0]+=(y[0]-yp[0])*(y[0]-yp[0]);
         mseTr[1]+=(y[1]-yp[1])*(y[1]-yp[1]);         
      }
      mseTr[0]/=500;
      mseTr[1]/=500;      
      printf("#Data = %d   #RFS = %d / %d  MSE = %f / %f\n",model.n_data, model.sub[0].numRFS, model.sub[1].numRFS, mseTr[0], mseTr[1]);
   }
   
   if (model.n_data != 20000) {
      fprintf(stderr,"model.n_data  should have been 20*1000 = 20000. Something is very wrong!\n");
      exit(1);
   }
   
   if (model.sub[0].numRFS != model.sub[1].numRFS) {
      fprintf(stderr,"There should have been an equal number of receptive fields for both outputs :-(\n");
      exit(1);
   }       
   numRFS = model.sub[0].numRFS;
   
   testErrors(&model, testErr, wTestErr);
   printf("MSE on test data: %f / %f\n",testErr[0],  testErr[1]);
   
   if (fabs(testErr[0]-testErr[1]) > 1e-4) {
      fprintf(stderr,"MSE should be equal for both outputs, but the difference is > 1e-4\n");
      exit(1);
   }
   
   printf("Weighted MSE....: %f / %f\n",wTestErr[0], wTestErr[1]);
   if (fabs(wTestErr[0]-wTestErr[1]) > 1e-4) {
      fprintf(stderr,"Weighted MSE should be equal for both outputs, but the difference is > 1e-4\n");
      exit(1);
   }
  
   printf("Writing the model to a binary file\n");
   /* Write the model to an XML file */
   lwpr_write_binary(&model,"lwpr_cross_2d.dat");

   /* Free the memory that was allocated for receptive fields etc. */
   lwpr_free_model(&model);

   printf("Re-read the model from the binary file\n");
   /* Read a model from an XML file, memory allocation is done automatically,
   ** but later lwpr_free_model has to be called again */
   j=lwpr_read_binary(&model,"lwpr_cross_2d.dat");
   remove("lwpr_cross_2d.dat");
   
   if (j==0) {
      fprintf(stderr,"File could not be read, aborting\n");
      exit(1);
   }
   printf("#Data = %d   #RFS = %d / %d\n",model.n_data, model.sub[0].numRFS, model.sub[1].numRFS);
   if (model.n_data != 20000 || model.sub[0].numRFS!=numRFS || model.sub[1].numRFS!=numRFS) {
      fprintf(stderr,"Model (from binary file) seems to be broken :-(\n");
      exit(1);
   }
   
   testErrors(&model, binErr, wBinErr);
   printf("MSE on test data: %f / %f\n",binErr[0],  binErr[1]);
   printf("Weighted MSE....: %f / %f\n",wBinErr[0], wBinErr[1]);
   
   sumErr = fabs(binErr[0] - testErr[0]) + fabs(binErr[1] - testErr[1]);
   sumErr+= fabs(wBinErr[0] - wTestErr[0]) + fabs(wBinErr[1] - wTestErr[1]);
   
   if (sumErr>1e-8) {
      fprintf(stderr,"Error statistics from the binary-IO LWPR model are not the same :-(\n");
      exit(1);
   }
   
   
#if HAVE_LIBEXPAT
   printf("Writing the model to an XML file\n");


   /* Write the model to an XML file */
   lwpr_write_xml(&model,"lwpr_cross_2d.xml");

   /* Free the memory that was allocated for receptive fields etc. */
   lwpr_free_model(&model);

   /* Read a model from an XML file, memory allocation is done automatically,
   ** but later lwpr_free_model has to be called again */
   j=lwpr_read_xml(&model,"lwpr_cross_2d.xml",&i);
   remove("lwpr_cross_2d.xml");

   printf("Re-read the model from the XML file\n");
   printf("%d errors   %d warnings\n",j,i);
   if (j!=0) {
      printf("Errors detected, aborting\n");
      exit(1);
   }

   printf("#Data = %d   #RFS = %d / %d\n",model.n_data, model.sub[0].numRFS, model.sub[1].numRFS);
   if (model.n_data != 20000 || model.sub[0].numRFS!=numRFS || model.sub[1].numRFS!=numRFS) {
      fprintf(stderr,"Model (from XML file) seems to be broken :-(\n");
      exit(1);
   }

   testErrors(&model, xmlErr, wXmlErr);
   printf("MSE on test data: %f / %f\n",xmlErr[0],  xmlErr[1]);
   printf("Weighted MSE....: %f / %f\n",wXmlErr[0], wXmlErr[1]);
   
   sumErr = fabs(xmlErr[0] - testErr[0]) + fabs(xmlErr[1] - testErr[1]);
   sumErr+= fabs(wXmlErr[0] - wTestErr[0]) + fabs(wXmlErr[1] - wTestErr[1]);
   
   sumErr/=fabs(testErr[0]) + fabs(testErr[1]) + fabs(wTestErr[0]) + fabs(wTestErr[1]);
   printf("Relative difference to the original model: %f\n",sumErr);
   
   if (sumErr>0.0001) {
      fprintf(stderr,"Error statistics from the XML-IO LWPR model differ too much :-(\n");
      exit(1);
   }
   
#else

   printf("LWPR library has been compiled without EXPAT support, XML IO will not be tested.\n");

#endif
         
   /* Free the memory that was allocated for receptive fields etc. 
   ** Note again that this does not free the LWPR_Model structure
   ** itself (but it exists on the stack, so it's automatically free'd) */
   lwpr_free_model(&model);
   exit(0);
}