I am developing a piece of software that uses FANN, the Fast Artificial Neural Network library.
I have tried after numerous failed attempts at writing my own ANN code to compile a FANN sample program, here the C++ XOR approximation program. Here is the source.
#include "../include/floatfann.h"
#include "../include/fann_cpp.h"
#include <ios>
#include <iostream>
#include <iomanip>
using std::cout;
using std::cerr;
using std::endl;
using std::setw;
using std::left;
using std::right;
using std::showpos;
using std::noshowpos;
// Callback function that simply prints the information to cout
int print_callback(FANN::neural_net &net, FANN::training_data &train,
unsigned int max_epochs, unsigned int epochs_between_reports,
float desired_error, unsigned int epochs, void *user_data)
{
cout << "Epochs " << setw(8) << epochs << ". "
<< "Current Error: " << left << net.get_MSE() << right << endl;
return 0;
}
// Test function that demonstrates usage of the fann C++ wrapper
void xor_test()
{
cout << endl << "XOR test started." << endl;
const float learning_rate = 0.7f;
const unsigned int num_layers = 3;
const unsigned int num_input = 2;
const unsigned int num_hidden = 3;
const unsigned int num_output = 1;
const float desired_error = 0.001f;
const unsigned int max_iterations = 300000;
const unsigned int iterations_between_reports = 10000;
////Make array for create_standard() workaround (prevent "FANN Error 11: Unable to allocate memory.")
const unsigned int num_input_num_hidden_num_output__array[3] = {num_input, num_hidden, num_output};
cout << endl << "Creating network." << endl;
FANN::neural_net net;
// cout<<"Debug 1"<<endl;
//net.create_standard(num_layers, num_input, num_hidden, num_output);//doesn't work
net.create_standard_array(num_layers, num_input_num_hidden_num_output__array);//this might work -- create_standard() workaround
net.set_learning_rate(learning_rate);
net.set_activation_steepness_hidden(1.0);
net.set_activation_steepness_output(1.0);
//Sample Code, changed below
net.set_activation_function_hidden(FANN::SIGMOID_SYMMETRIC_STEPWISE);
net.set_activation_function_output(FANN::SIGMOID_SYMMETRIC_STEPWISE);
//changed above to sigmoid
//net.set_activation_function_hidden(FANN::SIGMOID);
//net.set_activation_function_output(FANN::SIGMOID);
// Set additional properties such as the training algorithm
//net.set_training_algorithm(FANN::TRAIN_QUICKPROP);
// Output network type and parameters
cout << endl << "Network Type : ";
switch (net.get_network_type())
{
case FANN::LAYER://only connected to next layer
cout << "LAYER" << endl;
break;
case FANN::SHORTCUT://connected to all other layers
cout << "SHORTCUT" << endl;
break;
default:
cout << "UNKNOWN" << endl;
break;
}
net.print_parameters();
cout << endl << "Training network." << endl;
FANN::training_data data;
if (data.read_train_from_file("xor.data"))
{
// Initialize and train the network with the data
net.init_weights(data);
cout << "Max Epochs " << setw(8) << max_iterations << ". "
<< "Desired Error: " << left << desired_error << right << endl;
net.set_callback(print_callback, NULL);
net.train_on_data(data, max_iterations,
iterations_between_reports, desired_error);
cout << endl << "Testing network. (not really)" << endl;
//I don't really get this code --- the funny for loop. Whatever. I'll skip it.
for (unsigned int i = 0; i < data.length_train_data(); ++i)
{
// Run the network on the test data
fann_type *calc_out = net.run(data.get_input()[i]);
cout << "XOR test (" << showpos << data.get_input()[i][0] << ", "
<< data.get_input()[i][1] << ") -> " << *calc_out
<< ", should be " << data.get_output()[i][0] << ", "
<< "difference = " << noshowpos
<< fann_abs(*calc_out - data.get_output()[i][0]) << endl;
}
cout << endl << "Saving network." << endl;
// Save the network in floating point and fixed point
net.save("xor_float.net");
unsigned int decimal_point = net.save_to_fixed("xor_fixed.net");
data.save_train_to_fixed("xor_fixed.data", decimal_point);
cout << endl << "XOR test completed." << endl;
}
}
/* Startup function. Synchronizes C and C++ output, calls the test function
and reports any exceptions */
int main(int argc, char **argv)
{
try
{
std::ios::sync_with_stdio(); // Synchronize cout and printf output
xor_test();
}
catch (...)
{
cerr << endl << "Abnormal exception." << endl;
}
return 0;
}
Here's my output.
XOR test started.
Creating network.
Network Type : LAYER
Input layer : 2 neurons, 1 bias
Hidden layer : 3 neurons, 1 bias
Output layer : 1 neurons
Total neurons and biases : 8
Total connections : 13
Connection rate : 1.000
Network type : FANN_NETTYPE_LAYER
Training algorithm : FANN_TRAIN_RPROP
Training error function : FANN_ERRORFUNC_TANH
Training stop function : FANN_STOPFUNC_MSE
Bit fail limit : 0.350
Learning rate : 0.700
Learning momentum : 0.000
Quickprop decay : -0.000100
Quickprop mu : 1.750
RPROP increase factor : 1.200
RPROP decrease factor : 0.500
RPROP delta min : 0.000
RPROP delta max : 50.000
Cascade output change fraction : 0.010000
Cascade candidate change fraction : 0.010000
Cascade output stagnation epochs : 12
Cascade candidate stagnation epochs : 12
Cascade max output epochs : 150
Cascade min output epochs : 50
Cascade max candidate epochs : 150
Cascade min candidate epochs : 50
Cascade weight multiplier : 0.400
Cascade candidate limit :1000.000
Cascade activation functions[0] : FANN_SIGMOID
Cascade activation functions[1] : FANN_SIGMOID_SYMMETRIC
Cascade activation functions[2] : FANN_GAUSSIAN
Cascade activation functions[3] : FANN_GAUSSIAN_SYMMETRIC
Cascade activation functions[4] : FANN_ELLIOT
Cascade activation functions[5] : FANN_ELLIOT_SYMMETRIC
Cascade activation functions[6] : FANN_SIN_SYMMETRIC
Cascade activation functions[7] : FANN_COS_SYMMETRIC
Cascade activation functions[8] : FANN_SIN
Cascade activation functions[9] : FANN_COS
Cascade activation steepnesses[0] : 0.250
Cascade activation steepnesses[1] : 0.500
Cascade activation steepnesses[2] : 0.750
Cascade activation steepnesses[3] : 1.000
Cascade candidate groups : 2
Cascade no. of candidates : 80
Training network.
Max Epochs 300000. Desired Error: 0.001
Epochs 1. Current Error: 0.25
Epochs 10000. Current Error: 0.25
Epochs 20000. Current Error: 0.25
Epochs 30000. Current Error: 0.25
Epochs 40000. Current Error: 0.25
Epochs 50000. Current Error: 0.25
Epochs 60000. Current Error: 0.25
Epochs 70000. Current Error: 0.25
Epochs 80000. Current Error: 0.25
Epochs 90000. Current Error: 0.25
Epochs 100000. Current Error: 0.25
Epochs 110000. Current Error: 0.25
Epochs 120000. Current Error: 0.25
Epochs 130000. Current Error: 0.25
Epochs 140000. Current Error: 0.25
Epochs 150000. Current Error: 0.25
Epochs 160000. Current Error: 0.25
Epochs 170000. Current Error: 0.25
Epochs 180000. Current Error: 0.25
Epochs 190000. Current Error: 0.25
Epochs 200000. Current Error: 0.25
Epochs 210000. Current Error: 0.25
Epochs 220000. Current Error: 0.25
Epochs 230000. Current Error: 0.25
Epochs 240000. Current Error: 0.25
Epochs 250000. Current Error: 0.25
Epochs 260000. Current Error: 0.25
Epochs 270000. Current Error: 0.25
Epochs 280000. Current Error: 0.25
Epochs 290000. Current Error: 0.25
Epochs 300000. Current Error: 0.25
Testing network. (not really)
XOR test (+0, -1.875) -> +0, should be +0, difference = -0
XOR test (+0, -1.875) -> +0, should be +0, difference = -0
XOR test (+0, +1.875) -> +0, should be +0, difference = -0
XOR test (+0, +1.875) -> +0, should be +0, difference = -0
Saving network.
XOR test completed.
The training data (xor.data) is here:
4 2 1
-1 -1
-1
-1 1
1
1 -1
1
1 1
-1
What explains the eerie lack of learning in the ANN? I'm pretty convinced that I have something configured very wrong somewhere, especially given that this is the sample program. ANN experts, any advice?
Apply the FANN patch and make sure that all references to floatfann, doublefann, etc. are congruent.
Related
I have found a simple floating point error and I was wondering if there is a way around it. I'm compiling in Haiku OS. I'm in Haiku r1 Alpha 4
#include <iostream>
#include <cmath>
float P(float PV, float r, int t){
return(r * PV/1-pow((1+r),-t));
}
int main(void){
float PV = 100000;
float r = .005;
int t = 350;
std::cout << "A loan valued at $" << PV << " at a rate of %" << r << " with a payment period of " << t << "months would be $" << P(PV,r,t) << ", per-payment.\n";
return 0;
}
When I run it P(PV,r,t) comes out as 499.834 it should be 500. Though if I set r = 0.06 P is correct and comes out as P = 6000.
Maybe it's a compiler error. I'm using gcc version 2.95.3-haiku-121101.
The code:
return(r * PV/1-pow((1+r),-t));
should be:
return(r * PV/(1-pow((1+r),-t)));
and the expected result is about 605.718, not 500.
I am using OpenCV's implementation of Random Forest algorithm (i.e. RTrees) and am facing a little problem when setting parameters.
I have 5 classes and 3 variables and I want to add weight to classes because the samples sizes for each classes vary a lot.
I took a look at the documentation here and here and it seems that the priors array is the solution, but when I try to give it 5 weights (for my 5 classes) it gives me the following error :
OpenCV Error: One of arguments' values is out of range (Every class weight should be positive) in CvDTreeTrainData::set_data, file /home/sguinard/dev/opencv-2.4.13/modules/ml/src/tree.cpp, line 644
terminate called after throwing an instance of 'cv::Exception'
what(): /home/sguinard/dev/opencv-2.4.13/modules/ml/src/tree.cpp:644: error: (-211) Every class weight should be positive in function CvDTreeTrainData::set_data
If I understand well, it's due to the fact that the priors array have 5 elements. And when I try to give it only 3 elements (as my number of variables) everything works.
According to the documentation, this array should be used to add weight to classes but it actually seems that it is used to add weight to variables...
So, does anyone knows how to add weight to classes on OpenCV's RTrees algorithm ? (I'm working with OpenCV 2.4.13 in c++)
Thanks in advance !
Here is my code :
cv::Mat RandomForest(cv::Mat train_data, cv::Mat response_data, cv::Mat sample_data, int size, int size_predict, float weights[5])
{
#undef CV_TERMCRIT_ITER
#define CV_TERMCRIT_ITER 10
#define ATTRIBUTES_PER_SAMPLE 3
cv::RandomTrees RFTree;
float priors[] = {1,1,1};
CvRTParams RFParams = CvRTParams(25, // max depth
500, // min sample count
0, // regression accuracy: N/A here
false, // compute surrogate split, no missing data
5, // max number of categories (use sub-optimal algorithm for larger numbers)
//priors
weights, // the array of priors (use weights or priors)
true,//false, // calculate variable importance
2, // number of variables randomly selected at node and used to find the best split(s).
100, // max number of trees in the forest
0.01f, // forrest accuracy
CV_TERMCRIT_ITER | CV_TERMCRIT_EPS // termination cirteria
);
cv::Mat varIdx = cv::Mat();
cv::Mat vartype( train_data.cols + 1, 1, CV_8U );
vartype.setTo(cv::Scalar::all(CV_VAR_NUMERICAL));
vartype.at<uchar>(ATTRIBUTES_PER_SAMPLE, 0) = CV_VAR_CATEGORICAL;
cv::Mat sampleIdx = cv::Mat();
cv::Mat missingdatamask = cv::Mat();
for (int i=0; i!=train_data.rows; ++i)
{
for (int j=0; j!=train_data.cols; ++j)
{
if(train_data.at<float>(i,j)<0
|| train_data.at<float>(i,j)>10000
|| !float(train_data.at<float>(i,j)))
{train_data.at<float>(i,j)=0;}
}
}
// Training
std::cout << "Training ....." << std::flush;
bool train = RFTree.train(train_data,
CV_ROW_SAMPLE,//tflag,
response_data,//responses,
varIdx,
sampleIdx,
vartype,
missingdatamask,
RFParams);
if (train){std::cout << " Done" << std::endl;}
else{std::cout << " Failed" << std::endl;return cv::Mat();}
std::cout << "Variable Importance : " << std::endl;
cv::Mat VI = RFTree.getVarImportance();
for (int i=0; i!=VI.cols; ++i){std::cout << VI.at<float>(i) << " - " << std::flush;}
std::cout << std::endl;
std::cout << "Predicting ....." << std::flush;
cv::Mat predict(1,sample_data.rows,CV_32F);
float max = 0;
for (int i=0; i!=sample_data.rows; ++i)
{
predict.at<float>(i) = RFTree.predict(sample_data.row(i));
if (predict.at<float>(i)>max){max=predict.at<float>(i);/*std::cout << predict.at<float>(i) << "-"<< std::flush;*/}
}
// Personnal test due to an error I got (everyone sent to 0)
if (max==0){std::cout << " Failed ... Max value = 0" << std::endl;return cv::Mat();}
std::cout << " Done ... Max value = " << max << std::endl;
return predict;
}
I am currently working on a program that has to implement a 2D-FFT, (for cross correlation). I did a 1D FFT with CUDA which gave me the correct results, i am now trying to implement a 2D version. With few examples and documentation online i find it hard to find out what the error is.
So far i have been using the cuFFT manual only.
Anyway, i have created two 5x5 arrays and filled them with 1's. I have copied them onto the GPU memory and done the forward FFT, multiplied them and then done ifft on the result. This gives me a 5x5 array with values 650. I would expect to get a DC signal with the value 25 in only one slot in the 5x5 array. Instead i get 650 in the entire array.
Furthermore i am not allowed to print out the value of the signal after it has been copied onto the GPU memory. Writing
cout << d_signal[1].x << endl;
Gives me an acces violation. I have done the same thing in other cuda programs, where this has not been an issue. Does it have something to do with how the complex variable works, or is it human error?
If anyone has any pointers to what is going wrong i would greatly appreciate it. Here is the code
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <helper_functions.h>
#include <helper_cuda.h>
#include <ctime>
#include <time.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <cufft.h>
#include <fstream>
using namespace std;
typedef float2 Complex;
__global__ void ComplexMUL(Complex *a, Complex *b)
{
int i = threadIdx.x;
a[i].x = a[i].x * b[i].x - a[i].y*b[i].y;
a[i].y = a[i].x * b[i].y + a[i].y*b[i].x;
}
int main()
{
int N = 5;
int SIZE = N*N;
Complex *fg = new Complex[SIZE];
for (int i = 0; i < SIZE; i++){
fg[i].x = 1;
fg[i].y = 0;
}
Complex *fig = new Complex[SIZE];
for (int i = 0; i < SIZE; i++){
fig[i].x = 1; //
fig[i].y = 0;
}
for (int i = 0; i < 24; i=i+5)
{
cout << fg[i].x << " " << fg[i + 1].x << " " << fg[i + 2].x << " " << fg[i + 3].x << " " << fg[i + 4].x << endl;
}
cout << "----------------" << endl;
for (int i = 0; i < 24; i = i + 5)
{
cout << fig[i].x << " " << fig[i + 1].x << " " << fig[i + 2].x << " " << fig[i + 3].x << " " << fig[i + 4].x << endl;
}
cout << "----------------" << endl;
int mem_size = sizeof(Complex)* SIZE;
cufftComplex *d_signal;
checkCudaErrors(cudaMalloc((void **) &d_signal, mem_size));
checkCudaErrors(cudaMemcpy(d_signal, fg, mem_size, cudaMemcpyHostToDevice));
cufftComplex *d_filter_kernel;
checkCudaErrors(cudaMalloc((void **)&d_filter_kernel, mem_size));
checkCudaErrors(cudaMemcpy(d_filter_kernel, fig, mem_size, cudaMemcpyHostToDevice));
// cout << d_signal[1].x << endl;
// CUFFT plan
cufftHandle plan;
cufftPlan2d(&plan, N, N, CUFFT_C2C);
// Transform signal and filter
printf("Transforming signal cufftExecR2C\n");
cufftExecC2C(plan, (cufftComplex *)d_signal, (cufftComplex *)d_signal, CUFFT_FORWARD);
cufftExecC2C(plan, (cufftComplex *)d_filter_kernel, (cufftComplex *)d_filter_kernel, CUFFT_FORWARD);
printf("Launching Complex multiplication<<< >>>\n");
ComplexMUL <<< 32, 256 >> >(d_signal, d_filter_kernel);
// Transform signal back
printf("Transforming signal back cufftExecC2C\n");
cufftExecC2C(plan, (cufftComplex *)d_signal, (cufftComplex *)d_signal, CUFFT_INVERSE);
Complex *result = new Complex[SIZE];
cudaMemcpy(result, d_signal, sizeof(Complex)*SIZE, cudaMemcpyDeviceToHost);
for (int i = 0; i < SIZE; i=i+5)
{
cout << result[i].x << " " << result[i + 1].x << " " << result[i + 2].x << " " << result[i + 3].x << " " << result[i + 4].x << endl;
}
delete result, fg, fig;
cufftDestroy(plan);
//cufftDestroy(plan2);
cudaFree(d_signal);
cudaFree(d_filter_kernel);
}
The above code gives the following terminal output:
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
----------------
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
----------------
Transforming signal cufftExecR2C
Launching Complex multiplication<<< >>>
Transforming signal back cufftExecC2C
625 625 625 625 625
625 625 625 625 625
625 625 625 625 625
625 625 625 625 625
625 625 625 625 625
This gives me a 5x5 array with values 650 : It reads 625 which is 5555. The convolution algorithm you are using requires a supplemental divide by NN. Indeed, in cufft, there is no normalization coefficient in the forward transform. Hence, your convolution cannot be the simple multiply of the two fields in frequency domain. (some would call it the mathematicians DFT and not the physicists DFT).
Furthermore i am not allowed to print out the value of the signal after it has been copied onto the GPU memory: This is standard CUDA behavior. When allocating memory on the device, the data exists in device memory address space, and cannot be accessed by the CPU without additionnal effort. Search for managed memory, or zerocopy to have data accessible from both sides of the PCI Express (this is discussed in many other posts).
There are several problems here:
You are launching far too many threads for the size of the input arrays in the multiplication kernel, so that should be failing with out-of-bounds memory errors. I am surprised you are not receiving any sort of runtime error.
Your expected solution from the fft/fft - dot product - ifft sequence is, I believe, incorrect. The correct solution would be a 5x5 matrix with 25 in each entry.
As clearly described in the cuFFT documentation, the library performs unnormalised FFTs:
cuFFT performs un-normalized FFTs; that is, performing a forward FFT on an input data set followed by an inverse FFT on the resulting set yields data that is equal to the input, scaled by the number of elements. Scaling either transform by the reciprocal of the size of the data set is left for the user to perform as seen fit.
So by my reckoning, the correct output solution for your code should be a 5x5 matrix with 625 in each entry, which would be normalised to a 5x5 matrix with 25 in each entry, ie. the expected result. I don't understand how the problem at (1) isn't producing different results as the multiplication kernel should be failing.
TLDR; nothing to see here, move along...
Just as an add up to the other things mentioned already: I think your complex multiplication kernel is not doing the right thing. You are overwriting a[i].x in the first line and then use the new value of a[i].x in the second line to calculate a[i].y. I think you need to first generate a backup of a[i].x before you overwrite, something like:
float aReal_bk = a[i].x;
a[i].x = a[i].x * b[i].x - a[i].y * b[i].y;
a[i].y = aReal_bk * b[i].y + a[i].y * b[i].x;
As the title says, does Boost's cpp_dec_float support modulus operations? I'm dealing with money and would like to do some modulus operations to get the number of bills and coins that I need to return. cpp_dec_float seems to be the only arbitrary precision class that supports base 10.
If all you want is coin distribution, can't you just do it without modulo?
Boost multiprecision does define fmod, trunc, mod etc. whenever possible for a backend type; Here's a working demo: Live On Coliru
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/number.hpp>
#include <iostream>
using Num = boost::multiprecision::number<boost::multiprecision::cpp_dec_float<128>>;
int main()
{
Num x("189.5307");
for (Num denom : {
Num("500.00"), Num("200.00"), Num("100.00"),
Num("50.00"), Num("20.00"), Num("10.00"),
Num("5.00"), Num("2.00"), Num("1.00"),
Num("0.50"), Num("0.20"), Num("0.10"),
Num("0.05"), Num("0.02"), Num("0.01"),
})
{
Num count = x/denom;
if (count >= 1)
{
count = trunc(count);
std::cout << count << " * " << std::right << std::setw(6) << denom.str(2, std::ios::fixed) << "\n";
x -= denom * count;
}
}
std::cout << "Remainder: " << x << "\n";
}
I explicitly selected an "invalid" input value (one with excess precision for the denominations) so you can verify it handles them. I have not bothered with the case for negative amounts, but you can figure that out :)
1 * 100.00
1 * 50.00
1 * 20.00
1 * 10.00
1 * 5.00
2 * 2.00
1 * 0.50
1 * 0.02
1 * 0.01
Remainder: 0.0007
Using FANN I can't succeed to run copy&pasted code from FANN's website. I am using FANN version 2.2.0 on Windows 7 and MS Visual Studio 2008. My code for the training program of the XOR example looks like:
#include "floatfann.h"
#include "fann_cpp.h"
#include <ios>
#include <iostream>
#include <iomanip>
#include <string>
using std::cout;
using std::cerr;
using std::endl;
using std::setw;
using std::left;
using std::right;
using std::showpos;
using std::noshowpos;
// Callback function that simply prints the information to cout
int print_callback(FANN::neural_net &net, FANN::training_data &train,
unsigned int max_epochs, unsigned int epochs_between_reports,
float desired_error, unsigned int epochs, void *user_data)
{
cout << "Epochs " << setw(8) << epochs << ". "
<< "Current Error: " << left << net.get_MSE() << right << endl;
return 0;
}
// Test function that demonstrates usage of the fann C++ wrapper
void xor_test()
{
cout << endl << "XOR test started." << endl;
const float learning_rate = 0.7f;
const unsigned int num_layers = 3;
const unsigned int num_input = 2;
const unsigned int num_hidden = 3;
const unsigned int num_output = 1;
const float desired_error = 0.00001f;
const unsigned int max_iterations = 300000;
const unsigned int iterations_between_reports = 1000;
cout << endl << "Creating network." << endl;
FANN::neural_net net;
net.create_standard(num_layers, num_input, num_hidden, num_output);
net.set_learning_rate(learning_rate);
//net.set_activation_steepness_hidden(0.5);
//net.set_activation_steepness_output(0.5);
net.set_activation_function_hidden(FANN::SIGMOID_SYMMETRIC_STEPWISE);
net.set_activation_function_output(FANN::SIGMOID_SYMMETRIC_STEPWISE);
// Set additional properties such as the training algorithm
//net.set_training_algorithm(FANN::TRAIN_QUICKPROP);
// Output network type and parameters
cout << endl << "Network Type : ";
switch (net.get_network_type())
{
case FANN::LAYER:
cout << "LAYER" << endl;
break;
case FANN::SHORTCUT:
cout << "SHORTCUT" << endl;
break;
default:
cout << "UNKNOWN" << endl;
break;
}
net.print_parameters();
cout << endl << "Training network." << endl;
FANN::training_data data;
if (data.read_train_from_file("xor.data"))
{
// ***** MY INPUT
std::string fn;
fn = "xor_read.data";
data.save_train(fn);
fann_type **train_dat;
fann_type **out_dat;
train_dat = data.get_input();
out_dat = data.get_output();
printf("*****************\n");
printf("Printing read data (%d):\n", data.num_input_train_data());
for(unsigned int i = 0; i < data.num_input_train_data(); i++)
{
printf("XOR test (%f,%f) -> %f\n", train_dat[i][0], train_dat[i][1], out_dat[i][0]);
}
printf("*****************\n");
// END: MY INPUT **************
// Initialize and train the network with the data
net.init_weights(data);
cout << "Max Epochs " << setw(8) << max_iterations << ". "
<< "Desired Error: " << left << desired_error << right << endl;
net.set_callback(print_callback, NULL);
net.train_on_data(data, max_iterations,
iterations_between_reports, desired_error);
cout << endl << "Testing network." << endl;
for (unsigned int i = 0; i < data.length_train_data(); ++i)
{
// Run the network on the test data
fann_type *calc_out = net.run(data.get_input()[i]);
cout << "XOR test (" << showpos << data.get_input()[i][0] << ", "
<< data.get_input()[i][2] << ") -> " << *calc_out
<< ", should be " << data.get_output()[i][0] << ", "
<< "difference = " << noshowpos
<< fann_abs(*calc_out - data.get_output()[i][0]) << endl;
}
cout << endl << "Saving network." << endl;
// Save the network in floating point and fixed point
net.save("xor_float.net");
unsigned int decimal_point = net.save_to_fixed("xor_fixed.net");
data.save_train_to_fixed("xor_fixed.data", decimal_point);
cout << endl << "XOR test completed." << endl;
}
}
/* Startup function. Syncronizes C and C++ output, calls the test function
and reports any exceptions */
int main(int argc, char **argv)
{
try
{
std::ios::sync_with_stdio(); // Syncronize cout and printf output
xor_test();
}
catch (...)
{
cerr << endl << "Abnormal exception." << endl;
}
return 0;
}
I commented out :
//net.set_activation_steepness_hidden(0.5);
//net.set_activation_steepness_output(0.5);
otherwise it crashes. The file xor.data :
4 2 1
1 1
-1
-1 -1
-1
-1 1
1
1 -1
1
The output looks odd to me:
XOR test started.
Creating network.
Network Type : LAYER
Input layer : 2 neurons, 1 bias
Hidden layer : 3 neurons, 1 bias
Output layer : 1 neurons
Total neurons and biases : 8
Total connections : 13
Connection rate : 1.000
Network type : FANN_NETTYPE_LAYER
Training algorithm : FANN_TRAIN_RPROP
Training error function : FANN_ERRORFUNC_TANH
Training stop function : FANN_STOPFUNC_MSE
Bit fail limit : 0.350
Learning rate : 0.700
Learning momentum : 0.000
Quickprop decay : -0.000100
Quickprop mu : 1.750
RPROP increase factor : 1.200
RPROP decrease factor : 0.500
RPROP delta min : 0.000
RPROP delta max : 50.000
Cascade output change fraction : 0.010000
Cascade candidate change fraction : 0.010000
Cascade output stagnation epochs : 12
Cascade candidate stagnation epochs : 12
Cascade max output epochs : 150
Cascade min output epochs : 50
Cascade max candidate epochs : 150
Cascade min candidate epochs : 50
Cascade weight multiplier : 0.400
Cascade candidate limit :1000.000
Cascade activation functions[0] : FANN_SIGMOID
Cascade activation functions[1] : FANN_SIGMOID_SYMMETRIC
Cascade activation functions[2] : FANN_GAUSSIAN
Cascade activation functions[3] : FANN_GAUSSIAN_SYMMETRIC
Cascade activation functions[4] : FANN_ELLIOT
Cascade activation functions[5] : FANN_ELLIOT_SYMMETRIC
Cascade activation functions[6] : FANN_SIN_SYMMETRIC
Cascade activation functions[7] : FANN_COS_SYMMETRIC
Cascade activation functions[8] : FANN_SIN
Cascade activation functions[9] : FANN_COS
Cascade activation steepnesses[0] : 0.250
Cascade activation steepnesses[1] : 0.500
Cascade activation steepnesses[2] : 0.750
Cascade activation steepnesses[3] : 1.000
Cascade candidate groups : 2
Cascade no. of candidates : 80
Training network.
*****************
Printing read data (2):
XOR test (0.000000,1.875000) -> 0.000000
XOR test (0.000000,-1.875000) -> 0.000000
*****************
Max Epochs 300000. Desired Error: 1e-005
Epochs 1. Current Error: 0.260461
Epochs 36. Current Error: 7.15071e-006
Testing network.
XOR test (+0, +1.875) -> +5.295e-035, should be +0, difference = 5.295e-035
XOR test (+0, -1.875) -> +0, should be +0, difference = -0
XOR test (+0, -1.875) -> +0, should be +0, difference = -0
XOR test (+0, +1.875) -> +0, should be +0, difference = -0
Saving network.
XOR test completed.
The output after Testing network. looks like :
the training data as well as the test data are interpreted to be (0, +/- 1.875), as you can see in directly below the lines after Printing read data (2) and Testing network..
The (2) after Printing read data is taken from data.num_input_train_data() and my expectation would be to get a (4) since I have four sets of training data.
The "target" seems to be always "0" (see output), although the training data is never zero, but always +/- 1.
A different question has the same odd output hinting towards the training data being interpreted as (0,+/-1.875)->0.0. With this example training (like in my XOR example) also seemed to be successful, but the execution of the ANN (even on the data used for training) returned seemingly random numbers.
I found the answer in FANN - I get incorrect results (near 0) at simply task. It says when including "doublefann.h" one should also link the doublefann lib. This obviously holds for "floatfann.h" and the floatfann lib as well.