Update of /cvsroot/pure-data/externals/ann/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17348
Modified Files: ann_mlp.c Log Message: some bugfixes and changes ...
Index: ann_mlp.c =================================================================== RCS file: /cvsroot/pure-data/externals/ann/src/ann_mlp.c,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** ann_mlp.c 29 Jun 2005 22:17:37 -0000 1.8 --- ann_mlp.c 23 Jul 2005 21:16:10 -0000 1.9 *************** *** 6,9 **** --- 6,15 ---- this software is licensed under the GNU General Public License */ + + /* + hacked by Georg Holzmann for some additional methods, bug fixes, ... + 2005, grh@mur.at + */ + #include <stdio.h> #include <string.h> *************** *** 22,28 **** #define RUN 1
- #define MAXINPUT 1024 - #define MAXOUTPUT 256 - static t_class *ann_mlp_class;
--- 28,31 ---- *************** *** 36,42 **** --- 39,83 ---- unsigned int max_iterations; unsigned int iterations_between_reports; + fann_type *input; // grh: storage for input + t_atom *output; // grh: storage for output (t_atom) + fann_type *out_float; // grh: storage for output (fann_type) + t_canvas *x_canvas; t_outlet *l_out, *f_out; } t_ann_mlp;
+ // allocation + static void ann_mlp_allocate_storage(t_ann_mlp *x) + { + int i; + + if(!x->ann) + return; + + x->input = (fann_type *)getbytes(x->ann->num_input*sizeof(fann_type)); + x->output = (t_atom *)getbytes(x->ann->num_output*sizeof(t_atom)); + x->out_float = (fann_type *)getbytes(x->ann->num_output*sizeof(fann_type)); + + // init storage with zeros + for (i=0; i<x->ann->num_input; i++) + x->input[i]=0; + for (i=0; i<x->ann->num_output; i++) + { + SETFLOAT(x->output+i, 0); + x->out_float[i]=0; + } + } + + // deallocation + static void ann_mlp_free(t_ann_mlp *x) + { + if(!x->ann) + return; + + freebytes(x->input, x->ann->num_input * sizeof(fann_type)); + freebytes(x->output, x->ann->num_output * sizeof(t_atom)); + freebytes(x->out_float, x->ann->num_output * sizeof(fann_type)); + fann_destroy(x->ann); + } + static void ann_mlp_help(t_ann_mlp *x) { *************** *** 56,112 **** unsigned int num_output = 1; unsigned int num_layers = 3; ! unsigned int num_neurons_hidden = 3; float connection_rate = 1; float learning_rate = (float)0.7; ! ! if (argc>0) num_input = atom_getint(argv++);
! if (argc>1) num_output = atom_getint(argv++);
! if (argc>2) ! num_layers = atom_getint(argv++); ! ! if (argc>3) ! num_neurons_hidden = atom_getint(argv++); ! ! if (argc>4) connection_rate = atom_getfloat(argv++);
! if (argc>5) learning_rate = atom_getfloat(argv++);
! if (num_input>MAXINPUT) ! { ! error("too many inputs, maximum allowed is MAXINPUT"); ! return; ! } ! ! if (num_output>MAXOUTPUT) ! { ! error("too many outputs, maximum allowed is MAXOUTPUT"); ! return; ! } ! ! x->ann = fann_create(connection_rate, learning_rate, num_layers, ! num_input, num_neurons_hidden, num_output);
fann_set_activation_function_hidden(x->ann, FANN_SIGMOID_SYMMETRIC); fann_set_activation_function_output(x->ann, FANN_SIGMOID_SYMMETRIC); ! ! if (x->ann == 0) ! { ! error("error creating the ann"); ! } else ! { ! post("created ann with:"); ! post("num_input = %i", num_input); ! post("num_output = %i", num_output); ! post("num_layers = %i", num_layers); ! post("num_neurons_hidden = %i", num_neurons_hidden); ! post("connection_rate = %f", connection_rate); ! post("learning_rate = %f", learning_rate); ! } }
--- 97,188 ---- unsigned int num_output = 1; unsigned int num_layers = 3; ! unsigned int *neurons_per_layer = NULL; ! int activated=0; ! int i, count_args = 0; float connection_rate = 1; float learning_rate = (float)0.7; ! ! ! // okay, start parsing init args ... ! ! if (argc > count_args++) num_input = atom_getint(argv++);
! if (argc > count_args++) num_output = atom_getint(argv++);
! if (argc > count_args++) ! { ! int hidden=0; ! ! num_layers = atom_getint(argv++); ! hidden = num_layers-2; ! ! neurons_per_layer = (unsigned int *)getbytes(num_layers*sizeof(unsigned int)); ! ! neurons_per_layer[0] = num_input; ! ! // make standard initialization (if there are too few init args) ! for (i=1; i<hidden+1; i++) ! neurons_per_layer[i] = 3; ! ! // now check init args ! for (i=1; i<hidden+1; i++) ! { ! if (argc > count_args++) ! neurons_per_layer[i] = atom_getint(argv++); ! } ! ! neurons_per_layer[num_layers-1] = num_output; ! ! activated=1; ! } ! ! if (argc > count_args++) connection_rate = atom_getfloat(argv++);
! if (argc > count_args++) learning_rate = atom_getfloat(argv++);
! // make one hidden layer as standard, if there were too few init args ! if(!activated) ! { ! neurons_per_layer = (unsigned int *)getbytes(3*sizeof(unsigned int)); ! neurons_per_layer[0] = num_input; ! neurons_per_layer[1] = 3; ! neurons_per_layer[2] = num_output; ! }
+ // ... end of parsing init args + + + if(x->ann) + ann_mlp_free(x); + + x->ann = fann_create_array(connection_rate, learning_rate, num_layers, neurons_per_layer); + + // deallocate helper array + freebytes(neurons_per_layer, num_layers * sizeof(unsigned int)); + + if(!x->ann) + { + error("error creating the ann"); + return; + } + + ann_mlp_allocate_storage(x); fann_set_activation_function_hidden(x->ann, FANN_SIGMOID_SYMMETRIC); fann_set_activation_function_output(x->ann, FANN_SIGMOID_SYMMETRIC); ! ! // set error log to stdout, so that you see it in the pd console ! //fann_set_error_log((struct fann_error*)x->ann, stdout); ! // unfortunately this doesn't work ... but it should do in a similar way !! ! ! post("created ann with:"); ! post("num_input = %i", num_input); ! post("num_output = %i", num_output); ! post("num_layers = %i", num_layers); ! post("connection_rate = %f", connection_rate); ! post("learning_rate = %f", learning_rate); }
*************** *** 150,157 **** }
! ! ! static void ann_mlp_train_on_file(t_ann_mlp *x, t_symbol *sl, int argc, t_atom *argv) { if (x->ann == 0) { --- 226,235 ---- }
! static void ann_mlp_train_on_file(t_ann_mlp *x, t_symbol *s) { + // make correct path + char patcher_path[MAXPDSTRING]; + char filename[MAXPDSTRING]; + if (x->ann == 0) { *************** *** 160,173 **** }
! if (argc<1) ! { ! error("you must specify the filename with training data"); ! return; ! } else ! { ! x->filenametrain = atom_gensym(argv); ! }
! //post("nn: starting training on file %s, please be patient and wait for my next message (it could take severeal minutes to complete training)", x->filenametrain->s_name);
fann_train_on_file(x->ann, x->filenametrain->s_name, x->max_iterations, --- 238,250 ---- }
! // make correct path ! canvas_makefilename(x->x_canvas, s->s_name, patcher_path, MAXPDSTRING); ! sys_bashfilename(patcher_path, filename); ! x->filenametrain = gensym(filename);
! if(!x->filenametrain) ! return; ! ! post("nn: starting training on file %s, please be patient and wait ... (it could take severeal minutes to complete training)", x->filenametrain->s_name);
fann_train_on_file(x->ann, x->filenametrain->s_name, x->max_iterations, *************** *** 221,235 **** }
- // run the ann using floats in list passed to the inlet as input values // and send result to outlet as list of float static void ann_mlp_run_the_net(t_ann_mlp *x, t_symbol *sl, int argc, t_atom *argv) { ! int i=0; ! fann_type input[MAXINPUT]; fann_type *calc_out; - t_atom lista[MAXOUTPUT]; - int quanti; - float valoreTMP;
if (x->ann == 0) --- 298,307 ---- }
// run the ann using floats in list passed to the inlet as input values // and send result to outlet as list of float static void ann_mlp_run_the_net(t_ann_mlp *x, t_symbol *sl, int argc, t_atom *argv) { ! int i=0; fann_type *calc_out;
if (x->ann == 0) *************** *** 238,279 **** return; } ! ! quanti = x->ann->num_output; ! ! // fill input array with zeros ! for (i=0; i<MAXINPUT; i++) ! { ! input[i]=0; ! } ! ! // fill output array with zeros ! for (i=0; i<MAXOUTPUT; i++) ! { ! SETFLOAT(lista + i,0); ! }
// fill input array with actual data sent to inlet ! for (i=0;i<argc;i++) { ! input[i] = atom_getfloat(argv++); } // run the ann ! calc_out = fann_run(x->ann, input);
// fill the output array with result from ann ! for (i=0;i<quanti;i++) ! { ! valoreTMP = calc_out[i]; ! //post("calc_out[%i]=%f", i, calc_out[i]); ! SETFLOAT(lista+i, valoreTMP); ! }
// send output array to outlet ! outlet_anything(x->l_out, ! gensym("list") , ! quanti, ! lista); ! }
--- 310,336 ---- return; } ! ! if(argc < x->ann->num_input) ! { ! error("ann_mlp: too few input values!!"); ! return; ! }
// fill input array with actual data sent to inlet ! for (i=0;i<x->ann->num_input;i++) { ! x->input[i] = atom_getfloat(argv++); } // run the ann ! calc_out = fann_run(x->ann, x->input);
// fill the output array with result from ann ! for (i=0;i<x->ann->num_output;i++) ! SETFLOAT(x->output+i, calc_out[i]);
// send output array to outlet ! outlet_anything(x->l_out, gensym("list"), ! x->ann->num_output, x->output); }
*************** *** 281,290 **** { int i=0; ! fann_type input[MAXINPUT]; ! fann_type output[MAXOUTPUT]; ! //fann_type *calcMSE; ! //t_atom lista[MAXOUTPUT]; ! int quantiINs; ! int quantiOUTs; float mse;
--- 338,342 ---- { int i=0; ! int quantiINs, quantiOUTs; float mse;
*************** *** 304,338 **** }
- // fill input array with zeros - for (i=0; i<MAXINPUT; i++) - { - input[i]=0; - } - // fill input array with zeros - for (i=0; i<MAXOUTPUT; i++) - { - output[i]=0; - } - // fill input array with actual data sent to inlet for (i=0;i<quantiINs;i++) ! { ! input[i] = atom_getfloat(argv++); ! }
for (i=0;i<quantiOUTs;i++) ! { ! output[i] = atom_getfloat(argv++); ! } //fann_reset_MSE(x->ann);
! fann_train(x->ann, input, output);
mse = fann_get_MSE(x->ann); outlet_float(x->f_out, mse); - - }
--- 356,373 ---- }
// fill input array with actual data sent to inlet for (i=0;i<quantiINs;i++) ! x->input[i] = atom_getfloat(argv++);
for (i=0;i<quantiOUTs;i++) ! x->out_float[i] = atom_getfloat(argv++); //fann_reset_MSE(x->ann);
! fann_train(x->ann, x->input, x->out_float);
mse = fann_get_MSE(x->ann); outlet_float(x->f_out, mse); }
*************** *** 347,379 **** }
! static void ann_mlp_set_filename(t_ann_mlp *x, t_symbol *sl, int argc, t_atom *argv) { ! if (argc>0) { ! x->filename = atom_gensym(argv); ! } else ! { ! error("you must specify the filename"); ! } ! post("nn:filename set to %s", x->filename->s_name); }
! static void ann_mlp_load_ann_from_file(t_ann_mlp *x, t_symbol *sl, int argc, t_atom *argv) { ! if (argc>0) { ! x->filename = atom_gensym(argv); ! } ! x->ann = fann_create_from_file(x->filename->s_name); ! if (x->ann == 0) ! error("error opening %s", x->filename->s_name); ! else ! post("nn:ann loaded fom file %s", x->filename->s_name); }
! static void ann_mlp_save_ann_to_file(t_ann_mlp *x, t_symbol *sl, int argc, t_atom *argv) { ! if (argc>0) { ! x->filename = atom_gensym(argv); ! } ! if (x->ann == 0) { error("ann is not initialized"); --- 382,436 ---- }
! static void ann_mlp_set_filename(t_ann_mlp *x, t_symbol *s) { ! // make correct path ! char patcher_path[MAXPDSTRING]; ! char filename[MAXPDSTRING]; ! ! if(!s) ! return; ! ! // make correct path ! canvas_makefilename(x->x_canvas, s->s_name, patcher_path, MAXPDSTRING); ! sys_bashfilename(patcher_path, filename); ! x->filename = gensym(filename); }
! static void ann_mlp_load_ann_from_file(t_ann_mlp *x, t_symbol *s) { ! ann_mlp_set_filename(x,s); ! ! if(!x->filename) ! { ! error("ann: no filename !!!"); ! return; ! } ! ! // deallocate storage ! if(x->ann) ! ann_mlp_free(x); ! ! x->ann = fann_create_from_file(x->filename->s_name); ! ! if (x->ann == 0) ! error("error opening %s", x->filename->s_name); ! else ! post("nn:ann loaded fom file %s", x->filename->s_name); ! ! // allocate storage ! ann_mlp_allocate_storage(x); }
! static void ann_mlp_save_ann_to_file(t_ann_mlp *x, t_symbol *s) { ! ann_mlp_set_filename(x,s); ! ! if(!x->filename) ! { ! error("ann: no filename !!!"); ! return; ! } ! ! if (x->ann == 0) { error("ann is not initialized"); *************** *** 467,470 **** --- 524,621 ---- }
+ static void ann_mlp_set_activation_function_hidden(t_ann_mlp *x, t_symbol *sl, int argc, t_atom *argv) + { + t_symbol *parametro = 0; + int funzione = 0; + + if (x->ann == 0) + { + error("ann not initialized"); + return; + } + + if (argc>0) { + parametro = atom_gensym(argv); + if (strcmp(parametro->s_name, "FANN_THRESHOLD")==0) + funzione = FANN_THRESHOLD; + if (strcmp(parametro->s_name, "FANN_THRESHOLD_SYMMETRIC")==0) + funzione = FANN_THRESHOLD_SYMMETRIC; + if (strcmp(parametro->s_name, "FANN_LINEAR")==0) + funzione = FANN_LINEAR; + if (strcmp(parametro->s_name, "FANN_SIGMOID")==0) + funzione = FANN_SIGMOID; + if (strcmp(parametro->s_name, "FANN_SIGMOID_STEPWISE")==0) + funzione = FANN_SIGMOID_STEPWISE; + if (strcmp(parametro->s_name, "FANN_SIGMOID_SYMMETRIC")==0) + funzione = FANN_SIGMOID_SYMMETRIC; + if (strcmp(parametro->s_name, "FANN_SIGMOID_SYMMETRIC_STEPWISE")==0) + funzione = FANN_SIGMOID_SYMMETRIC_STEPWISE; + fann_set_activation_function_hidden(x->ann, funzione); + } else + { + error("you must specify the activation function"); + } + post("nn:activation function set to %s (%i)", parametro->s_name, funzione); + + } + + static void ann_mlp_randomize_weights(t_ann_mlp *x, t_symbol *sl, int argc, t_atom *argv) + { + t_float min = -1; + t_float max = 1; + + if(!x->ann) + { + post("ann_mlp: ann is not initialized"); + return; + } + + if (argc>0) + min = atom_getfloat(argv++); + + if (argc>1) + max = atom_getfloat(argv++); + + fann_randomize_weights(x->ann, min, max); + } + + static void ann_mlp_learnrate(t_ann_mlp *x, t_float f) + { + int learnrate = 0; + + if(!x->ann) + { + post("ann_mlp: ann is not initialized"); + return; + } + + learnrate = (f<0) ? 0 : f; + fann_set_learning_rate(x->ann, learnrate); + } + + static void ann_mlp_set_activation_steepness_hidden(t_ann_mlp *x, t_float f) + { + if(!x->ann) + { + post("ann_mlp: ann is not initialized"); + return; + } + + fann_set_activation_steepness_hidden(x->ann, f); + } + + static void ann_mlp_set_activation_steepness_output(t_ann_mlp *x, t_float f) + { + if(!x->ann) + { + post("ann_mlp: ann is not initialized"); + return; + } + + fann_set_activation_steepness_output(x->ann, f); + } + + void fann_set_activation_steepness_hidden(struct fann * ann, fann_type steepness); + static void ann_mlp_print_ann_details(t_ann_mlp *x) { *************** *** 492,495 **** --- 643,657 ---- }
+ static void ann_mlp_print_ann_print(t_ann_mlp *x) + { + if(!x->ann) + { + post("ann_mlp: ann is not initialized"); + return; + } + + fann_print_connections(x->ann); + fann_print_parameters(x->ann); + }
static void *ann_mlp_new(t_symbol *s, int argc, t_atom *argv) *************** *** 503,510 **** x->iterations_between_reports = 1000; x->mode=RUN;
if (argc>0) { x->filename = atom_gensym(argv); ! ann_mlp_load_ann_from_file(x, NULL , 0, NULL); }
--- 665,679 ---- x->iterations_between_reports = 1000; x->mode=RUN; + x->x_canvas = canvas_getcurrent(); + x->filename = NULL; + x->filenametrain = NULL; + x->ann = NULL; + x->input = NULL; + x->output = NULL; + x->out_float = NULL;
if (argc>0) { x->filename = atom_gensym(argv); ! ann_mlp_load_ann_from_file(x, NULL); }
*************** *** 512,523 **** }
- // free resources - static void ann_mlp_free(t_ann_mlp *x) - { - struct fann *ann = x->ann; - fann_destroy(ann); - // TODO: free other resources! - } - void ann_mlp_setup(void) { post(""); --- 681,684 ---- *************** *** 539,548 **** class_addmethod(ann_mlp_class, (t_method)ann_mlp_run, gensym("run"), 0); class_addmethod(ann_mlp_class, (t_method)ann_mlp_set_mode, gensym("setmode"), A_GIMME, 0); ! class_addmethod(ann_mlp_class, (t_method)ann_mlp_train_on_file, gensym("train-on-file"), A_GIMME, 0); class_addmethod(ann_mlp_class, (t_method)ann_mlp_manage_list, gensym("data"), A_GIMME, 0); ! class_addmethod(ann_mlp_class, (t_method)ann_mlp_set_filename, gensym("filename"), A_GIMME, 0); ! class_addmethod(ann_mlp_class, (t_method)ann_mlp_load_ann_from_file, gensym("load"),A_GIMME, 0); ! class_addmethod(ann_mlp_class, (t_method)ann_mlp_save_ann_to_file, gensym("save"),A_GIMME, 0); class_addmethod(ann_mlp_class, (t_method)ann_mlp_print_ann_details, gensym("details"), 0); // change training parameters --- 700,710 ---- class_addmethod(ann_mlp_class, (t_method)ann_mlp_run, gensym("run"), 0); class_addmethod(ann_mlp_class, (t_method)ann_mlp_set_mode, gensym("setmode"), A_GIMME, 0); ! class_addmethod(ann_mlp_class, (t_method)ann_mlp_train_on_file, gensym("train-on-file"), A_DEFSYMBOL, 0); class_addmethod(ann_mlp_class, (t_method)ann_mlp_manage_list, gensym("data"), A_GIMME, 0); ! class_addmethod(ann_mlp_class, (t_method)ann_mlp_set_filename, gensym("filename"), A_DEFSYMBOL, 0); ! class_addmethod(ann_mlp_class, (t_method)ann_mlp_load_ann_from_file, gensym("load"),A_DEFSYMBOL, 0); ! class_addmethod(ann_mlp_class, (t_method)ann_mlp_save_ann_to_file, gensym("save"),A_DEFSYMBOL, 0); class_addmethod(ann_mlp_class, (t_method)ann_mlp_print_ann_details, gensym("details"), 0); + class_addmethod(ann_mlp_class, (t_method)ann_mlp_print_ann_print, gensym("print"), 0); // change training parameters *************** *** 550,553 **** --- 712,716 ---- class_addmethod(ann_mlp_class, (t_method)ann_mlp_set_max_iterations, gensym("max_iterations"),A_GIMME, 0); class_addmethod(ann_mlp_class, (t_method)ann_mlp_set_iterations_between_reports, gensym("iterations_between_reports"),A_GIMME, 0); + class_addmethod(ann_mlp_class, (t_method)ann_mlp_learnrate, gensym("learnrate"), A_FLOAT, 0);
// change training and activation algorithms *************** *** 557,561 **** --- 720,730 ---- class_addmethod(ann_mlp_class, (t_method)ann_mlp_set_FANN_TRAIN_QUICKPROP, gensym("FANN_TRAIN_QUICKPROP"), 0); class_addmethod(ann_mlp_class, (t_method)ann_mlp_set_activation_function_output, gensym("set_activation_function_output"),A_GIMME, 0); + class_addmethod(ann_mlp_class, (t_method)ann_mlp_set_activation_function_hidden, gensym("set_activation_function_hidden"),A_GIMME, 0); + class_addmethod(ann_mlp_class, (t_method)ann_mlp_set_activation_steepness_hidden, gensym("set_activation_steepness_hidden"), A_FLOAT, 0); + class_addmethod(ann_mlp_class, (t_method)ann_mlp_set_activation_steepness_output, gensym("set_activation_steepness_output"), A_FLOAT, 0); + // initialization: + class_addmethod(ann_mlp_class, (t_method)ann_mlp_randomize_weights, gensym("randomize_weights"),A_GIMME, 0); + // the most important one: running the ann class_addlist(ann_mlp_class, (t_method)ann_mlp_manage_list);