我在使用FANN进行函数逼近。我的代码如下:
/* * File: main.cpp * Author: johannsebastian * * Created on November 26, 2013, 8:50 PM */#include "../FANN-2.2.0-Source/src/include/doublefann.h"#include "../FANN-2.2.0-Source/src/include/fann_cpp.h"//#include <doublefann>//#include <fann/fann_cpp>#include <cstdlib>#include <iostream>using namespace std;using namespace FANN;//Remember: fann_type is double!int main(int argc, char** argv) { //create a test network: [1,2,1] MLP neural_net * net = new neural_net; const unsigned int layers[3] = {1, 2, 1}; net->create_standard_array(3, layers); //net->create_standard(num_layers, num_input, num_hidden, num_output); //net->set_learning_rate(0.7f); //net->set_activation_steepness_hidden(0.7); //net->set_activation_steepness_output(0.7); net->set_activation_function_hidden(SIGMOID); net->set_activation_function_output(SIGMOID); net->set_training_algorithm(TRAIN_RPROP); //cout<<net->get_train_error_function() //exit(0); //test the number 2 fann_type * testinput = new fann_type; *testinput = 2; fann_type * testoutput = new fann_type; *testoutput = *(net->run(testinput)); double outputasdouble = (double) *testoutput; cout << "Test output: " << outputasdouble << endl; //make a training set of x->x^2 training_data * squaredata = new training_data; squaredata->read_train_from_file("trainingdata.txt"); //cout<<testinput[0]<<endl; //cout<<testoutput[0]<<endl; cout<<*(squaredata->get_input())[9]<<endl; cout<<*(squaredata->get_output())[9]<<endl; cout<<squaredata->length_train_data(); //scale data fann_type * scaledinput = new fann_type[squaredata->length_train_data()]; fann_type * scaledoutput = new fann_type[squaredata->length_train_data()]; for (unsigned int i = 0; i < squaredata->length_train_data(); i++) { scaledinput[i] = *squaredata->get_input()[i]/200;///100; scaledoutput[i] = *squaredata->get_output()[i]/200;///100; cout<<"In:\t"<<scaledinput[i]<<"\t Out:\t"<<scaledoutput[i]<<endl; } net->train_on_data(*squaredata, 1000000, 100000, 0.001); *testoutput = *(net->run(testinput)); outputasdouble = (double) *testoutput; cout << "Test output: " << outputasdouble << endl; cout << endl << "Easy!"; return 0;}
这是trainingdata.txt的内容:
10 1 11 12 43 94 165 256 367 498 649 8110 100
运行后我得到以下结果:
Test output: 0.4914541010010In: 0.005 Out: 0.005In: 0.01 Out: 0.02In: 0.015 Out: 0.045In: 0.02 Out: 0.08In: 0.025 Out: 0.125In: 0.03 Out: 0.18In: 0.035 Out: 0.245In: 0.04 Out: 0.32In: 0.045 Out: 0.405In: 0.05 Out: 0.5Max epochs 1000000. Desired error: 0.0010000000.Epochs 1. Current error: 2493.7961425781. Bit fail 10.Epochs 100000. Current error: 2457.3000488281. Bit fail 9.Epochs 200000. Current error: 2457.3000488281. Bit fail 9.Epochs 300000. Current error: 2457.3000488281. Bit fail 9.Epochs 400000. Current error: 2457.3000488281. Bit fail 9.Epochs 500000. Current error: 2457.3000488281. Bit fail 9.Epochs 600000. Current error: 2457.3000488281. Bit fail 9.Epochs 700000. Current error: 2457.3000488281. Bit fail 9.Epochs 800000. Current error: 2457.3000488281. Bit fail 9.Epochs 900000. Current error: 2457.3000488281. Bit fail 9.Epochs 1000000. Current error: 2457.3000488281. Bit fail 9.Test output: 1Easy!RUN FINISHED; exit value 0; real time: 9s; user: 10ms; system: 4s
为什么训练没有效果?我之前问了一个类似的问题,有人告诉我应该对神经网络的输入和输出进行缩放。我已经这样做了。是我设置了错误的参数,还是需要更长时间的训练?
回答:
你的隐藏层节点数太少,无法拟合二次函数。我建议你尝试使用10个节点。此外,我推荐你使用一个有趣的小程序,你可以通过设置参数来模拟训练过程。我使用了10个隐藏层节点,并将隐藏层和输出层的激活函数都设置为单极性Sigmoid,拟合效果还不错(但随机化权重可能会导致无法收敛,因此强烈建议增加隐藏层节点数,你可以自己尝试这个小程序并观察一些有趣的点):