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; }
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; } } }
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; }
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; }
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); }