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
00074 if (dataFile != NULL) {
00075
00076 rewind(dataFile) ;
00077
00078
00079 fprintf (dataFile, "%d %d %d", this->dataCount, this->num_input, this->num_output);
00080 fclose(dataFile);
00081
00082 dataFile = NULL;
00083 }
00084
00085
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
00095 fann_set_train_error_function(this->ann, FANN_ERRORFUNC_LINEAR);
00096
00097
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
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
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
00191 DBG();
00192 if (this->ann != NULL) fann_destroy(this->ann);
00193 }
00194
00196 void Network::createNewTrainingDataFile() {
00197
00198 DBG();
00199
00200 if (dataFile != NULL) fclose(dataFile);
00201
00202
00203 dataFile = fopen(this->dataFilename, "w+");
00204 fprintf (dataFile, " ");
00205
00206
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
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
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
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
00251 this->dataCount=0;
00252
00253
00254 this->ann = NULL;
00255 }
00256
00262 void Network::addTrainingData(double in[], double out[]) {
00263
00264 char printString[200];
00265
00266
00267 sprintf (printString, "adding traindata: in[%f(%f)", in[0], normIn(in[0]));
00268 fprintf (dataFile, "\n%.30f", normIn(in[0]));
00269
00270
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
00277 sprintf (printString, "%s], out[%f(%f)", printString, out[0], normOut(out[0]));
00278 fprintf (dataFile, "\n%.30f", normOut(out[0]));
00279
00280
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
00287 sprintf (printString, "%s]\n", printString);
00288
00289
00290 dataCount++;
00291
00292
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
00306 for (unsigned int i=0; i<this->num_input; i++) {
00307 normalizedIn[i] = normIn(in[i]);
00308 }
00309
00310
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
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
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
00343 hidden_neurons = new unsigned int[this->num_layers];
00344 hidden_neurons[0] = this->num_input;
00345 hidden_neurons[this->num_layers-1] = this->num_output;
00346 for (unsigned int i=1; i<=this->num_layers-2; i++) {
00347 hidden_neurons[i] = this->num_neurons_hidden;
00348 }
00349
00350
00351 this->ann = fann_create_standard_array(this->num_layers, hidden_neurons);
00352
00353
00354 cout <<"randomizing weights..." <<endl;
00355 fann_randomize_weights(this->ann, -0.1, 0.1);
00356
00357
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;
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;
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 }