This example shows how FANN creates a neural network that learns to solve the XOR problem.
Operating system: Ubuntu 10.04 LTS Lucid Lynx
IDE: Qt Creator 2.0.0
Project type: GUI application
Libraries used:
- FANN: version 1.2.0-1
- STL: from GCC, shipped with Qt Creator 2.0.0
#------------------------------------------------- # # Project created by QtCreator 2010-08-12T16:54:00 # #------------------------------------------------- QT += core QT -= gui LIBS += -L/usr/local/lib -lfann TARGET = CppFannExample2 CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp
#include <algorithm> #include <cassert> #include <fstream> #include <iostream> #include <iterator> #include <string> #include <vector> #include <floatfann.h> //From http://www.richelbilderbeek.nl/CppFileExists.htm bool FileExists(const std::string& filename) { std::fstream f; f.open(filename.c_str(),std::ios::in); return f.is_open(); } //From http://www.richelbilderbeek.nl/CppFileToVector.htm const std::vector<std::string> FileToVector(const std::string& fileName) { assert(FileExists(fileName)==true); std::vector<std::string> myVector; std::ifstream in(fileName.c_str()); std::string myString; for (int i=0; !in.eof(); ++i) { std::getline(in,myString); myVector.push_back(myString); } return myVector; } //From http://www.richelbilderbeek.nl/CppCoutContainer.htm template <class Container> void CoutContainer(const Container& c) { std::copy(c.begin(),c.end(), std::ostream_iterator<typename Container::value_type>(std::cout,"\n")); } //From http://www.richelbilderbeek.nl/CppSaveContainer.htm template <class Container> void SaveContainer(const Container& c, const std::string& filename) { std::ofstream f(filename.c_str()); std::copy(c.begin(),c.end(),std::ostream_iterator<typename Container::value_type>(f,"\n")); } void CreateXorProblemTrainingFile(const std::string& filename) { std::vector<std::string> s; //First line: // - 4: number of training sets // - 2: number of inputs // - 1: number of outputs s.push_back("4 2 1"); //Second line: if the two inputs are 1.0 and 1.0.... s.push_back("1.0 1.0"); //Third line: the XOR network should return a -1.0 s.push_back("-1.0"); //Fourth line: if the two inputs are -1.0 and -1.0.... s.push_back("-1.0 -1.0"); //Fifth line: the XOR network should return a -1.0 s.push_back("-1.0"); //And so one... s.push_back("-1.0 1.0"); //In s.push_back( "1.0" ); //Expected out s.push_back("1.0 -1.0"); //In s.push_back( "1.0" ); //Expected out SaveContainer(s,filename); } int main() { const unsigned int num_input = 2; const unsigned int num_hidden = 3; const unsigned int num_output = 1; std::vector<unsigned int> layer_sizes; layer_sizes.push_back(num_input); layer_sizes.push_back(num_hidden); layer_sizes.push_back(num_output); const std::string file_input = "XorProblemTrainingSet.txt"; const std::string file_output = "Output.txt"; const double desired_error = 0.00001; const unsigned int max_epochs = 100000; const unsigned int epochs_between_reports = 100; const double learning_rate = 0.05; fann * const n = fann_create_shortcut_array(learning_rate, layer_sizes.size(),&layer_sizes[0]); fann_set_activation_function_hidden(n, FANN_SIGMOID_SYMMETRIC); fann_set_activation_function_output(n, FANN_SIGMOID_SYMMETRIC); CreateXorProblemTrainingFile(file_input); //FANN is not const-correct... fann_train_on_file(n,const_cast<char*>(file_input.c_str()), max_epochs, epochs_between_reports, desired_error); fann_save(n,file_output.c_str()); { std::cout << "Showing output file: " << '\n'; const std::vector<std::string> v = FileToVector(file_output); CoutContainer(v); } fann_destroy(n); }
Note that screen output differs between runs, because the random number generator is initialized randomly.
Max epochs 100000. Desired error: 0.0000100000 Epochs 1. Current error: 0.2508820593 Epochs 100. Current error: 0.1011718586 Epochs 200. Current error: 0.0171126649 Epochs 300. Current error: 0.0025421339 Epochs 400. Current error: 0.0002089983 Epochs 470. Current error: 0.0000094494 Showing output file: FANN_FLO_1.1 3 0.050000 1.000000 1 5 5 5.00000000000000000000e-01 5.00000000000000000000e-01 3 4 2 0 0 0 3 3 3 0 6 0 (0 4.18440580368041992188e+00) (1 4.06674432754516601562e+00) (2 3.74954080581665039062e+00) (0 4.17614841461181640625e+00) (1 4.05507659912109375000e+00) (2 3.76885223388671875000e+00) (0 -2.67808938026428222656e+00) (1 -2.79252290725708007812e+00) (2 1.96936237812042236328e+00) (0 -2.83534169197082519531e+00) (1 -2.52798914909362792969e+00) (3 4.44841718673706054688e+00) (4 4.85006999969482421875e+00) (5 4.21606016159057617188e+00) (6 -5.98922777175903320312e+00)