NNetwork.cpp

gehe zur Dokumentation dieser Datei
00001 #include "NNetwork.h"
00002 #include "gui_debug.h"
00003 
00004 #include <doublefann.h>
00005 
00006 
00007 #include <ios>
00008 #include <iostream>
00009 #include <fstream>
00010 #include <iomanip>
00011 #include <stdio.h>
00012 
00013 using std::cout;
00014 using std::cerr;
00015 using std::endl;
00016 using namespace std;
00017 using std::setw;
00018 using std::left;
00019 using std::right;
00020 using std::showpos;
00021 using std::noshowpos;
00022 
00023 unsigned long int LAST_EPOCHS=0;
00024 double LAST_ERROR = 0;
00025 
00037 int FANN_API print_callback(struct fann *ann, struct fann_train_data *train,                           unsigned int max_epochs, unsigned int epochs_between_reports, float desired_error, unsigned int epochs){
00038     cout << "Epochs     " << setw(8) << epochs << ". "
00039         << "current error: " << left << fann_get_MSE(ann) << right << endl;
00040     LAST_EPOCHS = epochs;
00041     LAST_ERROR = fann_get_MSE(ann);
00042     return 0;
00043 }
00044 
00052 void Network::setMinMaxInputOutputValues  (double _minInput, double _maxInput, double _minOutput, double _maxOutput) {
00053 
00054    DBG();
00055    this->minInputValue = _minInput;
00056    this->maxInputValue = _maxInput;
00057    this->minOutputValue = _minOutput;
00058    this->maxOutputValue = _maxOutput;
00059 
00060    cout  <<"minInputValue=" <<this->minInputValue
00061       <<", maxInputValue=" <<this->maxInputValue <<endl
00062       <<"minOutputValue=" <<this->minOutputValue
00063       <<", maxOutputValue=" <<this->maxOutputValue
00064       <<endl;
00065 }
00066 
00071 void Network::trainNet (NETWORKTRAININGRESULTS *_results) {
00072    DBG();
00073    // Anzahl von inputs, outputs sowie trainingsdatacount an dateianfang setzen
00074    if (dataFile != NULL) {
00075       // An Dateianfang gehen
00076       rewind(dataFile) ;
00077 
00078       // Header schreiben
00079       fprintf (dataFile, "%d %d %d", this->dataCount, this->num_input, this->num_output);
00080       fclose(dataFile);
00081 
00082       dataFile = NULL;
00083    }
00084 
00085    // Falls noch kein Network geladen, wird eins erzeugt und die Counter zur�ckgesetzt
00086    if (this->ann == NULL) {
00087       this->clear();
00088       LAST_EPOCHS=0;
00089    }
00090 
00091    cout <<"maxInputValue=" <<maxInputValue << ", minInputValue=" <<minInputValue <<endl;
00092    cout <<"maxOutputValue=" <<maxOutputValue << ", minOutputValue=" <<minOutputValue <<endl;
00093 
00094    // Error-Funktion linear
00095    fann_set_train_error_function(this->ann, FANN_ERRORFUNC_LINEAR);
00096 
00097    // Activation-Function setzen
00098    fann_set_activation_function_hidden(
00099    this->ann, FANN_SIGMOID_SYMMETRIC);
00100 
00101    fann_set_activation_function_output(
00102 
00103    this->ann, FANN_SIGMOID_SYMMETRIC);
00104 
00105    // Activation-Stepness setzen
00106    fann_set_activation_steepness_hidden(
00107       this->ann, this->activation_stepness_hidden);
00108    fann_set_activation_steepness_output(
00109       this->ann, this->activation_stepness_output);
00110 
00111    cout <<"Training network on datafile: " <<this->dataFilename
00112         <<", max_iterations=" <<this->max_iterations 
00113         <<", iterations_between_reports=" <<this->iterations_between_reports 
00114         <<", desired_error=" <<this->desired_error 
00115              <<", trainingDataCount=" <<this->dataCount <<endl;
00116 
00117    fann_print_parameters(this->ann);
00118 
00119    fann_set_callback(this->ann, print_callback);
00120    fann_train_on_file(this->ann, this->dataFilename, max_iterations, iterations_between_reports, desired_error);
00121 
00122    // Anzahl der Trainingsepochen erg�nzen
00123    _results->total_epochs += LAST_EPOCHS;
00124    _results->error = LAST_ERROR;
00125    _results->last_epochs = LAST_EPOCHS;
00126    _results->trainError = this->desired_error;
00127    _results->max_epochs = this->max_iterations;
00128    
00129    cout <<"Saving network to file: " <<this->networkFilename <<endl; 
00130    fann_save(ann, networkFilename);
00131 }
00132 
00144 void Network::setParameters(int _max_epochs, int _iterations_between_report, double _desired_error, double _dEta, double _activation_stepness_hidden, double _activation_stepness_output, int _activation_function_hidden, int _activation_function_output) {
00145    DBG();
00146    cout <<"setting network training parameters: max_epochs=" << _max_epochs 
00147         <<", iterations_between_report=" <<_iterations_between_report
00148              <<", desired_error=" <<_desired_error 
00149         <<", activation_function_hidden=" <<_activation_function_hidden 
00150         <<", activation_stepness_hidden=" <<_activation_stepness_hidden
00151         <<", activation_function_output=" <<_activation_function_output 
00152         <<", activation_stepness_output=" <<_activation_stepness_output <<endl;
00153    this->max_iterations = _max_epochs;
00154    this->iterations_between_reports = _iterations_between_report;
00155    this->desired_error = _desired_error;
00156    this->activation_stepness_hidden = _activation_stepness_hidden;
00157 
00158    this->activation_stepness_output = _activation_stepness_output;
00159 
00160    if (_activation_function_hidden==0) {
00161       this->activation_function_hidden = FANN_SIGMOID;
00162    } else if (_activation_function_hidden==1) {
00163       this->activation_function_hidden = FANN_SIGMOID_SYMMETRIC;
00164    } else  {
00165       this->activation_function_hidden = FANN_LINEAR;
00166    }
00167 
00168    if (_activation_function_output==0) {
00169       this->activation_function_output = FANN_SIGMOID;
00170    } else if (_activation_function_output==1) {
00171       this->activation_function_output = FANN_SIGMOID_SYMMETRIC;
00172    } else {
00173       this->activation_function_output = FANN_LINEAR;
00174    }
00175 }
00176 
00181 void Network::setDesiredError(double _desired_error) {
00182    DBG();
00183    cout <<"setting desired_error=" <<_desired_error <<endl;
00184    this->desired_error = _desired_error;
00185 }
00186 
00188 Network::~Network() {
00189    
00190    // Network wieder freigeben
00191    DBG();
00192    if (this->ann != NULL) fann_destroy(this->ann);
00193 }
00194 
00196 void Network::createNewTrainingDataFile() {
00197 
00198    DBG();
00199    // Wenn Datei noch ge�ffnet => schlie�en
00200    if (dataFile != NULL) fclose(dataFile);
00201 
00202    // und wieder neu zum �berschreiben �ffnen
00203    dataFile = fopen(this->dataFilename, "w+");
00204    fprintf (dataFile, "                ");
00205 
00206    // Datensatz-Z�hler zur�cksetzen
00207    this->dataCount=0;
00208 }
00209 
00218 Network::Network(int _num_input, int _num_output, int _num_layers, int _num_neurons_hidden, const char* _netName) {
00219 
00220    DBG();
00221    // Initialparameter
00222    this->connection_rate = 1;
00223    this->learning_rate_eta = 0.9;
00224    this->num_input = _num_input;
00225    this->num_output = _num_output;
00226    this->num_layers = _num_layers;
00227    this->num_neurons_hidden = _num_neurons_hidden;
00228    this->activation_stepness_hidden=this->activation_stepness_output=0.01;
00229    // Standardm�ssig sigmoide aktivierung
00230    this->activation_function_hidden=this->activation_function_output=FANN_SIGMOID_SYMMETRIC;
00231    
00232    this->desired_error = 0.00003;
00233    this->max_iterations = 10000;
00234    this->iterations_between_reports = 1000;
00235    this->dataCount=0;
00236 
00237    this->num_input = _num_input;
00238    this->num_output = _num_output;
00239    this->num_layers = _num_layers;
00240    this->num_neurons_hidden = _num_neurons_hidden;
00241 
00242    /************************************************************
00243     * Dateien zum speichern der Daten sowie des Networkes erzeugen
00244     ***********************************************************/
00245    sprintf (this->dataFilename, "/tmp/nn-%s.data", _netName);
00246    sprintf (this->networkFilename, "/tmp/nn-%s.net", _netName);
00247    printf ("NN-Datei: %s, NN-Datendatei: %s\n", this->networkFilename, this->dataFilename);
00248 
00249    dataFile = fopen(this->dataFilename, "w+");
00250    // Datensatz-Z�hler zur�cksetzen
00251    this->dataCount=0;
00252 
00253    // Zeichen, dass noch kein Network existiert setzen
00254    this->ann = NULL;
00255 }
00256 
00262 void Network::addTrainingData(double in[], double out[]) {
00263 
00264    char printString[200];
00265 
00266    // Erstes Input-Neuron  
00267    sprintf (printString, "adding traindata: in[%f(%f)", in[0], normIn(in[0]));
00268    fprintf (dataFile, "\n%.30f", normIn(in[0]));
00269 
00270    // ggf. weitere Input-Neuronen
00271    for (unsigned int i=1; i<this->num_input; i++) {
00272       sprintf(printString, "%s,%f(%f)", printString, in[i], normIn(in[i]));
00273       fprintf (dataFile, " %.30f", normIn(in[i]));
00274    }
00275 
00276    // Erstes Output-Neuron
00277    sprintf (printString, "%s], out[%f(%f)", printString, out[0], normOut(out[0]));
00278    fprintf (dataFile, "\n%.30f", normOut(out[0]));
00279 
00280    // ggf. weitere Output-Neuronen
00281    for (unsigned int i=1; i<this->num_output; i++) {
00282       sprintf(printString, "%s,%f(%f)", printString, out[i], normOut(out[i]));
00283       fprintf (dataFile, " %.30f", normOut(out[i]));
00284    }
00285 
00286    // Zeilenende
00287    sprintf (printString, "%s]\n", printString);
00288 
00289    // Datenz�hler inkrementieren
00290    dataCount++;   
00291 
00292    // Ausgabe des Trainingsdatensatzes auf Bildschirm
00293 }
00294 
00300 void Network::getNetValue(double in[], double out[]) {
00301 
00302    fann_type *normalizedIn = new fann_type[this->num_input];
00303    fann_type *calc_out = new fann_type[this->num_output];
00304 
00305    // Input im Skalierungsbereich -1..1 normalisieren
00306    for (unsigned int i=0; i<this->num_input; i++) {
00307       normalizedIn[i] = normIn(in[i]);
00308    }
00309       
00310    // Network befragen
00311         printf ("asking network: (%f, %f) = ", normIn(in[0]), normIn(in[1]));
00312    this->ann = fann_create_from_file(this->networkFilename);
00313    if ((calc_out = fann_run(this->ann, normalizedIn)) == false) {
00314       cout <<"ERROR asking network" <<endl;
00315    }
00316 
00317    printf ("[");
00318    
00319    // Normalisierung f�r Output R�ckg�ngig machen
00320    for (unsigned int i=0; i<=this->num_output; i++) {
00321       out[i] = reNormOut((double)calc_out[i]);
00322       printf ("%f, ", calc_out[i]);
00323    }
00324    printf ("]\n");
00325 }
00326 
00328 void Network::clear() {
00329 
00330    DBG();
00331 
00332    // altes Network freigeben
00333    if (this->ann != NULL) fann_destroy(this->ann);
00334 
00335    cout  <<"CREATING NETWORK: " 
00336       <<"connection_rate=" <<connection_rate 
00337       <<", num_layers=" <<num_layers 
00338       <<", num_input=" <<num_input
00339       <<", num_neurons_hidden=" <<num_neurons_hidden
00340       <<", num_output=" <<num_output <<endl;
00341 
00342    // Anzahl der Neuronen auf der Zwischenebene dynamisch bestimmen
00343    hidden_neurons = new unsigned int[this->num_layers];
00344    hidden_neurons[0] = this->num_input;   // Input-Schicht
00345    hidden_neurons[this->num_layers-1] = this->num_output; // Output-Schicht
00346    for (unsigned int i=1; i<=this->num_layers-2; i++) {
00347       hidden_neurons[i] = this->num_neurons_hidden; // Hidden-Schichten
00348    }
00349 
00350    // Networkwerk erzeugen
00351    this->ann = fann_create_standard_array(this->num_layers, hidden_neurons);
00352 
00353    // Zuf�llige Gewichte
00354    cout <<"randomizing weights..." <<endl;
00355    fann_randomize_weights(this->ann, -0.1, 0.1);
00356    
00357    // Network in Datei speichern
00358    fann_save(this->ann, this->networkFilename);
00359 }
00360 
00366 double Network::normIn(double in) {
00367 
00368 
00369    double scalingIn = (maxInputValue-minInputValue);
00370    in -= minInputValue;
00371    in /= scalingIn;
00372 
00373    in = (in*2)-1;  // Bereich -0.9..0.9
00374 
00375    return in;
00376 }
00377 
00383 double Network::normOut(double out) {
00384    double scalingOut = (maxOutputValue-minOutputValue);
00385 
00386    out -= minOutputValue;
00387    out /= scalingOut;
00388 
00389    out = (out*2)-1;  // Bereich -1..1
00390    return out;
00391 }
00392 
00398 double Network::reNormOut(double netOut) {
00399    double scalingOut = (maxOutputValue-minOutputValue);
00400    netOut = (netOut+1)/2;
00401    netOut *= scalingOut;
00402    netOut += minOutputValue;
00403 
00404    return netOut;
00405 }

Erzeugt am Mon Nov 24 15:30:59 2008 für Walking Robot Simulation GUI - API Documentation von  doxygen 1.5.5